This is the IPv4 packet segmentation and reassembly implementation.
#include "lwip/opt.h"
#include "lwip/ip_frag.h"
#include "lwip/def.h"
#include "lwip/inet_chksum.h"
#include "lwip/netif.h"
#include "lwip/snmp.h"
#include "lwip/stats.h"
#include "lwip/icmp.h"
#include <string.h>
Data Structures | |
struct | ip_reass_helper |
This is a helper struct which holds the starting offset and the ending offset of this fragment to easily chain the fragments. More... | |
Macros | |
#define | IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) |
#define | IP_REASS_CHECK_OVERLAP 1 |
The IP reassembly code currently has the following limitations: More... | |
#define | IP_REASS_FLAG_LASTFRAG 0x01 |
#define | IP_REASS_FREE_OLDEST 1 |
Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is full (IP_REASS_MAX_PBUFS pbufs are enqueued). More... | |
Functions | |
err_t | ip_frag (struct pbuf *p, struct netif *netif, ip_addr_t *dest) |
Fragment an IP datagram if too large for the netif. More... | |
struct pbuf * | ip_reass (struct pbuf *p) |
Reassembles incoming IP fragments into an IP datagram. More... | |
static int | ip_reass_chain_frag_into_datagram_and_validate (struct ip_reassdata *ipr, struct pbuf *new_p) |
Chain a new pbuf into the pbuf list that composes the datagram. More... | |
static void | ip_reass_dequeue_datagram (struct ip_reassdata *ipr, struct ip_reassdata *prev) |
Dequeues a datagram from the datagram queue. More... | |
static struct ip_reassdata * | ip_reass_enqueue_new_datagram (struct ip_hdr *fraghdr, int clen) |
Enqueues a new fragment into the fragment queue. More... | |
static int | ip_reass_free_complete_datagram (struct ip_reassdata *ipr, struct ip_reassdata *prev) |
Free a datagram (struct ip_reassdata) and all its pbufs. More... | |
static int | ip_reass_remove_oldest_datagram (struct ip_hdr *fraghdr, int pbufs_needed) |
Free the oldest datagram to make room for enqueueing new fragments. More... | |
void | ip_reass_tmr (void) |
Reassembly timer base function for both NO_SYS == 0 and 1 (!). More... | |
Variables | |
static u16_t | ip_reass_pbufcount |
PACK_STRUCT_BEGIN struct ip_reass_helper | PACK_STRUCT_STRUCT |
static struct ip_reassdata * | reassdatagrams |
#define IP_ADDRESSES_AND_ID_MATCH | ( | iphdrA, | |
iphdrB | |||
) |
Referenced by ip_reass(), and ip_reass_remove_oldest_datagram().
#define IP_REASS_CHECK_OVERLAP 1 |
The IP reassembly code currently has the following limitations:
Setting this to 0, you can turn off checking the fragments for overlapping regions. The code gets a little smaller. Only use this if you know that overlapping won't occur on your network!
#define IP_REASS_FLAG_LASTFRAG 0x01 |
Referenced by ip_reass(), and ip_reass_chain_frag_into_datagram_and_validate().
#define IP_REASS_FREE_OLDEST 1 |
Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is full (IP_REASS_MAX_PBUFS pbufs are enqueued).
The code gets a little smaller. Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA is set to 1, so one datagram can be reassembled at a time, only.
Fragment an IP datagram if too large for the netif.
Chop the datagram in MTU sized chunks and send them in order by using a fixed size static memory buffer (PBUF_REF) or point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF).
p | ip packet to send |
netif | the netif on which to send |
dest | destination ip address to which to send |
References ERR_MEM, ERR_OK, htons, if(), inet_chksum(), ip_frag(), IP_HLEN, IP_MF, IP_OFFMASK, IP_REASS_DEBUG, IPFRAG_STATS_INC, IPH_CHKSUM_SET, IPH_LEN_SET, IPH_OFFSET, IPH_OFFSET_SET, iphdr, pbuf::len, LWIP_ASSERT, LWIP_DEBUGF, LWIP_MEM_ALIGN, netif::mtu, pbuf::next, ntohs, NULL, netif::output, pbuf::payload, pbuf_alloc(), pbuf_cat(), pbuf_chain(), pbuf_copy_partial(), pbuf_free(), pbuf_header(), PBUF_IP, PBUF_LINK, PBUF_RAM, PBUF_RAW, pbuf_realloc(), PBUF_REF, pbuf_ref(), snmp_inc_ipfragcreates, snmp_inc_ipfragoks, and pbuf::tot_len.
Referenced by ip_frag(), ip_reass(), and ip_reass_enqueue_new_datagram().
Reassembles incoming IP fragments into an IP datagram.
p | points to a pbuf chain of the fragment |
References ip_reassdata::datagram_len, ip_reassdata::flags, htons, if(), inet_chksum(), IP_ADDRESSES_AND_ID_MATCH, ip_frag(), IP_HLEN, IP_MF, IP_OFFMASK, ip_reass_chain_frag_into_datagram_and_validate(), IP_REASS_DEBUG, ip_reass_dequeue_datagram(), ip_reass_enqueue_new_datagram(), IP_REASS_FLAG_LASTFRAG, ip_reass_pbufcount, ip_reass_remove_oldest_datagram(), IPFRAG_STATS_INC, IPH_CHKSUM_SET, IPH_HL, IPH_ID, IPH_LEN, IPH_LEN_SET, IPH_OFFSET, IPH_OFFSET_SET, ip_reassdata::iphdr, LWIP_DEBUGF, ip_reassdata::next, ntohs, NULL, ip_reassdata::p, pbuf::payload, pbuf_cat(), pbuf_clen(), pbuf_free(), pbuf_header(), PP_NTOHS, S16_F, snmp_inc_ipreasmreqds, and X16_F.
Referenced by ip_input().
|
static |
Chain a new pbuf into the pbuf list that composes the datagram.
The pbuf list will grow over time as new pbufs are rx. Also checks that the datagram passes basic continuity checks (if the last fragment was received at least once).
root_p | points to the 'root' pbuf for the current datagram being assembled. |
new_p | points to the pbuf for the current fragment |
References ip_reassdata::datagram_len, ip_reassdata::flags, if(), IP_HLEN, IP_OFFMASK, IP_REASS_FLAG_LASTFRAG, ip_reass_pbufcount, IPH_HL, IPH_LEN, IPH_OFFSET, pbuf::len, LWIP_ASSERT, ntohs, NULL, ip_reassdata::p, pbuf::payload, pbuf_clen(), and pbuf_free().
Referenced by ip_reass().
|
static |
Dequeues a datagram from the datagram queue.
Doesn't deallocate the pbufs.
ipr | points to the queue entry to dequeue |
References LWIP_ASSERT, memp_free(), ip_reassdata::next, and NULL.
Referenced by ip_reass(), and ip_reass_free_complete_datagram().
|
static |
Enqueues a new fragment into the fragment queue.
fraghdr | points to the new fragments IP hdr |
clen | number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) |
References ip_frag(), IP_HLEN, IP_REASS_DEBUG, ip_reass_remove_oldest_datagram(), IPFRAG_STATS_INC, ip_reassdata::iphdr, LWIP_DEBUGF, memp_malloc(), ip_reassdata::next, NULL, reassdatagrams, and ip_reassdata::timer.
Referenced by ip_reass().
|
static |
Free a datagram (struct ip_reassdata) and all its pbufs.
Updates the total count of enqueued pbufs (ip_reass_pbufcount), SNMP counters and sends an ICMP time exceeded packet.
ipr | datagram to free |
prev | the previous datagram in the linked list |
References ICMP_TE_FRAG, icmp_time_exceeded(), if(), IP_HLEN, ip_reass_dequeue_datagram(), ip_reass_pbufcount, ip_reassdata::iphdr, LWIP_ASSERT, ip_reassdata::next, NULL, ip_reassdata::p, pbuf::payload, pbuf_clen(), pbuf_free(), and snmp_inc_ipreasmfails.
Referenced by ip_reass_remove_oldest_datagram(), and ip_reass_tmr().
|
static |
Free the oldest datagram to make room for enqueueing new fragments.
The datagram 'fraghdr' belongs to is not freed!
fraghdr | IP header of the current fragment |
pbufs_needed | number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) |
References IP_ADDRESSES_AND_ID_MATCH, ip_reass_free_complete_datagram(), ip_reassdata::iphdr, ip_reassdata::next, NULL, reassdatagrams, and ip_reassdata::timer.
Referenced by ip_reass(), and ip_reass_enqueue_new_datagram().
Reassembly timer base function for both NO_SYS == 0 and 1 (!).
Should be called every 1000 msec (defined by IP_TMR_INTERVAL).
References IP_REASS_DEBUG, ip_reass_free_complete_datagram(), LWIP_DEBUGF, ip_reassdata::next, NULL, reassdatagrams, ip_reassdata::timer, and U16_F.
Referenced by ip_reass_timer().
|
static |
Referenced by ip_reass(), ip_reass_chain_frag_into_datagram_and_validate(), and ip_reass_free_complete_datagram().
PACK_STRUCT_BEGIN struct ip_reass_helper PACK_STRUCT_STRUCT |
|
static |
Referenced by ip_reass_enqueue_new_datagram(), ip_reass_remove_oldest_datagram(), and ip_reass_tmr().