task #11472 Support PBUF_REF for RX (IPv6 and IPv4/v6 reassembly might not work yet)

This commit is contained in:
goldsimon 2014-12-08 14:45:36 +01:00
parent 36f470383b
commit 4085a3fad4
6 changed files with 58 additions and 28 deletions

View File

@ -148,28 +148,25 @@ icmp_input(struct pbuf *p, struct netif *inp)
* allocate a new one and copy p into it * allocate a new one and copy p into it
*/ */
struct pbuf *r; struct pbuf *r;
/* switch p->payload to ip header */
if (pbuf_header(p, hlen)) {
LWIP_ASSERT("icmp_input: moving p->payload to ip header failed\n", 0);
goto memerr;
}
/* allocate new packet buffer with space for link headers */ /* allocate new packet buffer with space for link headers */
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); r = pbuf_alloc(PBUF_LINK, p->tot_len + hlen, PBUF_RAM);
if (r == NULL) { if (r == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n")); LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: allocating new pbuf failed\n"));
goto memerr; goto memerr;
} }
LWIP_ASSERT("check that first pbuf can hold struct the ICMP header", LWIP_ASSERT("check that first pbuf can hold struct the ICMP header",
(r->len >= hlen + sizeof(struct icmp_echo_hdr))); (r->len >= hlen + sizeof(struct icmp_echo_hdr)));
/* copy the whole packet including ip header */ /* copy the ip header */
if (pbuf_copy(r, p) != ERR_OK) { MEMCPY(r->payload, iphdr, hlen);
LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
goto memerr;
}
iphdr = (struct ip_hdr *)r->payload; iphdr = (struct ip_hdr *)r->payload;
/* switch r->payload back to icmp header */ /* switch r->payload back to icmp header */
if (pbuf_header(r, -hlen)) { if (pbuf_header(r, -hlen)) {
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0); LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0);
goto memerr;
}
/* copy the rest of the packet without ip header */
if (pbuf_copy(r, p) != ERR_OK) {
LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
goto memerr; goto memerr;
} }
/* free the original p */ /* free the original p */

View File

@ -586,7 +586,7 @@ ip_input(struct pbuf *p, struct netif *inp)
/* send ICMP destination protocol unreachable unless is was a broadcast */ /* send ICMP destination protocol unreachable unless is was a broadcast */
if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) && if (!ip_addr_isbroadcast(ip_current_dest_addr(), inp) &&
!ip_addr_ismulticast(ip_current_dest_addr())) { !ip_addr_ismulticast(ip_current_dest_addr())) {
pbuf_header(p, iphdr_hlen); /* Move to ip header, no check necessary. */ pbuf_header_force(p, iphdr_hlen); /* Move to ip header, no check necessary. */
p->payload = iphdr; p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PROTO); icmp_dest_unreach(p, ICMP_DUR_PROTO);
} }

View File

@ -649,6 +649,7 @@ netif_found:
options_done: options_done:
/* p points to IPv6 header again. */ /* p points to IPv6 header again. */
/* @todo: this does not work for PBUF_REF pbufs */
pbuf_header(p, ip_data.current_ip_header_tot_len); pbuf_header(p, ip_data.current_ip_header_tot_len);
/* send to upper layers */ /* send to upper layers */

View File

@ -489,26 +489,17 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
/** /**
* Adjusts the payload pointer to hide or reveal headers in the payload. * Adjusts the payload pointer to hide or reveal headers in the payload.
* * @see pbuf_header.
* Adjusts the ->payload pointer so that space for a header
* (dis)appears in the pbuf payload.
*
* The ->payload, ->tot_len and ->len fields are adjusted.
* *
* @param p pbuf to change the header size. * @param p pbuf to change the header size.
* @param header_size_increment Number of bytes to increment header size which * @param header_size_increment Number of bytes to increment header size.
* increases the size of the pbuf. New space is on the front. * @param force Allow 'header_size_increment > 0' for PBUF_REF/PBUF_ROM types
* (Using a negative value decreases the header size.)
* If hdr_size_inc is 0, this function does nothing and returns successful.
* *
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
* the call will fail. A check is made that the increase in header size does
* not move the payload pointer in front of the start of the buffer.
* @return non-zero on failure, zero on success. * @return non-zero on failure, zero on success.
* *
*/ */
u8_t u8_t
pbuf_header(struct pbuf *p, s16_t header_size_increment) pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
{ {
u16_t type; u16_t type;
void *payload; void *payload;
@ -561,6 +552,8 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { if ((header_size_increment < 0) && (increment_magnitude <= p->len)) {
/* increase payload pointer */ /* increase payload pointer */
p->payload = (u8_t *)p->payload - header_size_increment; p->payload = (u8_t *)p->payload - header_size_increment;
} else if ((header_size_increment > 0) && force) {
p->payload = (u8_t *)p->payload - header_size_increment;
} else { } else {
/* cannot expand payload to front (yet!) /* cannot expand payload to front (yet!)
* bail out unsuccessfully */ * bail out unsuccessfully */
@ -581,6 +574,42 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
return 0; return 0;
} }
/**
* Adjusts the payload pointer to hide or reveal headers in the payload.
*
* Adjusts the ->payload pointer so that space for a header
* (dis)appears in the pbuf payload.
*
* The ->payload, ->tot_len and ->len fields are adjusted.
*
* @param p pbuf to change the header size.
* @param header_size_increment Number of bytes to increment header size which
* increases the size of the pbuf. New space is on the front.
* (Using a negative value decreases the header size.)
* If hdr_size_inc is 0, this function does nothing and returns successful.
*
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
* the call will fail. A check is made that the increase in header size does
* not move the payload pointer in front of the start of the buffer.
* @return non-zero on failure, zero on success.
*
*/
u8_t
pbuf_header(struct pbuf *p, s16_t header_size_increment)
{
return pbuf_header_impl(p, header_size_increment, 0);
}
/**
* Same as pbuf_header but does not check if 'header_size > 0' is allowed.
* This is used internally only, to allow PBUF_REF for RX.
*/
u8_t
pbuf_header_force(struct pbuf *p, s16_t header_size_increment)
{
return pbuf_header_impl(p, header_size_increment, 1);
}
/** /**
* Dereference a pbuf chain or queue and deallocate any no-longer-used * Dereference a pbuf chain or queue and deallocate any no-longer-used
* pbufs at the head of this chain or queue. * pbufs at the head of this chain or queue.

View File

@ -398,7 +398,7 @@ udp_input(struct pbuf *p, struct netif *inp)
struct pbuf *q; struct pbuf *q;
/* for that, move payload to IP header again */ /* for that, move payload to IP header again */
if (p_header_changed == 0) { if (p_header_changed == 0) {
pbuf_header(p, hdrs_len); pbuf_header_force(p, hdrs_len);
p_header_changed = 1; p_header_changed = 1;
} }
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
@ -457,7 +457,7 @@ udp_input(struct pbuf *p, struct netif *inp)
#endif /* LWIP_IPV6 */ #endif /* LWIP_IPV6 */
!ip_addr_ismulticast(ip_current_dest_addr())) { !ip_addr_ismulticast(ip_current_dest_addr())) {
/* move payload pointer back to ip header */ /* move payload pointer back to ip header */
pbuf_header(p, ip_current_header_tot_len() + UDP_HLEN); pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN);
icmp_port_unreach(ip_current_is_v6(), p); icmp_port_unreach(ip_current_is_v6(), p);
} }
#endif /* LWIP_ICMP || LWIP_ICMP6 */ #endif /* LWIP_ICMP || LWIP_ICMP6 */

View File

@ -42,7 +42,9 @@ extern "C" {
/** Currently, the pbuf_custom code is only needed for one specific configuration /** Currently, the pbuf_custom code is only needed for one specific configuration
* of IP_FRAG */ * of IP_FRAG */
#ifndef LWIP_SUPPORT_CUSTOM_PBUF
#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF) #define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
#endif
/* @todo: We need a mechanism to prevent wasting memory in every pbuf /* @todo: We need a mechanism to prevent wasting memory in every pbuf
(TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */ (TCP vs. UDP, IPv4 vs. IPv6: UDP/IPv4 packets may waste up to 28 bytes) */
@ -158,6 +160,7 @@ struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type,
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */ #endif /* LWIP_SUPPORT_CUSTOM_PBUF */
void pbuf_realloc(struct pbuf *p, u16_t size); void pbuf_realloc(struct pbuf *p, u16_t size);
u8_t pbuf_header(struct pbuf *p, s16_t header_size); u8_t pbuf_header(struct pbuf *p, s16_t header_size);
u8_t pbuf_header_force(struct pbuf *p, s16_t header_size);
void pbuf_ref(struct pbuf *p); void pbuf_ref(struct pbuf *p);
u8_t pbuf_free(struct pbuf *p); u8_t pbuf_free(struct pbuf *p);
u8_t pbuf_clen(struct pbuf *p); u8_t pbuf_clen(struct pbuf *p);