%description:
Test the IP fragmentation reassembly buffer (IPv4FragBuf class)

%includes:
#include <vector>
#include "inet/networklayer/ipv4/IPv4FragBuf.h"
#include "inet/networklayer/ipv4/IPv4Datagram.h"

%global:

using namespace inet;

struct Frag
{
    ushort id;
    long src;
    long dest;
    ushort offset;
    ushort bytes;
    bool islast;
};

typedef std::vector<Frag> FragVector;

bool insertFragment(IPv4FragBuf& fragbuf, Frag& f)
{
    IPv4Datagram *frag = new IPv4Datagram();
    frag->setIdentification(f.id);
    frag->setSrcAddress(IPv4Address(f.src));
    frag->setDestAddress(IPv4Address(f.dest));
    frag->setFragmentOffset(f.offset);
    frag->setMoreFragments(!f.islast);
    frag->setHeaderLength(24);
    frag->setByteLength(24+f.bytes);

    IPv4Datagram *dgram = fragbuf.addFragment(frag, 0);
    delete dgram;
    return dgram!=NULL;
}

%activity:

// create a number of fragmented datagrams
FragVector v;
Frag f;
int numdatagrams = 0;
for (f.src=1024; f.src<1026; f.src++) {
    for (f.dest=2048; f.dest<2050; f.dest++) {
        for (f.id=0; f.id<80; f.id++) {
            numdatagrams++;
            int n = f.id/10+2;
            for (int i=0; i<n; i++) {
                f.offset=i*100;
                f.bytes=100;
                f.islast = (i==n-1);
                v.push_back(f);
            }
        }
    }
}

// dump
for (int j=0; j<v.size(); j++)
{
    Frag& f = v[j];
    //EV << f.src << ">" << f.dest << ":" << f.id << " " << f.offset << " (" << f.bytes << ") " << (f.islast?"LAST":"") << "\n";
}

EV << numdatagrams << " datagrams in " << v.size() << " fragments\n";

// try assemble them, fragments in original order
IPv4FragBuf fragbuf1;
int i, num;
for (i=0, num=0; i<v.size(); i++)
    if (insertFragment(fragbuf1, v[i]))
        num++;
EV << "assembled in original order: " << num << "\n";

// try assemble fragments in reverse order
IPv4FragBuf fragbuf2;
for (i=v.size()-1, num=0; i>=0; i--)
    if (insertFragment(fragbuf2, v[i]))
        num++;
EV << "assembled in reverse order: " << num << "\n";

// shuffle fragments
for (i=0; i<100000; i++)
{
    int a = intrand(v.size());
    int b = intrand(v.size());
    f = v[a]; v[a] = v[b]; v[b] = f;
}

// try assemble shuffled fragments
IPv4FragBuf fragbuf3;
for (i=0, num=0; i<v.size(); i++)
    if (insertFragment(fragbuf3, v[i]))
        num++;
EV << "assembled in random order: " << num << "\n";


%contains: stdout
320 datagrams in 1760 fragments
assembled in original order: 320
assembled in reverse order: 320
assembled in random order: 320

