INET Framework for OMNeT++/OMNEST
inet::IPv6FragBuf Class Reference

Reassembly buffer for fragmented IPv6 datagrams. More...

#include <IPv6FragBuf.h>

Classes

struct  DatagramBuffer
 
struct  Key
 

Public Member Functions

 IPv6FragBuf ()
 Ctor. More...
 
 ~IPv6FragBuf ()
 Dtor. More...
 
void init (ICMPv6 *icmp)
 Initialize fragmentation buffer. More...
 
IPv6DatagramaddFragment (IPv6Datagram *datagram, IPv6FragmentHeader *fh, simtime_t now)
 Takes a fragment and inserts it into the reassembly buffer. More...
 
void 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. More...
 

Protected Types

typedef std::map< Key, DatagramBufferBuffers
 

Protected Attributes

Buffers bufs
 
ICMPv6icmpModule = nullptr
 

Detailed Description

Reassembly buffer for fragmented IPv6 datagrams.

Member Typedef Documentation

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

Constructor & Destructor Documentation

inet::IPv6FragBuf::IPv6FragBuf ( )

Ctor.

32 {
33  icmpModule = nullptr;
34 }
ICMPv6 * icmpModule
Definition: IPv6FragBuf.h:71
inet::IPv6FragBuf::~IPv6FragBuf ( )

Dtor.

37 {
38  for (auto & elem : bufs) {
39  delete elem.second.datagram;
40  }
41 }
Buffers bufs
Definition: IPv6FragBuf.h:68

Member Function Documentation

IPv6Datagram * inet::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 nullptr.

Referenced by inet::IPv6::localDeliver().

49 {
50  // find datagram buffer
51  Key key;
52  key.id = fh->getIdentification();
53  key.src = datagram->getSrcAddress();
54  key.dest = datagram->getDestAddress();
55 
56  auto i = bufs.find(key);
57 
58  DatagramBuffer *buf = nullptr;
59  if (i == bufs.end()) {
60  // this is the first fragment of that datagram, create reassembly buffer for it
61  buf = &bufs[key];
62  buf->datagram = nullptr;
63  buf->createdAt = now;
64  }
65  else {
66  // use existing buffer
67  buf = &(i->second);
68  }
69 
70  int fragmentLength = datagram->calculateFragmentLength();
71  unsigned short offset = fh->getFragmentOffset();
72  bool moreFragments = fh->getMoreFragments();
73 
74  // RFC 2460 4.5:
75  // If the length of a fragment, as derived from the fragment packet's
76  // Payload Length field, is not a multiple of 8 octets and the M flag
77  // of that fragment is 1, then that fragment must be discarded and an
78  // ICMP Parameter Problem, Code 0, message should be sent to the
79  // source of the fragment, pointing to the Payload Length field of
80  // the fragment packet.
81  if (moreFragments && (fragmentLength % 8) != 0) {
83  return nullptr;
84  }
85 
86  // RFC 2460 4.5:
87  // If the length and offset of a fragment are such that the Payload
88  // Length of the packet reassembled from that fragment would exceed
89  // 65,535 octets, then that fragment must be discarded and an ICMP
90  // Parameter Problem, Code 0, message should be sent to the source of
91  // the fragment, pointing to the Fragment Offset field of the
92  // fragment packet.
93  if (offset + fragmentLength > 65535) {
95  return nullptr;
96  }
97 
98  // add fragment to buffer
99  bool isComplete = buf->buf.addFragment(offset,
100  offset + fragmentLength,
101  !moreFragments);
102 
103  // Store the first fragment. The first fragment contains the whole
104  // encapsulated payload, and extension headers of the
105  // original datagram.
106  if (offset == 0) {
107  delete buf->datagram;
108  buf->datagram = datagram;
109  }
110  else {
111  delete datagram;
112  }
113 
114  // do we have the complete datagram?
115  if (isComplete) {
116  // datagram complete: deallocate buffer and return complete datagram
117  IPv6Datagram *ret = buf->datagram;
118  if (!ret)
119  throw cRuntimeError("Model error: completed datagram without datagram pointer.");
120  ret->removeExtensionHeader(IP_PROT_IPv6EXT_FRAGMENT);
121  ret->setByteLength(ret->calculateUnfragmentableHeaderByteLength() + buf->buf.getTotalLength());
122  bufs.erase(i);
123  return ret;
124  }
125  else {
126  // there are still missing fragments
127  return nullptr;
128  }
129 }
Definition: ICMPv6Message_m.h:74
Definition: ICMPv6Message_m.h:148
Buffers bufs
Definition: IPv6FragBuf.h:68
void * Key
Definition: Macho.h:325
Definition: IPProtocolId_m.h:97
ICMPv6 * icmpModule
Definition: IPv6FragBuf.h:71
virtual void sendErrorMessage(IPv6Datagram *datagram, ICMPv6Type type, int code)
This method can be called from other modules to send an ICMPv6 error packet.
Definition: ICMPv6.cc:188
void inet::IPv6FragBuf::init ( ICMPv6 icmp)

Initialize fragmentation buffer.

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

Referenced by inet::IPv6::initialize().

44 {
45  icmpModule = icmp;
46 }
ICMPv6 * icmpModule
Definition: IPv6FragBuf.h:71
void inet::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.

Referenced by inet::IPv6::localDeliver().

143 {
144  // this method shouldn't be called too often because iteration on
145  // an std::map is *very* slow...
146 
147  ASSERT(icmpModule);
148 
149  for (auto i = bufs.begin(); i != bufs.end(); ) {
150  // if too old, remove it
151  DatagramBuffer& buf = i->second;
152  if (buf.createdAt < lastupdate) {
153  if (buf.datagram) {
154  // send ICMP error
155  EV_INFO << "datagram fragment timed out in reassembly buffer, sending ICMP_TIME_EXCEEDED\n";
157  }
158 
159  // delete
160  auto oldi = i++;
161  bufs.erase(oldi);
162  }
163  else {
164  ++i;
165  }
166  }
167 }
Buffers bufs
Definition: IPv6FragBuf.h:68
ICMPv6 * icmpModule
Definition: IPv6FragBuf.h:71
Definition: ICMPv6Message_m.h:73
virtual void sendErrorMessage(IPv6Datagram *datagram, ICMPv6Type type, int code)
This method can be called from other modules to send an ICMPv6 error packet.
Definition: ICMPv6.cc:188

Member Data Documentation

Buffers inet::IPv6FragBuf::bufs
protected
ICMPv6* inet::IPv6FragBuf::icmpModule = nullptr
protected

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