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:
goldsimon 2007-06-03 18:36:42 +00:00
parent 3639daa329
commit 3a607a197e
5 changed files with 131 additions and 21 deletions

View File

@ -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.

View File

@ -69,8 +69,8 @@
void
ip_init(void)
{
#if IP_FRAG
ip_frag_init();
#if IP_REASSEMBLY
ip_reass_init();
#endif
}

View File

@ -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 */

View File

@ -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__ */

View File

@ -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