IPv6FragBuf.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2005 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 
00019 #include <omnetpp.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include "IPv6FragBuf.h"
00023 #include "ICMPv6.h"
00024 #include "ICMPv6Message_m.h"  // for TIME_EXCEEDED
00025 #include "IPv6Datagram.h"
00026 #include "IPv6ExtensionHeaders_m.h"
00027 
00028 
00029 IPv6FragBuf::IPv6FragBuf()
00030 {
00031     icmpModule = NULL;
00032 }
00033 
00034 IPv6FragBuf::~IPv6FragBuf()
00035 {
00036 }
00037 
00038 void IPv6FragBuf::init(ICMPv6 *icmp)
00039 {
00040     icmpModule = icmp;
00041 }
00042 
00043 IPv6Datagram *IPv6FragBuf::addFragment(IPv6Datagram *datagram, IPv6FragmentHeader *fh, simtime_t now)
00044 {
00045     // find datagram buffer
00046     Key key;
00047     key.id = fh->getIdentification();
00048     key.src = datagram->getSrcAddress();
00049     key.dest = datagram->getDestAddress();
00050 
00051     Buffers::iterator i = bufs.find(key);
00052 
00053     DatagramBuffer *buf = NULL;
00054     if (i==bufs.end())
00055     {
00056         // this is the first fragment of that datagram, create reassembly buffer for it
00057         buf = &bufs[key];
00058         buf->datagram = NULL;
00059     }
00060     else
00061     {
00062         // use existing buffer
00063         buf = &(i->second);
00064     }
00065 
00066     // add fragment into reassembly buffer
00067     // FIXME next lines aren't correct: check 4.5 of RFC 2460 regarding Unfragmentable part, Fragmentable part, etc
00068     int bytes = datagram->getByteLength() - datagram->calculateHeaderByteLength();
00069     bool isComplete = buf->buf.addFragment(fh->getFragmentOffset(),
00070                                            fh->getFragmentOffset() + bytes,
00071                                            !fh->getMoreFragments());
00072 
00073     // store datagram. Only one fragment carries the actual modelled
00074     // content (getEncapsulatedMsg()), other (empty) ones are only
00075     // preserved so that we can send them in ICMP if reassembly times out.
00076     if (datagram->getEncapsulatedMsg())
00077     {
00078         delete buf->datagram;
00079         buf->datagram = datagram;
00080     }
00081     else
00082     {
00083         delete datagram;
00084     }
00085 
00086     // do we have the complete datagram?
00087     if (isComplete)
00088     {
00089         // datagram complete: deallocate buffer and return complete datagram
00090         IPv6Datagram *ret = buf->datagram;
00091         ret->setByteLength(ret->calculateHeaderByteLength()+buf->buf.getTotalLength()); // FIXME cf with 4.5 of RFC 2460
00092         //TODO: remove extension header IPv6FragmentHeader; maybe not here but when datagram gets inserted into the reassembly buffer --Andras
00093         bufs.erase(i);
00094         return ret;
00095     }
00096     else
00097     {
00098         // there are still missing fragments
00099         buf->lastupdate = now;
00100         return NULL;
00101     }
00102 }
00103 
00104 void IPv6FragBuf::purgeStaleFragments(simtime_t lastupdate)
00105 {
00106     // this method shouldn't be called too often because iteration on
00107     // an std::map is *very* slow...
00108 
00109     ASSERT(icmpModule);
00110 
00111     for (Buffers::iterator i=bufs.begin(); i!=bufs.end(); )
00112     {
00113         // if too old, remove it
00114         DatagramBuffer& buf = i->second;
00115         if (buf.lastupdate < lastupdate)
00116         {
00117             // send ICMP error
00118             EV << "datagram fragment timed out in reassembly buffer, sending ICMP_TIME_EXCEEDED\n";
00119             icmpModule->sendErrorMessage(buf.datagram, ICMPv6_TIME_EXCEEDED, 0);
00120 
00121             // delete
00122             Buffers::iterator oldi = i++;
00123             bufs.erase(oldi);
00124         }
00125         else
00126         {
00127             ++i;
00128         }
00129     }
00130 }
00131