55 #if LWIP_IPV6 && LWIP_IPV6_REASS 61 #ifndef IP_REASS_CHECK_OVERLAP 62 #define IP_REASS_CHECK_OVERLAP 1 69 #ifndef IP_REASS_FREE_OLDEST 70 #define IP_REASS_FREE_OLDEST 1 73 #if IPV6_FRAG_COPYHEADER 74 #define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN)) 77 #define IP_REASS_FLAG_LASTFRAG 0x01 86 #ifdef PACK_STRUCT_USE_INCLUDES 90 struct ip6_reass_helper {
96 #ifdef PACK_STRUCT_USE_INCLUDES 101 static struct ip6_reassdata *reassdatagrams;
102 static u16_t ip6_reass_pbufcount;
105 static void ip6_reass_free_complete_datagram(
struct ip6_reassdata *ipr);
106 #if IP_REASS_FREE_OLDEST 107 static void ip6_reass_remove_oldest_datagram(
struct ip6_reassdata *ipr,
int pbufs_needed);
113 struct ip6_reassdata *r, *tmp;
115 #if !IPV6_FRAG_COPYHEADER 116 LWIP_ASSERT(
"sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
117 sizeof(
struct ip6_reass_helper) <= IP6_FRAG_HLEN);
133 ip6_reass_free_complete_datagram(tmp);
146 ip6_reass_free_complete_datagram(
struct ip6_reassdata *ipr)
148 struct ip6_reassdata *prev;
149 u16_t pbufs_freed = 0;
152 struct ip6_reass_helper *iprh;
155 iprh = (
struct ip6_reass_helper *)ipr->p->payload;
156 if (iprh->start == 0) {
160 ipr->p = iprh->next_pbuf;
164 LWIP_ASSERT(
"ip6_reass_free: moving p->payload to ip6 header failed\n", 0);
170 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
181 iprh = (
struct ip6_reass_helper *)p->
payload;
186 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
192 if (ipr == reassdatagrams) {
193 reassdatagrams = ipr->next;
195 prev = reassdatagrams;
196 while (prev !=
NULL) {
197 if (prev->next == ipr) {
203 prev->next = ipr->next;
209 LWIP_ASSERT(
"ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed);
210 ip6_reass_pbufcount -= pbufs_freed;
213 #if IP_REASS_FREE_OLDEST 223 ip6_reass_remove_oldest_datagram(
struct ip6_reassdata *ipr,
int pbufs_needed)
225 struct ip6_reassdata *r, *oldest;
230 r = oldest = reassdatagrams;
233 if (r->timer <= oldest->timer) {
244 if (oldest !=
NULL) {
245 ip6_reass_free_complete_datagram(oldest);
260 ip6_reass(
struct pbuf *p)
262 struct ip6_reassdata *ipr, *ipr_prev;
263 struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=
NULL;
264 struct ip6_frag_hdr * frag_hdr;
266 u8_t clen, valid = 1;
271 LWIP_ASSERT(
"ip6_frag_hdr must be in the first pbuf, not chained",
272 (
const void*)ip6_current_header() == ((
u8_t*)p->
payload) - IP6_HLEN);
274 frag_hdr = (
struct ip6_frag_hdr *) p->
payload;
278 offset =
ntohs(frag_hdr->_fragment_offset);
283 len =
ntohs(ip6_current_header()->_plen);
285 len -= IP6_FRAG_HLEN;
289 for (ipr = reassdatagrams, ipr_prev =
NULL; ipr !=
NULL; ipr = ipr->next) {
293 if ((frag_hdr->_identification == ipr->identification) &&
294 ip6_addr_cmp(ip6_current_src_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->src)) &&
295 ip6_addr_cmp(ip6_current_dest_addr(), &(IPV6_FRAG_HDRREF(ipr->iphdr)->dest))) {
304 ipr = (
struct ip6_reassdata *)
memp_malloc(MEMP_IP6_REASSDATA);
306 #if IP_REASS_FREE_OLDEST 308 ip6_reass_remove_oldest_datagram(ipr, clen);
309 ipr = (
struct ip6_reassdata *)
memp_malloc(MEMP_IP6_REASSDATA);
312 for (ipr_prev = reassdatagrams; ipr_prev !=
NULL; ipr_prev = ipr_prev->next) {
313 if (ipr_prev->next == ipr) {
326 memset(ipr, 0,
sizeof(
struct ip6_reassdata));
330 ipr->next = reassdatagrams;
331 reassdatagrams = ipr;
336 #if IPV6_FRAG_COPYHEADER 337 MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
340 ipr->iphdr =
ip_data.current_ip6_header;
344 ipr->identification = frag_hdr->_identification;
347 ipr->nexth = frag_hdr->_nexth;
352 #if IP_REASS_FREE_OLDEST 353 ip6_reass_remove_oldest_datagram(ipr, clen);
356 for (ipr_prev = reassdatagrams; ipr_prev !=
NULL; ipr_prev = ipr_prev->next) {
357 if (ipr_prev->next == ipr) {
373 #if IPV6_FRAG_COPYHEADER 374 if (IPV6_FRAG_REQROOM > 0) {
381 LWIP_ASSERT(
"sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
382 sizeof(
struct ip6_reass_helper) <= IP6_FRAG_HLEN);
384 iprh = (
struct ip6_reass_helper *)p->
payload;
385 iprh->next_pbuf =
NULL;
386 iprh->start = (offset & IP6_FRAG_OFFSET_MASK);
387 iprh->end = (offset & IP6_FRAG_OFFSET_MASK) + len;
392 for (q = ipr->p; q !=
NULL;) {
393 iprh_tmp = (
struct ip6_reass_helper*)q->
payload;
394 if (iprh->start < iprh_tmp->start) {
395 #if IP_REASS_CHECK_OVERLAP 396 if (iprh->end > iprh_tmp->start) {
402 if (iprh_prev !=
NULL) {
403 if (iprh->start < iprh_prev->end) {
413 if (iprh_prev !=
NULL) {
415 iprh_prev->next_pbuf = p;
421 }
else if (iprh->start == iprh_tmp->start) {
425 #if IP_REASS_CHECK_OVERLAP 426 }
else if (iprh->start < iprh_tmp->end) {
434 if (iprh_prev !=
NULL) {
435 if (iprh_prev->end != iprh_tmp->start) {
442 q = iprh_tmp->next_pbuf;
443 iprh_prev = iprh_tmp;
448 if (iprh_prev !=
NULL) {
451 #if IP_REASS_CHECK_OVERLAP 452 LWIP_ASSERT(
"check fragments don't overlap", iprh_prev->end <= iprh->start);
454 iprh_prev->next_pbuf = p;
455 if (iprh_prev->end != iprh->start) {
459 #if IP_REASS_CHECK_OVERLAP 460 LWIP_ASSERT(
"no previous fragment, this must be the first fragment!",
470 ip6_reass_pbufcount += clen;
473 if (iprh->start == 0) {
474 #if IPV6_FRAG_COPYHEADER 475 if (iprh->next_pbuf !=
NULL) {
476 MEMCPY(&ipr->iphdr, ip6_current_header(), IP6_HLEN);
480 ipr->iphdr =
ip_data.current_ip6_header;
485 if ((offset & IP6_FRAG_MORE_FLAG) == 0) {
486 ipr->datagram_len = iprh->end;
490 iprh_tmp = (
struct ip6_reass_helper*)ipr->p->payload;
491 if (iprh_tmp->start != 0) {
494 if (ipr->datagram_len == 0) {
501 while ((q !=
NULL) && valid) {
502 iprh = (
struct ip6_reass_helper*)q->
payload;
503 if (iprh_prev->end != iprh->start) {
513 struct ip6_hdr* iphdr_ptr;
516 iprh = (
struct ip6_reass_helper*) ipr->p->payload;
517 while (iprh !=
NULL) {
518 struct pbuf* next_pbuf = iprh->next_pbuf;
519 if (next_pbuf !=
NULL) {
521 iprh_tmp = (
struct ip6_reass_helper*)next_pbuf->
payload;
525 #if IPV6_FRAG_COPYHEADER 526 if (IPV6_FRAG_REQROOM > 0) {
541 #if IPV6_FRAG_COPYHEADER 542 if (IPV6_FRAG_REQROOM > 0) {
547 iphdr_ptr = (
struct ip6_hdr*)((
u8_t*)ipr->p->payload - IP6_HLEN);
548 MEMCPY(iphdr_ptr, &ipr->iphdr, IP6_HLEN);
550 iphdr_ptr = ipr->iphdr;
554 ipr->datagram_len += (
u16_t)(((
u8_t*)ipr->p->payload - (
u8_t*)iphdr_ptr)
559 iphdr_ptr->_plen =
htons(ipr->datagram_len);
566 frag_hdr = (
struct ip6_frag_hdr *) p->
payload;
567 frag_hdr->_nexth = ipr->nexth;
568 frag_hdr->reserved = 0;
569 frag_hdr->_fragment_offset = 0;
570 frag_hdr->_identification = 0;
573 if (reassdatagrams == ipr) {
575 reassdatagrams = ipr->next;
579 ipr_prev->next = ipr->next;
589 LWIP_ASSERT(
"ip6_reass: moving p->payload to ip6 header failed\n", 0);
607 #if LWIP_IPV6 && LWIP_IPV6_FRAG 610 static struct pbuf_custom_ref*
611 ip6_frag_alloc_pbuf_custom_ref(
void)
613 return (
struct pbuf_custom_ref*)
memp_malloc(MEMP_FRAG_PBUF);
618 ip6_frag_free_pbuf_custom_ref(
struct pbuf_custom_ref* p)
627 ip6_frag_free_pbuf_custom(
struct pbuf *p)
629 struct pbuf_custom_ref *pcr = (
struct pbuf_custom_ref*)p;
632 if (pcr->original !=
NULL) {
635 ip6_frag_free_pbuf_custom_ref(pcr);
651 ip6_frag(
struct pbuf *p,
struct netif *
netif,
const ip6_addr_t *dest)
653 struct ip6_hdr *original_ip6hdr;
654 struct ip6_hdr *ip6hdr;
655 struct ip6_frag_hdr * frag_hdr;
657 struct pbuf *newpbuf;
658 static u32_t identification;
662 u16_t fragment_offset = 0;
664 u16_t poff = IP6_HLEN;
665 u16_t newpbuflen = 0;
670 original_ip6hdr = (
struct ip6_hdr *)p->
payload;
672 mtu = nd6_get_destination_mtu(dest, netif);
677 nfb = (mtu - (IP6_HLEN + IP6_FRAG_HLEN)) & IP6_FRAG_OFFSET_MASK;
680 last = (left <= nfb);
683 cop = last ? left : nfb;
691 if (rambuf ==
NULL) {
696 (p->
len >= (IP6_HLEN + IP6_FRAG_HLEN)));
698 ip6hdr = (
struct ip6_hdr *)rambuf->
payload;
699 frag_hdr = (
struct ip6_frag_hdr *)((
u8_t*)rambuf->
payload + IP6_HLEN);
707 while (left_to_copy) {
708 struct pbuf_custom_ref *pcr;
709 newpbuflen = (left_to_copy < p->
len) ? left_to_copy : p->
len;
715 pcr = ip6_frag_alloc_pbuf_custom_ref();
723 if (newpbuf ==
NULL) {
724 ip6_frag_free_pbuf_custom_ref(pcr);
731 pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom;
737 left_to_copy -= newpbuflen;
745 frag_hdr->_nexth = original_ip6hdr->_nexth;
746 frag_hdr->reserved = 0;
747 frag_hdr->_fragment_offset =
htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG));
748 frag_hdr->_identification =
htonl(identification);
750 IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
751 IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN);
757 netif->output_ip6(netif, rambuf, dest);
768 fragment_offset += cop;
#define PACK_STRUCT_STRUCT
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
#define SMEMCPY(dst, src, len)
#define MEMCPY(dst, src, len)
#define PACK_STRUCT_FIELD(x)
void memp_free(memp_t type, void *mem)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
#define IP_REASS_MAX_PBUFS
u8_t pbuf_free(struct pbuf *p)
#define IP6_FRAG_STATS_INC(x)
#define LWIP_ASSERT(message, assertion)
void pbuf_ref(struct pbuf *p)
#define PACK_STRUCT_BEGIN
struct ip_globals ip_data
u8_t pbuf_clen(struct pbuf *p)
u8_t pbuf_header_force(struct pbuf *p, s16_t header_size_increment)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
void * memp_malloc(memp_t type)