ipv4_frag.c
Go to the documentation of this file.
1 /**
2  * @file ipv4_frag.c
3  * @brief IPv4 fragmentation and reassembly
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * The Internet Protocol (IP) implements datagram fragmentation, so that
30  * packets may be formed that can pass through a link with a smaller maximum
31  * transmission unit (MTU) than the original datagram size. Refer to the
32  * following RFCs for complete details:
33  * - RFC 791: Internet Protocol specification
34  * - RFC 815: IP datagram reassembly algorithms
35  *
36  * @author Oryx Embedded SARL (www.oryx-embedded.com)
37  * @version 1.9.8
38  **/
39 
40 //Switch to the appropriate trace level
41 #define TRACE_LEVEL IPV4_TRACE_LEVEL
42 
43 //Dependencies
44 #include "core/net.h"
45 #include "core/ip.h"
46 #include "ipv4/ipv4.h"
47 #include "ipv4/ipv4_frag.h"
48 #include "ipv4/icmp.h"
49 #include "mibs/mib2_module.h"
50 #include "mibs/ip_mib_module.h"
51 #include "debug.h"
52 
53 //Check TCP/IP stack configuration
54 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
55 
56 //Tick counter to handle periodic operations
58 
59 
60 /**
61  * @brief Fragment an IPv4 datagram into smaller packets
62  * @param[in] interface Underlying network interface
63  * @param[in] pseudoHeader IPv4 pseudo header
64  * @param[in] id Fragment identification
65  * @param[in] payload Multi-part buffer containing the payload
66  * @param[in] payloadOffset Offset to the first payload byte
67  * @param[in] ancillary Additional options passed to the stack along with
68  * the packet
69  * @return Error code
70  **/
71 
73  Ipv4PseudoHeader *pseudoHeader, uint16_t id, const NetBuffer *payload,
74  size_t payloadOffset, NetTxAncillary *ancillary)
75 {
76  error_t error;
77  size_t offset;
78  size_t length;
79  size_t payloadLen;
80  size_t fragmentOffset;
81  size_t maxFragmentSize;
82  NetBuffer *fragment;
83 
84  //Number of IP datagrams that would require fragmentation in order to be
85  //transmitted
86  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragReqds, 1);
87  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragReqds, 1);
88 
89  //Retrieve the length of the payload
90  payloadLen = netBufferGetLength(payload) - payloadOffset;
91 
92  //Allocate a memory buffer to hold IP fragments
93  fragment = ipAllocBuffer(0, &fragmentOffset);
94  //Failed to allocate memory?
95  if(!fragment)
96  return ERROR_OUT_OF_MEMORY;
97 
98  //Determine the maximum payload size for fragmented packets
99  maxFragmentSize = interface->ipv4Context.linkMtu - sizeof(Ipv4Header);
100  //The size shall be a multiple of 8-byte blocks
101  maxFragmentSize -= (maxFragmentSize % 8);
102 
103  //Initialize error code
104  error = NO_ERROR;
105 
106  //Split the payload into multiple IP fragments
107  for(offset = 0; offset < payloadLen; offset += length)
108  {
109  //Flush the contents of the fragment
110  error = netBufferSetLength(fragment, fragmentOffset);
111  //Sanity check
112  if(error)
113  break;
114 
115  //Process the last fragment?
116  if((payloadLen - offset) <= maxFragmentSize)
117  {
118  //Size of the current fragment
119  length = payloadLen - offset;
120  //Copy fragment data
121  netBufferConcat(fragment, payload, payloadOffset + offset, length);
122 
123  //Do not set the MF flag for the last fragment
124  error = ipv4SendPacket(interface, pseudoHeader, id, offset / 8,
125  fragment, fragmentOffset, ancillary);
126  }
127  else
128  {
129  //Size of the current fragment (must be a multiple of 8-byte blocks)
130  length = maxFragmentSize;
131  //Copy fragment data
132  netBufferConcat(fragment, payload, payloadOffset + offset, length);
133 
134  //Fragmented packets must have the MF flag set
135  error = ipv4SendPacket(interface, pseudoHeader, id, IPV4_FLAG_MF |
136  (offset / 8), fragment, fragmentOffset, ancillary);
137  }
138 
139  //Failed to send current IP packet?
140  if(error)
141  break;
142 
143  //Number of IP datagram fragments that have been generated as a result
144  //of fragmentation at this entity
145  MIB2_INC_COUNTER32(ipGroup.ipFragCreates, 1);
146  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragCreates, 1);
147  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragCreates, 1);
148  }
149 
150  //Check status code
151  if(error)
152  {
153  //Number of IP datagrams that have been discarded because they needed
154  //to be fragmented at this entity but could not be
155  MIB2_INC_COUNTER32(ipGroup.ipFragFails, 1);
156  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragFails, 1);
157  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragFails, 1);
158  }
159  else
160  {
161  //Number of IP datagrams that have been successfully fragmented at this
162  //entity
163  MIB2_INC_COUNTER32(ipGroup.ipFragOKs, 1);
164  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsOutFragOKs, 1);
165  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsOutFragOKs, 1);
166  }
167 
168  //Free previously allocated memory
169  netBufferFree(fragment);
170  //Return status code
171  return error;
172 }
173 
174 
175 /**
176  * @brief IPv4 datagram reassembly algorithm
177  * @param[in] interface Underlying network interface
178  * @param[in] packet Pointer to the IPv4 fragmented packet
179  * @param[in] length Packet length including header and payload
180  * @param[in] ancillary Additional options passed to the stack along with
181  * the packet
182  **/
183 
184 void ipv4ReassembleDatagram(NetInterface *interface, const Ipv4Header *packet,
185  size_t length, NetRxAncillary *ancillary)
186 {
187  error_t error;
188  uint16_t offset;
189  uint16_t dataFirst;
190  uint16_t dataLast;
191  Ipv4FragDesc *frag;
192  Ipv4HoleDesc *hole;
193  Ipv4HoleDesc *prevHole;
194 
195  //Number of IP fragments received which needed to be reassembled
196  MIB2_INC_COUNTER32(ipGroup.ipReasmReqds, 1);
197  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmReqds, 1);
198  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmReqds, 1);
199 
200  //Get the length of the payload
201  length -= packet->headerLength * 4;
202  //Convert the fragment offset from network byte order
203  offset = ntohs(packet->fragmentOffset);
204 
205  //Every fragment except the last must contain a multiple of 8 bytes of data
206  if((offset & IPV4_FLAG_MF) && (length % 8))
207  {
208  //Number of failures detected by the IP reassembly algorithm
209  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
210  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
211  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
212 
213  //Drop the incoming fragment
214  return;
215  }
216 
217  //Calculate the index of the first byte
218  dataFirst = (offset & IPV4_OFFSET_MASK) * 8;
219  //Calculate the index immediately following the last byte
220  dataLast = dataFirst + (uint16_t) length;
221 
222  //Search for a matching IP datagram being reassembled
223  frag = ipv4SearchFragQueue(interface, packet);
224 
225  //No matching entry in the reassembly queue?
226  if(frag == NULL)
227  {
228  //Number of failures detected by the IP reassembly algorithm
229  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
230  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
231  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
232 
233  //Drop the incoming fragment
234  return;
235  }
236 
237  //The very first fragment requires special handling
238  if(!(offset & IPV4_OFFSET_MASK))
239  {
240  //Calculate the length of the IP header including options
241  frag->headerLength = packet->headerLength * 4;
242 
243  //Enforce the size of the reconstructed datagram
244  if((frag->headerLength + frag->dataLen) > IPV4_MAX_FRAG_DATAGRAM_SIZE)
245  {
246  //Number of failures detected by the IP reassembly algorithm
247  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
248  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
249  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
250 
251  //Drop the reconstructed datagram
252  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
253  //Exit immediately
254  return;
255  }
256 
257  //Make sure the IP header entirely fits in the first chunk
258  if(frag->headerLength > frag->buffer.chunk[0].size)
259  {
260  //Number of failures detected by the IP reassembly algorithm
261  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
262  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
263  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
264 
265  //Drop the reconstructed datagram
266  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
267  //Exit immediately
268  return;
269  }
270 
271  //Fix the length of the first chunk
272  frag->buffer.chunk[0].length = (uint16_t) frag->headerLength;
273  //Always take the IP header from the first fragment
274  netBufferWrite((NetBuffer *) &frag->buffer, 0, packet, frag->headerLength);
275  }
276 
277  //It may be necessary to increase the size of the buffer...
278  if(dataLast > frag->dataLen)
279  {
280  //Enforce the size of the reconstructed datagram
281  if((frag->headerLength + dataLast) > IPV4_MAX_FRAG_DATAGRAM_SIZE)
282  {
283  //Number of failures detected by the IP reassembly algorithm
284  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
285  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
286  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
287 
288  //Drop the reconstructed datagram
289  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
290  //Exit immediately
291  return;
292  }
293 
294  //Adjust the size of the reconstructed datagram
295  error = netBufferSetLength((NetBuffer *) &frag->buffer,
296  frag->headerLength + dataLast + sizeof(Ipv4HoleDesc));
297 
298  //Any error to report?
299  if(error)
300  {
301  //Number of failures detected by the IP reassembly algorithm
302  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
303  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
304  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
305 
306  //Drop the reconstructed datagram
307  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
308  //Exit immediately
309  return;
310  }
311 
312  //Actual length of the payload
313  frag->dataLen = dataLast;
314  }
315 
316  //Select the first hole descriptor from the list
317  hole = ipv4FindHole(frag, frag->firstHole);
318  //Keep track of the previous hole in the list
319  prevHole = NULL;
320 
321  //Iterate through the hole descriptors
322  while(hole != NULL)
323  {
324  //Save lower and upper boundaries for later use
325  uint16_t holeFirst = hole->first;
326  uint16_t holeLast = hole->last;
327 
328  //Check whether the newly arrived fragment interacts with this hole in
329  //some way
330  if(dataFirst < holeLast && dataLast > holeFirst)
331  {
332  //The current descriptor is no longer valid. We will destroy it, and
333  //in the next two steps, we will determine whether or not it is
334  //necessary to create any new hole descriptors
335  if(prevHole != NULL)
336  prevHole->next = hole->next;
337  else
338  frag->firstHole = hole->next;
339 
340  //Is there still a hole at the beginning of the segment?
341  if(dataFirst > holeFirst)
342  {
343  //Create a new entry that describes this hole
344  hole = ipv4FindHole(frag, holeFirst);
345  hole->first = holeFirst;
346  hole->last = dataFirst;
347 
348  //Insert the newly created entry into the hole descriptor list
349  if(prevHole != NULL)
350  {
351  hole->next = prevHole->next;
352  prevHole->next = hole->first;
353  }
354  else
355  {
356  hole->next = frag->firstHole;
357  frag->firstHole = hole->first;
358  }
359 
360  //Always keep track of the previous hole
361  prevHole = hole;
362  }
363 
364  //Is there still a hole at the end of the segment?
365  if(dataLast < holeLast && (offset & IPV4_FLAG_MF))
366  {
367  //Create a new entry that describes this hole
368  hole = ipv4FindHole(frag, dataLast);
369  hole->first = dataLast;
370  hole->last = holeLast;
371 
372  //Insert the newly created entry into the hole descriptor list
373  if(prevHole != NULL)
374  {
375  hole->next = prevHole->next;
376  prevHole->next = hole->first;
377  }
378  else
379  {
380  hole->next = frag->firstHole;
381  frag->firstHole = hole->first;
382  }
383 
384  //Always keep track of the previous hole
385  prevHole = hole;
386  }
387  }
388  else
389  {
390  //The newly arrived fragment does not interact with the current hole
391  prevHole = hole;
392  }
393 
394  //Select the next hole descriptor from the list
395  hole = ipv4FindHole(frag, prevHole ? prevHole->next : frag->firstHole);
396  }
397 
398  //Copy data from the fragment to the reassembly buffer
399  netBufferWrite((NetBuffer *) &frag->buffer,
400  frag->headerLength + dataFirst, IPV4_DATA(packet), length);
401 
402  //Dump hole descriptor list
403  ipv4DumpHoleList(frag);
404 
405  //If the hole descriptor list is empty, the reassembly process is now
406  //complete
407  if(!ipv4FindHole(frag, frag->firstHole))
408  {
409  //Discard the extra hole descriptor that follows the reconstructed
410  //datagram
411  error = netBufferSetLength((NetBuffer *) &frag->buffer,
412  frag->headerLength + frag->dataLen);
413 
414  //Check status code
415  if(error)
416  {
417  //Number of failures detected by the IP reassembly algorithm
418  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
419  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
420  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
421  }
422  else
423  {
424  //Point to the IP header
425  Ipv4Header *datagram = netBufferAt((NetBuffer *) &frag->buffer, 0);
426 
427  //Fix IP header
428  datagram->totalLength = htons(frag->headerLength + frag->dataLen);
429  datagram->fragmentOffset = 0;
430  datagram->headerChecksum = 0;
431 
432  //Number of IP datagrams successfully reassembled
433  MIB2_INC_COUNTER32(ipGroup.ipReasmOKs, 1);
434  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmOKs, 1);
435  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmOKs, 1);
436 
437  //Pass the original IPv4 datagram to the higher protocol layer
438  ipv4ProcessDatagram(interface, (NetBuffer *) &frag->buffer, ancillary);
439  }
440 
441  //Release previously allocated memory
442  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
443  }
444 }
445 
446 
447 /**
448  * @brief Fragment reassembly timeout handler
449  *
450  * This routine must be periodically called by the TCP/IP stack to
451  * handle IPv4 fragment reassembly timeout
452  *
453  * @param[in] interface Underlying network interface
454  **/
455 
456 void ipv4FragTick(NetInterface *interface)
457 {
458  error_t error;
459  uint_t i;
460  systime_t time;
461  Ipv4HoleDesc *hole;
462 
463  //Get current time
464  time = osGetSystemTime();
465 
466  //Loop through the reassembly queue
467  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
468  {
469  //Point to the current entry in the reassembly queue
470  Ipv4FragDesc *frag = &interface->ipv4Context.fragQueue[i];
471 
472  //Make sure the entry is currently in use
473  if(frag->buffer.chunkCount > 0)
474  {
475  //If the timer runs out, the partially-reassembled datagram must be
476  //discarded and ICMP Time Exceeded message sent to the source host
477  if((time - frag->timestamp) >= IPV4_FRAG_TIME_TO_LIVE)
478  {
479  //Debug message
480  TRACE_INFO("IPv4 fragment reassembly timeout...\r\n");
481  //Dump IP header contents for debugging purpose
483 
484  //Number of failures detected by the IP reassembly algorithm
485  MIB2_INC_COUNTER32(ipGroup.ipReasmFails, 1);
486  IP_MIB_INC_COUNTER32(ipv4SystemStats.ipSystemStatsReasmFails, 1);
487  IP_MIB_INC_COUNTER32(ipv4IfStatsTable[interface->index].ipIfStatsReasmFails, 1);
488 
489  //Point to the first hole descriptor
490  hole = ipv4FindHole(frag, frag->firstHole);
491 
492  //Make sure the fragment zero has been received before sending an
493  //ICMP message
494  if(hole != NULL && hole->first > 0)
495  {
496  //Fix the size of the reconstructed datagram
497  error = netBufferSetLength((NetBuffer *) &frag->buffer,
498  frag->headerLength + hole->first);
499 
500  //Check status code
501  if(!error)
502  {
503  //Send an ICMP Time Exceeded message
506  }
507  }
508 
509  //Drop the partially reconstructed datagram
510  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
511  }
512  }
513  }
514 }
515 
516 
517 /**
518  * @brief Search for a matching datagram in the reassembly queue
519  * @param[in] interface Underlying network interface
520  * @param[in] packet Incoming IPv4 packet
521  * @return Matching fragment descriptor
522  **/
523 
525  const Ipv4Header *packet)
526 {
527  error_t error;
528  uint_t i;
529  Ipv4Header *datagram;
530  Ipv4FragDesc *frag;
531  Ipv4HoleDesc *hole;
532 
533  //Search for a matching IP datagram being reassembled
534  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
535  {
536  //Point to the current entry in the reassembly queue
537  frag = &interface->ipv4Context.fragQueue[i];
538 
539  //Check whether the current entry is used?
540  if(frag->buffer.chunkCount > 0)
541  {
542  //Point to the corresponding datagram
543  datagram = netBufferAt((NetBuffer *) &frag->buffer, 0);
544 
545  //Check source and destination addresses
546  if(datagram->srcAddr != packet->srcAddr)
547  continue;
548  if(datagram->destAddr != packet->destAddr)
549  continue;
550  //Compare identification and protocol fields
551  if(datagram->identification != packet->identification)
552  continue;
553  if(datagram->protocol != packet->protocol)
554  continue;
555 
556  //A matching entry has been found in the reassembly queue
557  return frag;
558  }
559  }
560 
561  //If the current packet does not match an existing entry in the reassembly
562  //queue, then create a new entry
563  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
564  {
565  //Point to the current entry in the reassembly queue
566  frag = &interface->ipv4Context.fragQueue[i];
567 
568  //The current entry is free?
569  if(!frag->buffer.chunkCount)
570  {
571  //Number of chunks that comprise the reassembly buffer
572  frag->buffer.maxChunkCount = arraysize(frag->buffer.chunk);
573 
574  //Allocate sufficient memory to hold the IPv4 header and
575  //the first hole descriptor
576  error = netBufferSetLength((NetBuffer *) &frag->buffer,
578 
579  //Failed to allocate memory?
580  if(error)
581  {
582  //Clean up side effects
583  netBufferSetLength((NetBuffer *) &frag->buffer, 0);
584  //Exit immediately
585  return NULL;
586  }
587 
588  //Initial length of the reconstructed datagram
589  frag->headerLength = packet->headerLength * 4;
590  frag->dataLen = 0;
591 
592  //Fix the length of the first chunk
593  frag->buffer.chunk[0].length = (uint16_t) frag->headerLength;
594  //Copy IPv4 header from the incoming fragment
595  netBufferWrite((NetBuffer *) &frag->buffer, 0, packet, frag->headerLength);
596 
597  //Save current time
598  frag->timestamp = osGetSystemTime();
599  //Create a new entry in the hole descriptor list
600  frag->firstHole = 0;
601 
602  //Point to first hole descriptor
603  hole = ipv4FindHole(frag, frag->firstHole);
604  //The entry describes the datagram as being completely missing
605  hole->first = 0;
606  hole->last = IPV4_INFINITY;
607  hole->next = IPV4_INFINITY;
608 
609  //Dump hole descriptor list
610  ipv4DumpHoleList(frag);
611 
612  //Return the matching fragment descriptor
613  return frag;
614  }
615  }
616 
617  //The reassembly queue is full
618  return NULL;
619 }
620 
621 
622 /**
623  * @brief Flush IPv4 reassembly queue
624  * @param[in] interface Underlying network interface
625  **/
626 
628 {
629  uint_t i;
630 
631  //Loop through the reassembly queue
632  for(i = 0; i < IPV4_MAX_FRAG_DATAGRAMS; i++)
633  {
634  //Drop any partially reconstructed datagram
635  netBufferSetLength((NetBuffer *) &interface->ipv4Context.fragQueue[i].buffer, 0);
636  }
637 }
638 
639 
640 /**
641  * @brief Retrieve hole descriptor
642  * @param[in] frag IPv4 fragment descriptor
643  * @param[in] offset Offset of the hole
644  * @return A pointer to the hole descriptor is returned if the specified
645  * offset is valid. Otherwise NULL is returned
646  **/
647 
648 Ipv4HoleDesc *ipv4FindHole(Ipv4FragDesc *frag, uint16_t offset)
649 {
650  //Return a pointer to the hole descriptor
651  return netBufferAt((NetBuffer *) &frag->buffer, frag->headerLength + offset);
652 }
653 
654 
655 /**
656  * @brief Dump hole descriptor list
657  * @param[in] frag IPv4 fragment descriptor
658  **/
659 
661 {
662 //Check debugging level
663 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
664  Ipv4HoleDesc *hole;
665 
666  //Debug message
667  TRACE_DEBUG("Hole descriptor list:\r\n");
668  //Select the first hole descriptor from the list
669  hole = ipv4FindHole(frag, frag->firstHole);
670 
671  //Loop through the hole descriptor list
672  while(hole != NULL)
673  {
674  //Display current hole
675  TRACE_DEBUG(" %" PRIu16 " - %" PRIu16 "\r\n", hole->first, hole->last);
676  //Select the next hole descriptor from the list
677  hole = ipv4FindHole(frag, hole->next);
678  }
679 #endif
680 }
681 
682 #endif
systime_t timestamp
Time at which the first fragment was received.
Definition: ipv4_frag.h:125
uint8_t length
Definition: coap_common.h:190
#define htons(value)
Definition: cpu_endian.h:413
MIB-II module.
systime_t ipv4FragTickCounter
Definition: ipv4_frag.c:57
ChunkDesc chunk[N(IPV4_MAX_FRAG_DATAGRAM_SIZE)+1]
Definition: ipv4_frag.h:115
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:638
#define Ipv4Header
Definition: ipv4.h:36
void ipv4FragTick(NetInterface *interface)
Fragment reassembly timeout handler.
Definition: ipv4_frag.c:456
void ipv4FlushFragQueue(NetInterface *interface)
Flush IPv4 reassembly queue.
Definition: ipv4_frag.c:627
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define IPV4_MAX_FRAG_DATAGRAM_SIZE
Definition: ipv4_frag.h:62
void ipv4DumpHoleList(Ipv4FragDesc *frag)
Dump hole descriptor list.
Definition: ipv4_frag.c:660
error_t netBufferConcat(NetBuffer *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Concatenate two multi-part buffers.
Definition: net_mem.c:442
void ipv4DumpHeader(const Ipv4Header *ipHeader)
Dump IPv4 header for debugging purpose.
Definition: ipv4.c:1489
#define NET_MEM_POOL_BUFFER_SIZE
Definition: net_mem.h:55
uint16_t length
Definition: net_mem.h:79
uint16_t firstHole
Index of the first hole.
Definition: ipv4_frag.h:128
ICMP (Internet Control Message Protocol)
error_t
Error codes.
Definition: error.h:42
size_t dataLen
Length of the payload.
Definition: ipv4_frag.h:127
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
void * address
Definition: net_mem.h:78
void ipv4ProcessDatagram(NetInterface *interface, const NetBuffer *buffer, NetRxAncillary *ancillary)
Incoming IPv4 datagram processing.
Definition: ipv4.c:739
void ipv4ReassembleDatagram(NetInterface *interface, const Ipv4Header *packet, size_t length, NetRxAncillary *ancillary)
IPv4 datagram reassembly algorithm.
Definition: ipv4_frag.c:184
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
#define IPV4_DATA(packet)
Definition: ipv4.h:94
#define NetTxAncillary
Definition: net_misc.h:36
#define Ipv4PseudoHeader
Definition: ipv4.h:39
#define TRACE_INFO(...)
Definition: debug.h:95
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
error_t ipv4SendPacket(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, uint16_t fragId, size_t fragOffset, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 packet.
Definition: ipv4.c:958
#define IPV4_FRAG_TIME_TO_LIVE
Definition: ipv4_frag.h:69
size_t headerLength
Length of the header.
Definition: ipv4_frag.h:126
#define ntohs(value)
Definition: cpu_endian.h:421
Fragmented packet descriptor.
Definition: ipv4_frag.h:123
#define IPV4_MAX_FRAG_DATAGRAMS
Definition: ipv4_frag.h:55
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint32_t time
IPv4 fragmentation and reassembly.
IPv4 and IPv6 common routines.
IP MIB module.
#define MIB2_INC_COUNTER32(name, value)
Definition: mib2_module.h:156
Ipv4FragDesc * ipv4SearchFragQueue(NetInterface *interface, const Ipv4Header *packet)
Search for a matching datagram in the reassembly queue.
Definition: ipv4_frag.c:524
error_t netBufferSetLength(NetBuffer *buffer, size_t length)
Adjust the length of a multi-part buffer.
Definition: net_mem.c:320
size_t netBufferWrite(NetBuffer *dest, size_t destOffset, const void *src, size_t length)
Write data to a multi-part buffer.
Definition: net_mem.c:619
error_t ipv4FragmentDatagram(NetInterface *interface, Ipv4PseudoHeader *pseudoHeader, uint16_t id, const NetBuffer *payload, size_t payloadOffset, NetTxAncillary *ancillary)
Fragment an IPv4 datagram into smaller packets.
Definition: ipv4_frag.c:72
Ipv4HoleDesc * ipv4FindHole(Ipv4FragDesc *frag, uint16_t offset)
Retrieve hole descriptor.
Definition: ipv4_frag.c:648
#define IPV4_INFINITY
Definition: ipv4_frag.h:75
IPv4 (Internet Protocol Version 4)
uint8_t payloadLen
Definition: ipv6.h:343
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
__start_packed struct @69 Ipv4HoleDesc
Hole descriptor.
Ipv4ReassemblyBuffer buffer
Buffer containing the reassembled datagram.
Definition: ipv4_frag.h:129
uint32_t systime_t
Definition: compiler_port.h:46
error_t icmpSendErrorMessage(NetInterface *interface, uint8_t type, uint8_t code, uint8_t parameter, const NetBuffer *ipPacket, size_t ipPacketOffset)
Send an ICMP Error message.
Definition: icmp.c:269
Success.
Definition: error.h:44
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:70
systime_t osGetSystemTime(void)
Retrieve system time.