#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 | ( | ) |
void IPFragBuf::init | ( | ICMP * | icmp | ) |
Initialize fragmentation buffer. ICMP module is needed for sending TIME_EXCEEDED ICMP message in purgeStaleFragments().
Referenced by IP::initialize().
00037 { 00038 icmpModule = icmp; 00039 }
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.
Referenced by IP::reassembleAndDeliver().
00042 { 00043 // find datagram buffer 00044 Key key; 00045 key.id = datagram->getIdentification(); 00046 key.src = datagram->getSrcAddress(); 00047 key.dest = datagram->getDestAddress(); 00048 00049 Buffers::iterator i = bufs.find(key); 00050 00051 DatagramBuffer *buf = NULL; 00052 if (i==bufs.end()) 00053 { 00054 // this is the first fragment of that datagram, create reassembly buffer for it 00055 buf = &bufs[key]; 00056 buf->datagram = NULL; 00057 } 00058 else 00059 { 00060 // use existing buffer 00061 buf = &(i->second); 00062 } 00063 00064 // add fragment into reassembly buffer 00065 int bytes = datagram->getByteLength() - datagram->getHeaderLength(); 00066 bool isComplete = buf->buf.addFragment(datagram->getFragmentOffset(), 00067 datagram->getFragmentOffset() + bytes, 00068 !datagram->getMoreFragments()); 00069 00070 // store datagram. Only one fragment carries the actual modelled 00071 // content (getEncapsulatedMsg()), other (empty) ones are only 00072 // preserved so that we can send them in ICMP if reassembly times out. 00073 if (datagram->getEncapsulatedMsg()) 00074 { 00075 delete buf->datagram; 00076 buf->datagram = datagram; 00077 } 00078 else 00079 { 00080 delete datagram; 00081 } 00082 00083 // do we have the complete datagram? 00084 if (isComplete) 00085 { 00086 // datagram complete: deallocate buffer and return complete datagram 00087 IPDatagram *ret = buf->datagram; 00088 ret->setByteLength(ret->getHeaderLength()+buf->buf.getTotalLength()); 00089 bufs.erase(i); 00090 return ret; 00091 } 00092 else 00093 { 00094 // there are still missing fragments 00095 buf->lastupdate = now; 00096 return NULL; 00097 } 00098 }
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.
Referenced by IP::reassembleAndDeliver().
00101 { 00102 // this method shouldn't be called too often because iteration on 00103 // an std::map is *very* slow... 00104 00105 ASSERT(icmpModule); 00106 00107 for (Buffers::iterator i=bufs.begin(); i!=bufs.end(); ) 00108 { 00109 // if too old, remove it 00110 DatagramBuffer& buf = i->second; 00111 if (buf.lastupdate < lastupdate) 00112 { 00113 // send ICMP error 00114 EV << "datagram fragment timed out in reassembly buffer, sending ICMP_TIME_EXCEEDED\n"; 00115 icmpModule->sendErrorMessage(buf.datagram, ICMP_TIME_EXCEEDED, 0); 00116 00117 // delete 00118 Buffers::iterator oldi = i++; 00119 bufs.erase(oldi); 00120 } 00121 else 00122 { 00123 ++i; 00124 } 00125 } 00126 }
Buffers IPFragBuf::bufs [protected] |
Referenced by addFragment(), and purgeStaleFragments().
ICMP* IPFragBuf::icmpModule [protected] |
Referenced by init(), IPFragBuf(), and purgeStaleFragments().