INET Framework for OMNeT++/OMNEST
IPv6FragBuf Class Reference

#include <IPv6FragBuf.h>

List of all members.

Classes

struct  DatagramBuffer
struct  Key

Public Member Functions

 IPv6FragBuf ()
 ~IPv6FragBuf ()
void init (ICMPv6 *icmp)
IPv6DatagramaddFragment (IPv6Datagram *datagram, IPv6FragmentHeader *fh, simtime_t now)
void purgeStaleFragments (simtime_t lastupdate)

Protected Types

typedef std::map< Key,
DatagramBuffer
Buffers

Protected Attributes

Buffers bufs
ICMPv6icmpModule

Detailed Description

Reassembly buffer for fragmented IPv6 datagrams.


Member Typedef Documentation

typedef std::map<Key,DatagramBuffer> IPv6FragBuf::Buffers [protected]

Constructor & Destructor Documentation

IPv6FragBuf::IPv6FragBuf ( )

Ctor.

{
    icmpModule = NULL;
}
IPv6FragBuf::~IPv6FragBuf ( )

Dtor.

{
}

Member Function Documentation

IPv6Datagram * IPv6FragBuf::addFragment ( IPv6Datagram datagram,
IPv6FragmentHeader *  fh,
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.

{
    // find datagram buffer
    Key key;
    key.id = fh->getIdentification();
    key.src = datagram->getSrcAddress();
    key.dest = datagram->getDestAddress();

    Buffers::iterator i = bufs.find(key);

    DatagramBuffer *buf = NULL;
    if (i==bufs.end())
    {
        // this is the first fragment of that datagram, create reassembly buffer for it
        buf = &bufs[key];
        buf->datagram = NULL;
    }
    else
    {
        // use existing buffer
        buf = &(i->second);
    }

    // add fragment into reassembly buffer
    // FIXME next lines aren't correct: check 4.5 of RFC 2460 regarding Unfragmentable part, Fragmentable part, etc
    int bytes = datagram->getByteLength() - datagram->calculateHeaderByteLength();
    bool isComplete = buf->buf.addFragment(fh->getFragmentOffset(),
                                           fh->getFragmentOffset() + bytes,
                                           !fh->getMoreFragments());

    // store datagram. Only one fragment carries the actual modelled
    // content (getEncapsulatedPacket()), other (empty) ones are only
    // preserved so that we can send them in ICMP if reassembly times out.
    if (datagram->getEncapsulatedPacket())
    {
        delete buf->datagram;
        buf->datagram = datagram;
    }
    else
    {
        delete datagram;
    }

    // do we have the complete datagram?
    if (isComplete)
    {
        // datagram complete: deallocate buffer and return complete datagram
        IPv6Datagram *ret = buf->datagram;
        ret->setByteLength(ret->calculateHeaderByteLength()+buf->buf.getTotalLength()); // FIXME cf with 4.5 of RFC 2460
        //TODO: remove extension header IPv6FragmentHeader; maybe not here but when datagram gets inserted into the reassembly buffer --Andras
        bufs.erase(i);
        return ret;
    }
    else
    {
        // there are still missing fragments
        buf->lastupdate = now;
        return NULL;
    }
}
void IPv6FragBuf::init ( ICMPv6 icmp)

Initialize fragmentation buffer. ICMP module is needed for sending TIME_EXCEEDED ICMP message in purgeStaleFragments().

Referenced by IPv6::initialize().

{
    icmpModule = icmp;
}
void IPv6FragBuf::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.

{
    // this method shouldn't be called too often because iteration on
    // an std::map is *very* slow...

    ASSERT(icmpModule);

    for (Buffers::iterator i=bufs.begin(); i!=bufs.end(); )
    {
        // if too old, remove it
        DatagramBuffer& buf = i->second;
        if (buf.lastupdate < lastupdate)
        {
            // send ICMP error
            EV << "datagram fragment timed out in reassembly buffer, sending ICMP_TIME_EXCEEDED\n";
            icmpModule->sendErrorMessage(buf.datagram, ICMPv6_TIME_EXCEEDED, 0);

            // delete
            Buffers::iterator oldi = i++;
            bufs.erase(oldi);
        }
        else
        {
            ++i;
        }
    }
}

Member Data Documentation


The documentation for this class was generated from the following files: