mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-04 14:29:39 +00:00
opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF (defaulting to off for now) that can be set to 0 to send fragmented packets by passing PBUF_REFs down the stack.
This commit is contained in:
parent
3639daa329
commit
3a607a197e
@ -19,6 +19,11 @@ HISTORY
|
||||
|
||||
++ New features:
|
||||
|
||||
2007-05-18 Simon Goldschmidt
|
||||
* opt.h, ip_frag.c, ip_frag.h, ip.c: Added option IP_FRAG_USES_STATIC_BUF
|
||||
(defaulting to off for now) that can be set to 0 to send fragmented
|
||||
packets by passing PBUF_REFs down the stack.
|
||||
|
||||
2007-05-23 Frédéric Bernon
|
||||
* api_lib.c: Implement SO_RCVTIMEO for accept and recv on TCP
|
||||
connections, such present in patch #5959.
|
||||
|
@ -69,8 +69,8 @@
|
||||
void
|
||||
ip_init(void)
|
||||
{
|
||||
#if IP_FRAG
|
||||
ip_frag_init();
|
||||
#if IP_REASSEMBLY
|
||||
ip_reass_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -46,8 +46,7 @@
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#if (IP_FRAG || IP_REASSEMBLY)
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
||||
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1];
|
||||
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
||||
@ -58,7 +57,9 @@ static u8_t ip_reassflags;
|
||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||
|
||||
static u8_t ip_reasstmr;
|
||||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if IP_REASSEMBLY || IP_FRAG_USES_STATIC_BUF
|
||||
/*
|
||||
* Copy len bytes from offset in pbuf to buffer
|
||||
*
|
||||
@ -84,13 +85,14 @@ copy_from_pbuf(struct pbuf *p, u16_t * offset,
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#endif /* IP_REASSEMBLY || IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
/**
|
||||
* Initializes IP reassembly and fragmentation states.
|
||||
* Initializes IP reassembly states.
|
||||
*/
|
||||
void
|
||||
ip_frag_init(void)
|
||||
ip_reass_init(void)
|
||||
{
|
||||
ip_reasstmr = 0;
|
||||
ip_reassflags = 0;
|
||||
@ -299,30 +301,54 @@ nullreturn:
|
||||
pbuf_free(p);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if IP_FRAG
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
static u8_t buf[MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU)];
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
/**
|
||||
* 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_ROM)
|
||||
* by using a fixed size static memory buffer (PBUF_REF) or
|
||||
* point PBUF_REFs into p (depending on IP_FRAG_USES_STATIC_BUF).
|
||||
*
|
||||
* @param p ip packet to send
|
||||
* @param netif the netif on which to send
|
||||
* @param dest destination ip address to which to send
|
||||
*
|
||||
* @return ERR_OK if sent successfully, err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
{
|
||||
struct pbuf *rambuf;
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
struct pbuf *header;
|
||||
#else
|
||||
struct pbuf *newpbuf;
|
||||
struct ip_hdr *original_iphdr;
|
||||
#endif
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t nfb = 0;
|
||||
u16_t nfb;
|
||||
u16_t left, cop;
|
||||
u16_t mtu = netif->mtu;
|
||||
u16_t ofo, omf;
|
||||
u16_t last;
|
||||
u16_t poff = IP_HLEN;
|
||||
u16_t tmp;
|
||||
#if !IP_FRAG_USES_STATIC_BUF
|
||||
u16_t newpbuflen, left_to_copy;
|
||||
#endif
|
||||
|
||||
/* Get a RAM based MTU sized pbuf */
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
/* When using a static buffer, we use a PBUF_REF, which we will
|
||||
* use to reference the packet (without link header).
|
||||
* Layer and length is irrelevant.
|
||||
*/
|
||||
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
||||
if (rambuf == NULL) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n"));
|
||||
@ -334,6 +360,10 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
/* Copy the IP header in it */
|
||||
iphdr = rambuf->payload;
|
||||
SMEMCPY(iphdr, p->payload, IP_HLEN);
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
original_iphdr = p->payload;
|
||||
iphdr = original_iphdr;
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
/* Save original offset */
|
||||
tmp = ntohs(IPH_OFFSET(iphdr));
|
||||
@ -342,29 +372,75 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
|
||||
left = p->tot_len - IP_HLEN;
|
||||
|
||||
nfb = (mtu - IP_HLEN) / 8;
|
||||
|
||||
while (left) {
|
||||
last = (left <= mtu - IP_HLEN);
|
||||
|
||||
/* Set new offset and MF flag */
|
||||
ofo += nfb;
|
||||
tmp = omf | (IP_OFFMASK & (ofo));
|
||||
if (!last)
|
||||
tmp = tmp | IP_MF;
|
||||
IPH_OFFSET_SET(iphdr, htons(tmp));
|
||||
|
||||
/* Fill this fragment */
|
||||
nfb = (mtu - IP_HLEN) / 8;
|
||||
cop = last ? left : nfb * 8;
|
||||
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
p = copy_from_pbuf(p, &poff, (u8_t *) iphdr + IP_HLEN, cop);
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
/* When not using a static buffer, create a chain of pbufs.
|
||||
* The first will be a PBUF_RAM holding the link and IP header.
|
||||
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
|
||||
* but limited to the size of an mtu.
|
||||
*/
|
||||
rambuf = pbuf_alloc(PBUF_LINK, IP_HLEN, PBUF_RAM);
|
||||
if (rambuf == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
|
||||
iphdr = rambuf->payload;
|
||||
|
||||
/* Can just adjust p directly for needed offset. */
|
||||
p->payload = (u8_t *)p->payload + poff;
|
||||
p->len -= poff;
|
||||
|
||||
left_to_copy = cop;
|
||||
while (left_to_copy) {
|
||||
newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
|
||||
/* Is this pbuf already empty? */
|
||||
if (!newpbuflen) {
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
newpbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
|
||||
if (newpbuf == NULL) {
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* Mirror this pbuf, although we might not need all of it. */
|
||||
newpbuf->payload = p->payload;
|
||||
newpbuf->len = newpbuf->tot_len = newpbuflen;
|
||||
/* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
|
||||
* so that it is removed when pbuf_dechain is later called on rambuf.
|
||||
*/
|
||||
pbuf_cat(rambuf, newpbuf);
|
||||
left_to_copy -= newpbuflen;
|
||||
if (left_to_copy)
|
||||
p = p->next;
|
||||
}
|
||||
poff = newpbuflen;
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
/* Correct header */
|
||||
IPH_OFFSET_SET(iphdr, htons(tmp));
|
||||
IPH_LEN_SET(iphdr, htons(cop + IP_HLEN));
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
if (last)
|
||||
pbuf_realloc(rambuf, left + IP_HLEN);
|
||||
|
||||
/* This part is ugly: we alloc a RAM based pbuf for
|
||||
* the link level header for each chunk and then
|
||||
* free it.A PBUF_ROM style pbuf for which pbuf_header
|
||||
@ -382,11 +458,29 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
/* No need for separate header pbuf - we allowed room for it in rambuf
|
||||
* when allocated.
|
||||
*/
|
||||
netif->output(netif, rambuf, dest);
|
||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||
|
||||
/* Unfortunately we can't reuse rambuf - the hardware may still be
|
||||
* using the buffer. Instead we free it (and the ensuing chain) and
|
||||
* recreate it next time round the loop. If we're lucky the hardware
|
||||
* will have already sent the packet, the free will really free, and
|
||||
* there will be zero memory penalty.
|
||||
*/
|
||||
|
||||
pbuf_free(rambuf);
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
left -= cop;
|
||||
ofo += nfb;
|
||||
}
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
pbuf_free(rambuf);
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
snmp_inc_ipfragoks();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif /* IP_FRAG || IP_REASSEMBLY */
|
||||
#endif /* IP_FRAG */
|
||||
|
@ -39,24 +39,25 @@
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#if (IP_FRAG || IP_REASSEMBLY)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* The IP timer interval in milliseconds. */
|
||||
#if IP_REASSEMBLY
|
||||
/* The IP reassembly timer interval in milliseconds. */
|
||||
#define IP_TMR_INTERVAL 1000
|
||||
|
||||
void ip_frag_init(void);
|
||||
void ip_reass_init(void);
|
||||
void ip_reass_tmr(void);
|
||||
struct pbuf * ip_reass(struct pbuf *p);
|
||||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if IP_FRAG
|
||||
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
|
||||
#endif /* IP_FRAG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IP_FRAG || IP_REASSEMBLY */
|
||||
|
||||
#endif /* __LWIP_IP_FRAG_H__ */
|
||||
|
@ -264,8 +264,18 @@ a lot of data that needs to be copied, this should be set high. */
|
||||
#define IP_REASS_BUFSIZE 5760
|
||||
#endif
|
||||
|
||||
/* Use a static MTU-sized buffer for IP fragmentation.
|
||||
|
||||
* Otherwise pbufs are allocated and reference the original
|
||||
* packet data to be fragmented.
|
||||
|
||||
*/
|
||||
#ifndef IP_FRAG_USES_STATIC_BUF
|
||||
#define IP_FRAG_USES_STATIC_BUF 1
|
||||
#endif
|
||||
|
||||
/* Assumed max MTU on any interface for IP frag buffer */
|
||||
#ifndef IP_FRAG_MAX_MTU
|
||||
#if IP_FRAG_USES_STATIC_BUF && !defined(IP_FRAG_MAX_MTU)
|
||||
#define IP_FRAG_MAX_MTU 1500
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user