#include <IPFragBuf.h>
Public Member Functions | |
IPFragBuf () | |
~IPFragBuf () | |
void | init (ICMP *icmp) |
IPDatagram * | addFragment (IPDatagram *datagram, simtime_t now) |
void | purgeStaleFragments (simtime_t lastupdate) |
Protected Types | |
typedef std::map< Key, DatagramBuffer > | Buffers |
Protected Attributes | |
Buffers | bufs |
ICMP * | icmpModule |
Classes | |
struct | DatagramBuffer |
struct | Key |
typedef std::map<Key,DatagramBuffer> IPFragBuf::Buffers [protected] |
IPFragBuf::IPFragBuf | ( | ) |
IPDatagram * IPFragBuf::addFragment | ( | IPDatagram * | datagram, | |
simtime_t | now | |||
) |
Takes a fragment and inserts it into the reassembly buffer. If this fragment completes a datagram, the full reassembled datagram is returned, otherwise NULL.
00043 { 00044 // find datagram buffer 00045 Key key; 00046 key.id = datagram->identification(); 00047 key.src = datagram->srcAddress(); 00048 key.dest = datagram->destAddress(); 00049 00050 Buffers::iterator i = bufs.find(key); 00051 00052 DatagramBuffer *buf = NULL; 00053 if (i==bufs.end()) 00054 { 00055 // this is the first fragment of that datagram, create reassembly buffer for it 00056 buf = &bufs[key]; 00057 buf->datagram = NULL; 00058 } 00059 else 00060 { 00061 // use existing buffer 00062 buf = &(i->second); 00063 } 00064 00065 // add fragment into reassembly buffer 00066 int bytes = datagram->byteLength() - datagram->headerLength(); 00067 bool isComplete = buf->buf.addFragment(datagram->fragmentOffset(), 00068 datagram->fragmentOffset() + bytes, 00069 !datagram->moreFragments()); 00070 00071 // store datagram. Only one fragment carries the actual modelled 00072 // content (encapsulatedMsg()), other (empty) ones are only 00073 // preserved so that we can send them in ICMP if reassembly times out. 00074 if (datagram->encapsulatedMsg()) 00075 { 00076 delete buf->datagram; 00077 buf->datagram = datagram; 00078 } 00079 else 00080 { 00081 delete datagram; 00082 } 00083 00084 // do we have the complete datagram? 00085 if (isComplete) 00086 { 00087 // datagram complete: deallocate buffer and return complete datagram 00088 IPDatagram *ret = buf->datagram; 00089 ret->setByteLength(ret->headerLength()+buf->buf.totalLength()); 00090 bufs.erase(i); 00091 return ret; 00092 } 00093 else 00094 { 00095 // there are still missing fragments 00096 buf->lastupdate = now; 00097 return NULL; 00098 } 00099 }
void IPFragBuf::init | ( | ICMP * | icmp | ) |
Initialize fragmentation buffer. ICMP module is needed for sending TIME_EXCEEDED ICMP message in purgeStaleFragments().
00038 { 00039 icmpModule = icmp; 00040 }
void IPFragBuf::purgeStaleFragments | ( | simtime_t | lastupdate | ) |
Throws out all fragments which are incomplete and their last update (last fragment arrival) was before "lastupdate", and sends ICMP TIME EXCEEDED message about them.
Timeout should be between 60 seconds and 120 seconds (RFC1122). This method should be called more frequently, maybe every 10..30 seconds or so.
00102 { 00103 // this method shouldn't be called too often because iteration on 00104 // an std::map is *very* slow... 00105 00106 ASSERT(icmpModule); 00107 00108 for (Buffers::iterator i=bufs.begin(); i!=bufs.end(); ) 00109 { 00110 // if too old, remove it 00111 DatagramBuffer& buf = i->second; 00112 if (buf.lastupdate < lastupdate) 00113 { 00114 // send ICMP error 00115 EV << "datagram fragment timed out in reassembly buffer, sending ICMP_TIME_EXCEEDED\n"; 00116 icmpModule->sendErrorMessage(buf.datagram, ICMP_TIME_EXCEEDED, 0); 00117 00118 // delete 00119 Buffers::iterator oldi = i++; 00120 bufs.erase(oldi); 00121 } 00122 else 00123 { 00124 ++i; 00125 } 00126 } 00127 }
Buffers IPFragBuf::bufs [protected] |
ICMP* IPFragBuf::icmpModule [protected] |