Upgraded lwIP to 2.0.3
This commit is contained in:
@@ -4,6 +4,22 @@ HISTORY
|
|||||||
|
|
||||||
* [Enter new changes just after this line - do not remove this line]
|
* [Enter new changes just after this line - do not remove this line]
|
||||||
|
|
||||||
|
(STABLE-2.0.3)
|
||||||
|
|
||||||
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2017-09-11: Simon Goldschmidt
|
||||||
|
* tcp_in.c: fix bug #51937 (leaking tcp_pcbs on passive close with unacked data)
|
||||||
|
|
||||||
|
2017-08-02: Abroz Bizjak/Simon Goldschmidt
|
||||||
|
* multiple fixes in IPv4 reassembly (leading to corrupted datagrams received)
|
||||||
|
|
||||||
|
2017-03-30: Simon Goldschmidt
|
||||||
|
* dhcp.c: return ERR_VAL instead of asserting on offset-out-of-pbuf
|
||||||
|
|
||||||
|
2017-03-23: Dirk Ziegelmeier
|
||||||
|
* dhcp.h: fix bug #50618 (dhcp_remove_struct() macro does not work)
|
||||||
|
|
||||||
(STABLE-2.0.2)
|
(STABLE-2.0.2)
|
||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
@@ -13,6 +29,9 @@ HISTORY
|
|||||||
We now have a #define for a header file name that is #included in every .c
|
We now have a #define for a header file name that is #included in every .c
|
||||||
file that provides hooks.
|
file that provides hooks.
|
||||||
|
|
||||||
|
2017-02-10: Simon Goldschmidt
|
||||||
|
* tcp_close does not fail on memory error (instead, FIN is sent from tcp_tmr)
|
||||||
|
|
||||||
++ Bugfixes:
|
++ Bugfixes:
|
||||||
|
|
||||||
2017-03-08
|
2017-03-08
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ with newer versions.
|
|||||||
|
|
||||||
* [Enter new changes just after this line - do not remove this line]
|
* [Enter new changes just after this line - do not remove this line]
|
||||||
|
|
||||||
|
(2.0.2)
|
||||||
|
|
||||||
|
++ Application changes:
|
||||||
|
|
||||||
|
* slipif: The way to pass serial port number has changed. netif->num is not
|
||||||
|
supported any more, netif->state is interpreted as an u8_t port number now
|
||||||
|
(it's not a POINTER to an u8_t any more!)
|
||||||
|
|
||||||
(2.0.1)
|
(2.0.1)
|
||||||
|
|
||||||
++ Application changes:
|
++ Application changes:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
void eth_mac_irq()
|
void
|
||||||
|
eth_mac_irq()
|
||||||
{
|
{
|
||||||
/* Service MAC IRQ here */
|
/* Service MAC IRQ here */
|
||||||
|
|
||||||
@@ -17,7 +18,8 @@ void eth_mac_irq()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static err_t netif_output(struct netif *netif, struct pbuf *p)
|
static err_t
|
||||||
|
netif_output(struct netif *netif, struct pbuf *p)
|
||||||
{
|
{
|
||||||
LINK_STATS_INC(link.xmit);
|
LINK_STATS_INC(link.xmit);
|
||||||
|
|
||||||
@@ -38,12 +40,14 @@ static err_t netif_output(struct netif *netif, struct pbuf *p)
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netif_status_callback(struct netif *netif)
|
static void
|
||||||
|
netif_status_callback(struct netif *netif)
|
||||||
{
|
{
|
||||||
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
|
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static err_t netif_init(struct netif *netif)
|
static err_t
|
||||||
|
netif_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
netif->linkoutput = netif_output;
|
netif->linkoutput = netif_output;
|
||||||
netif->output = etharp_output;
|
netif->output = etharp_output;
|
||||||
@@ -58,7 +62,8 @@ static err_t netif_init(struct netif *netif)
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
void
|
||||||
|
main(void)
|
||||||
{
|
{
|
||||||
struct netif netif;
|
struct netif netif;
|
||||||
|
|
||||||
@@ -74,7 +79,7 @@ void main(void)
|
|||||||
netif_set_up(&netif);
|
netif_set_up(&netif);
|
||||||
|
|
||||||
/* Start DHCP and HTTPD */
|
/* Start DHCP and HTTPD */
|
||||||
dhcp_init();
|
dhcp_start(&netif );
|
||||||
httpd_init();
|
httpd_init();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
|
|||||||
@@ -177,14 +177,20 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
|||||||
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
|
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
|
||||||
LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
|
LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
|
||||||
conn = (struct netconn *)arg;
|
conn = (struct netconn *)arg;
|
||||||
|
|
||||||
|
if (conn == NULL) {
|
||||||
|
pbuf_free(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
|
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
|
||||||
|
|
||||||
#if LWIP_SO_RCVBUF
|
#if LWIP_SO_RCVBUF
|
||||||
SYS_ARCH_GET(conn->recv_avail, recv_avail);
|
SYS_ARCH_GET(conn->recv_avail, recv_avail);
|
||||||
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
|
if (!sys_mbox_valid(&conn->recvmbox) ||
|
||||||
((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
|
((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
|
||||||
#else /* LWIP_SO_RCVBUF */
|
#else /* LWIP_SO_RCVBUF */
|
||||||
if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
|
if (!sys_mbox_valid(&conn->recvmbox)) {
|
||||||
#endif /* LWIP_SO_RCVBUF */
|
#endif /* LWIP_SO_RCVBUF */
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return;
|
return;
|
||||||
@@ -471,8 +477,6 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||||||
struct netconn *newconn;
|
struct netconn *newconn;
|
||||||
struct netconn *conn = (struct netconn *)arg;
|
struct netconn *conn = (struct netconn *)arg;
|
||||||
|
|
||||||
LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
|
|
||||||
|
|
||||||
if (conn == NULL) {
|
if (conn == NULL) {
|
||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
@@ -490,6 +494,8 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
|||||||
return ERR_VAL;
|
return ERR_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
|
||||||
|
|
||||||
/* We have to set the callback here even though
|
/* We have to set the callback here even though
|
||||||
* the new socket is unknown. newconn->socket is marked as -1. */
|
* the new socket is unknown. newconn->socket is marked as -1. */
|
||||||
newconn = netconn_alloc(conn->type, conn->callback);
|
newconn = netconn_alloc(conn->type, conn->callback);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
//#include "lwip/errno.h"
|
||||||
|
|
||||||
#if !NO_SYS
|
#if !NO_SYS
|
||||||
/** Table to quickly map an lwIP error (err_t) to a socket error
|
/** Table to quickly map an lwIP error (err_t) to a socket error
|
||||||
|
|||||||
@@ -360,8 +360,9 @@ mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id)
|
|||||||
static void
|
static void
|
||||||
mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t)
|
mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t)
|
||||||
{
|
{
|
||||||
struct mqtt_request_t *r = *tail;
|
struct mqtt_request_t *r;
|
||||||
LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL);
|
LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL);
|
||||||
|
r = *tail;
|
||||||
while (t > 0 && r != NULL) {
|
while (t > 0 && r != NULL) {
|
||||||
if (t >= r->timeout_diff) {
|
if (t >= r->timeout_diff) {
|
||||||
t -= (u8_t)r->timeout_diff;
|
t -= (u8_t)r->timeout_diff;
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ void
|
|||||||
lwip_init(void)
|
lwip_init(void)
|
||||||
{
|
{
|
||||||
#ifndef LWIP_SKIP_CONST_CHECK
|
#ifndef LWIP_SKIP_CONST_CHECK
|
||||||
int a;
|
int a = 0;
|
||||||
LWIP_UNUSED_ARG(a);
|
LWIP_UNUSED_ARG(a);
|
||||||
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
LWIP_ASSERT("LWIP_CONST_CAST not implemented correctly. Check your lwIP port.", LWIP_CONST_CAST(void*, &a) == &a);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -736,7 +736,7 @@ dhcp_start(struct netif *netif)
|
|||||||
|
|
||||||
/* no DHCP client attached yet? */
|
/* no DHCP client attached yet? */
|
||||||
if (dhcp == NULL) {
|
if (dhcp == NULL) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): starting new DHCP client\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): mallocing new DHCP client\n"));
|
||||||
dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
|
dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
|
||||||
if (dhcp == NULL) {
|
if (dhcp == NULL) {
|
||||||
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_start(): could not allocate dhcp\n"));
|
||||||
@@ -1500,7 +1500,7 @@ again:
|
|||||||
offset_max = options_idx_max;
|
offset_max = options_idx_max;
|
||||||
options = (u8_t*)q->payload;
|
options = (u8_t*)q->payload;
|
||||||
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
/* at least 1 byte to read and no end marker, then at least 3 bytes to read? */
|
||||||
while ((q != NULL) && (options[offset] != DHCP_OPTION_END) && (offset < offset_max)) {
|
while ((q != NULL) && (offset < offset_max) && (options[offset] != DHCP_OPTION_END)) {
|
||||||
u8_t op = options[offset];
|
u8_t op = options[offset];
|
||||||
u8_t len;
|
u8_t len;
|
||||||
u8_t decode_len = 0;
|
u8_t decode_len = 0;
|
||||||
@@ -1617,7 +1617,7 @@ decode_next:
|
|||||||
offset_max -= q->len;
|
offset_max -= q->len;
|
||||||
if ((offset < offset_max) && offset_max) {
|
if ((offset < offset_max) && offset_max) {
|
||||||
q = q->next;
|
q = q->next;
|
||||||
LWIP_ASSERT("next pbuf was null", q);
|
LWIP_ERROR("next pbuf was null", q != NULL, return ERR_VAL;);
|
||||||
options = (u8_t*)q->payload;
|
options = (u8_t*)q->payload;
|
||||||
} else {
|
} else {
|
||||||
/* We've run out of bytes, probably no end marker. Don't proceed. */
|
/* We've run out of bytes, probably no end marker. Don't proceed. */
|
||||||
@@ -1832,7 +1832,7 @@ dhcp_create_msg(struct netif *netif, struct dhcp *dhcp, u8_t message_type)
|
|||||||
(dhcp->p_out->len >= sizeof(struct dhcp_msg)));
|
(dhcp->p_out->len >= sizeof(struct dhcp_msg)));
|
||||||
|
|
||||||
/* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
|
/* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */
|
||||||
if (message_type != DHCP_REQUEST) {
|
if ((message_type != DHCP_REQUEST) || (dhcp->state == DHCP_STATE_REBOOTING)) {
|
||||||
/* reuse transaction identifier in retransmissions */
|
/* reuse transaction identifier in retransmissions */
|
||||||
if (dhcp->tries == 0) {
|
if (dhcp->tries == 0) {
|
||||||
#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
|
#if DHCP_CREATE_RAND_XID && defined(LWIP_RAND)
|
||||||
@@ -1942,7 +1942,8 @@ dhcp_supplied_address(const struct netif *netif)
|
|||||||
{
|
{
|
||||||
if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
|
if ((netif != NULL) && (netif_dhcp_data(netif) != NULL)) {
|
||||||
struct dhcp* dhcp = netif_dhcp_data(netif);
|
struct dhcp* dhcp = netif_dhcp_data(netif);
|
||||||
return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING);
|
return (dhcp->state == DHCP_STATE_BOUND) || (dhcp->state == DHCP_STATE_RENEWING) ||
|
||||||
|
(dhcp->state == DHCP_STATE_REBINDING);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,10 @@
|
|||||||
|
|
||||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||||
|
|
||||||
|
#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1
|
||||||
|
#define IP_REASS_VALIDATE_PBUF_QUEUED 0
|
||||||
|
#define IP_REASS_VALIDATE_PBUF_DROPPED -1
|
||||||
|
|
||||||
/** This is a helper struct which holds the starting
|
/** This is a helper struct which holds the starting
|
||||||
* offset and the ending offset of this fragment to
|
* offset and the ending offset of this fragment to
|
||||||
* easily chain the fragments.
|
* easily chain the fragments.
|
||||||
@@ -333,10 +337,11 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
|
|||||||
* fragment was received at least once).
|
* fragment was received at least once).
|
||||||
* @param ipr points to the reassembly state
|
* @param ipr points to the reassembly state
|
||||||
* @param new_p points to the pbuf for the current fragment
|
* @param new_p points to the pbuf for the current fragment
|
||||||
* @return 0 if invalid, >0 otherwise
|
* @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet)
|
||||||
|
* @return see IP_REASS_VALIDATE_* defines
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p)
|
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p, int is_last)
|
||||||
{
|
{
|
||||||
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL;
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
@@ -375,7 +380,18 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
}
|
}
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
iprh_prev->next_pbuf = new_p;
|
iprh_prev->next_pbuf = new_p;
|
||||||
|
if (iprh_prev->end != iprh->start) {
|
||||||
|
/* There is a fragment missing between the current
|
||||||
|
* and the previous fragment */
|
||||||
|
valid = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
|
if (iprh->end > iprh_tmp->start) {
|
||||||
|
/* fragment overlaps with following, throw away */
|
||||||
|
goto freepbuf;
|
||||||
|
}
|
||||||
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
/* fragment with the lowest offset */
|
/* fragment with the lowest offset */
|
||||||
ipr->p = new_p;
|
ipr->p = new_p;
|
||||||
}
|
}
|
||||||
@@ -426,7 +442,7 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
|
|
||||||
/* At this point, the validation part begins: */
|
/* At this point, the validation part begins: */
|
||||||
/* If we already received the last fragment */
|
/* If we already received the last fragment */
|
||||||
if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) {
|
if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
|
||||||
/* and had no holes so far */
|
/* and had no holes so far */
|
||||||
if (valid) {
|
if (valid) {
|
||||||
/* then check if the rest of the fragments is here */
|
/* then check if the rest of the fragments is here */
|
||||||
@@ -454,23 +470,21 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
((struct ip_reass_helper*)ipr->p->payload) != iprh);
|
((struct ip_reass_helper*)ipr->p->payload) != iprh);
|
||||||
LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
|
LWIP_ASSERT("validate_datagram:next_pbuf!=NULL",
|
||||||
iprh->next_pbuf == NULL);
|
iprh->next_pbuf == NULL);
|
||||||
LWIP_ASSERT("validate_datagram:datagram end!=datagram len",
|
|
||||||
iprh->end == ipr->datagram_len);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If valid is 0 here, there are some fragments missing in the middle
|
/* If valid is 0 here, there are some fragments missing in the middle
|
||||||
* (since MF == 0 has already arrived). Such datagrams simply time out if
|
* (since MF == 0 has already arrived). Such datagrams simply time out if
|
||||||
* no more fragments are received... */
|
* no more fragments are received... */
|
||||||
return valid;
|
return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
|
||||||
}
|
}
|
||||||
/* If we come here, not all fragments were received, yet! */
|
/* If we come here, not all fragments were received, yet! */
|
||||||
return 0; /* not yet valid! */
|
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
||||||
#if IP_REASS_CHECK_OVERLAP
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
freepbuf:
|
freepbuf:
|
||||||
ip_reass_pbufcount -= pbuf_clen(new_p);
|
ip_reass_pbufcount -= pbuf_clen(new_p);
|
||||||
pbuf_free(new_p);
|
pbuf_free(new_p);
|
||||||
return 0;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,6 +502,8 @@ ip4_reass(struct pbuf *p)
|
|||||||
struct ip_reassdata *ipr;
|
struct ip_reassdata *ipr;
|
||||||
struct ip_reass_helper *iprh;
|
struct ip_reass_helper *iprh;
|
||||||
u16_t offset, len, clen;
|
u16_t offset, len, clen;
|
||||||
|
int valid;
|
||||||
|
int is_last;
|
||||||
|
|
||||||
IPFRAG_STATS_INC(ip_frag.recv);
|
IPFRAG_STATS_INC(ip_frag.recv);
|
||||||
MIB2_STATS_INC(mib2.ipreasmreqds);
|
MIB2_STATS_INC(mib2.ipreasmreqds);
|
||||||
@@ -552,24 +568,41 @@ ip4_reass(struct pbuf *p)
|
|||||||
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
|
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Track the current number of pbufs current 'in-flight', in order to limit
|
|
||||||
the number of fragments that may be enqueued at any one time */
|
|
||||||
ip_reass_pbufcount += clen;
|
|
||||||
|
|
||||||
/* At this point, we have either created a new entry or pointing
|
/* At this point, we have either created a new entry or pointing
|
||||||
* to an existing one */
|
* to an existing one */
|
||||||
|
|
||||||
/* check for 'no more fragments', and update queue entry*/
|
/* check for 'no more fragments', and update queue entry*/
|
||||||
if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
|
is_last = (IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0;
|
||||||
|
if (is_last) {
|
||||||
|
u16_t datagram_len = (u16_t)(offset + len);
|
||||||
|
if ((datagram_len < offset) || (datagram_len > (0xFFFF - IP_HLEN))) {
|
||||||
|
/* u16_t overflow, cannot handle this */
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* find the right place to insert this pbuf */
|
||||||
|
/* @todo: trim pbufs if fragments are overlapping */
|
||||||
|
valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last);
|
||||||
|
if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) {
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
/* if we come here, the pbuf has been enqueued */
|
||||||
|
|
||||||
|
/* Track the current number of pbufs current 'in-flight', in order to limit
|
||||||
|
the number of fragments that may be enqueued at any one time
|
||||||
|
(overflow checked by testing against IP_REASS_MAX_PBUFS) */
|
||||||
|
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen);
|
||||||
|
if (is_last) {
|
||||||
|
u16_t datagram_len = (u16_t)(offset + len);
|
||||||
|
ipr->datagram_len = datagram_len;
|
||||||
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
|
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
|
||||||
ipr->datagram_len = offset + len;
|
|
||||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||||
("ip4_reass: last fragment seen, total len %"S16_F"\n",
|
("ip4_reass: last fragment seen, total len %"S16_F"\n",
|
||||||
ipr->datagram_len));
|
ipr->datagram_len));
|
||||||
}
|
}
|
||||||
/* find the right place to insert this pbuf */
|
|
||||||
/* @todo: trim pbufs if fragments are overlapping */
|
if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
|
||||||
if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
|
|
||||||
struct ip_reassdata *ipr_prev;
|
struct ip_reassdata *ipr_prev;
|
||||||
/* the totally last fragment (flag more fragments = 0) was received at least
|
/* the totally last fragment (flag more fragments = 0) was received at least
|
||||||
* once AND all fragments are received */
|
* once AND all fragments are received */
|
||||||
|
|||||||
@@ -849,7 +849,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
|
|||||||
netif_poll(). */
|
netif_poll(). */
|
||||||
|
|
||||||
/* let last point to the last pbuf in chain r */
|
/* let last point to the last pbuf in chain r */
|
||||||
for (last = r; last->next != NULL; last = last->next);
|
for (last = r; last->next != NULL; last = last->next) {
|
||||||
|
/* nothing to do here, just get to the last pbuf */
|
||||||
|
}
|
||||||
|
|
||||||
SYS_ARCH_PROTECT(lev);
|
SYS_ARCH_PROTECT(lev);
|
||||||
if (netif->loop_first != NULL) {
|
if (netif->loop_first != NULL) {
|
||||||
|
|||||||
@@ -358,7 +358,6 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
|
|||||||
default:
|
default:
|
||||||
/* Has already been closed, do nothing. */
|
/* Has already been closed, do nothing. */
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == ERR_OK) {
|
if (err == ERR_OK) {
|
||||||
@@ -371,6 +370,12 @@ tcp_close_shutdown_fin(struct tcp_pcb *pcb)
|
|||||||
} else if (err == ERR_MEM) {
|
} else if (err == ERR_MEM) {
|
||||||
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */
|
/* Mark this pcb for closing. Closing is retried from tcp_tmr. */
|
||||||
pcb->flags |= TF_CLOSEPEND;
|
pcb->flags |= TF_CLOSEPEND;
|
||||||
|
/* We have to return ERR_OK from here to indicate to the callers that this
|
||||||
|
pcb should not be used any more as it will be freed soon via tcp_tmr.
|
||||||
|
This is OK here since sending FIN does not guarantee a time frime for
|
||||||
|
actually freeing the pcb, either (it is left in closure states for
|
||||||
|
remote ACK or timeout) */
|
||||||
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -408,8 +413,8 @@ tcp_close(struct tcp_pcb *pcb)
|
|||||||
* @ingroup tcp_raw
|
* @ingroup tcp_raw
|
||||||
* Causes all or part of a full-duplex connection of this PCB to be shut down.
|
* Causes all or part of a full-duplex connection of this PCB to be shut down.
|
||||||
* This doesn't deallocate the PCB unless shutting down both sides!
|
* This doesn't deallocate the PCB unless shutting down both sides!
|
||||||
* Shutting down both sides is the same as calling tcp_close, so if it succeds,
|
* Shutting down both sides is the same as calling tcp_close, so if it succeds
|
||||||
* the PCB should not be referenced any more.
|
* (i.e. returns ER_OK), the PCB must not be referenced any more!
|
||||||
*
|
*
|
||||||
* @param pcb PCB to shutdown
|
* @param pcb PCB to shutdown
|
||||||
* @param shut_rx shut down receive side if this is != 0
|
* @param shut_rx shut down receive side if this is != 0
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
|
|||||||
static void tcp_listen_input(struct tcp_pcb_listen *pcb);
|
static void tcp_listen_input(struct tcp_pcb_listen *pcb);
|
||||||
static void tcp_timewait_input(struct tcp_pcb *pcb);
|
static void tcp_timewait_input(struct tcp_pcb *pcb);
|
||||||
|
|
||||||
|
static int tcp_input_delayed_close(struct tcp_pcb *pcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
|
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
|
||||||
* the segment between the PCBs and passes it on to tcp_process(), which implements
|
* the segment between the PCBs and passes it on to tcp_process(), which implements
|
||||||
@@ -404,17 +406,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
recv_acked = 0;
|
recv_acked = 0;
|
||||||
}
|
}
|
||||||
if (recv_flags & TF_CLOSED) {
|
if (tcp_input_delayed_close(pcb)) {
|
||||||
/* The connection has been closed and we will deallocate the
|
|
||||||
PCB. */
|
|
||||||
if (!(pcb->flags & TF_RXCLOSED)) {
|
|
||||||
/* Connection closed although the application has only shut down the
|
|
||||||
tx side: call the PCB's err callback and indicate the closure to
|
|
||||||
ensure the application doesn't continue using the PCB. */
|
|
||||||
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
|
|
||||||
}
|
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
|
||||||
memp_free(MEMP_TCP_PCB, pcb);
|
|
||||||
goto aborted;
|
goto aborted;
|
||||||
}
|
}
|
||||||
#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
|
#if TCP_QUEUE_OOSEQ && LWIP_WND_SCALE
|
||||||
@@ -488,6 +480,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tcp_input_pcb = NULL;
|
tcp_input_pcb = NULL;
|
||||||
|
if (tcp_input_delayed_close(pcb)) {
|
||||||
|
goto aborted;
|
||||||
|
}
|
||||||
/* Try to send something out. */
|
/* Try to send something out. */
|
||||||
tcp_output(pcb);
|
tcp_output(pcb);
|
||||||
#if TCP_INPUT_DEBUG
|
#if TCP_INPUT_DEBUG
|
||||||
@@ -532,6 +527,30 @@ dropped:
|
|||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Called from tcp_input to check for TF_CLOSED flag. This results in closing
|
||||||
|
* and deallocating a pcb at the correct place to ensure noone references it
|
||||||
|
* any more.
|
||||||
|
* @returns 1 if the pcb has been closed and deallocated, 0 otherwise
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
tcp_input_delayed_close(struct tcp_pcb *pcb)
|
||||||
|
{
|
||||||
|
if (recv_flags & TF_CLOSED) {
|
||||||
|
/* The connection has been closed and we will deallocate the
|
||||||
|
PCB. */
|
||||||
|
if (!(pcb->flags & TF_RXCLOSED)) {
|
||||||
|
/* Connection closed although the application has only shut down the
|
||||||
|
tx side: call the PCB's err callback and indicate the closure to
|
||||||
|
ensure the application doesn't continue using the PCB. */
|
||||||
|
TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
|
||||||
|
}
|
||||||
|
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||||
|
memp_free(MEMP_TCP_PCB, pcb);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by tcp_input() when a segment arrives for a listening
|
* Called by tcp_input() when a segment arrives for a listening
|
||||||
* connection (from tcp_input()).
|
* connection (from tcp_input()).
|
||||||
@@ -1749,11 +1768,11 @@ tcp_parseopt(struct tcp_pcb *pcb)
|
|||||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_parseopt: bad length\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/* An WND_SCALE option with the right option length. */
|
||||||
|
data = tcp_getoptbyte();
|
||||||
/* If syn was received with wnd scale option,
|
/* If syn was received with wnd scale option,
|
||||||
activate wnd scale opt, but only if this is not a retransmission */
|
activate wnd scale opt, but only if this is not a retransmission */
|
||||||
if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
|
if ((flags & TCP_SYN) && !(pcb->flags & TF_WND_SCALE)) {
|
||||||
/* An WND_SCALE option with the right option length. */
|
|
||||||
data = tcp_getoptbyte();
|
|
||||||
pcb->snd_scale = data;
|
pcb->snd_scale = data;
|
||||||
if (pcb->snd_scale > 14U) {
|
if (pcb->snd_scale > 14U) {
|
||||||
pcb->snd_scale = 14U;
|
pcb->snd_scale = 14U;
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ void sys_timeouts_init(void)
|
|||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
/* tcp_tmr() at index 0 is started on demand */
|
/* tcp_tmr() at index 0 is started on demand */
|
||||||
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
|
||||||
/* we have to cast via size_t to get rid of const warning
|
/* we have to cast via size_t to get rid of const warning
|
||||||
(this is OK as cyclic_timer() casts back to const* */
|
(this is OK as cyclic_timer() casts back to const* */
|
||||||
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
|
sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
|
||||||
|
|||||||
@@ -76,8 +76,7 @@
|
|||||||
* systems, this should be defined to something less resource-consuming.
|
* systems, this should be defined to something less resource-consuming.
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_PLATFORM_DIAG
|
#ifndef LWIP_PLATFORM_DIAG
|
||||||
#include "Debug.hpp"
|
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
|
||||||
#define LWIP_PLATFORM_DIAG(x) printf(x);
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -91,14 +91,6 @@ u32_t lwip_htonl(u32_t x);
|
|||||||
#endif
|
#endif
|
||||||
#define lwip_ntohl(x) lwip_htonl(x)
|
#define lwip_ntohl(x) lwip_htonl(x)
|
||||||
|
|
||||||
/* Provide usual function names as macros for users, but this can be turned off */
|
|
||||||
#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
|
||||||
#define htons(x) lwip_htons(x)
|
|
||||||
#define ntohs(x) lwip_ntohs(x)
|
|
||||||
#define htonl(x) lwip_htonl(x)
|
|
||||||
#define ntohl(x) lwip_ntohl(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* These macros should be calculated by the preprocessor and are used
|
/* These macros should be calculated by the preprocessor and are used
|
||||||
with compile-time constants only (so that there is no little-endian
|
with compile-time constants only (so that there is no little-endian
|
||||||
overhead at runtime). */
|
overhead at runtime). */
|
||||||
@@ -109,9 +101,16 @@ u32_t lwip_htonl(u32_t x);
|
|||||||
(((x) & 0x00ff0000UL) >> 8) | \
|
(((x) & 0x00ff0000UL) >> 8) | \
|
||||||
(((x) & 0xff000000UL) >> 24))
|
(((x) & 0xff000000UL) >> 24))
|
||||||
#define PP_NTOHL(x) PP_HTONL(x)
|
#define PP_NTOHL(x) PP_HTONL(x)
|
||||||
|
|
||||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||||
|
|
||||||
|
/* Provide usual function names as macros for users, but this can be turned off */
|
||||||
|
#ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
|
||||||
|
#define htons(x) lwip_htons(x)
|
||||||
|
#define ntohs(x) lwip_ntohs(x)
|
||||||
|
#define htonl(x) lwip_htonl(x)
|
||||||
|
#define ntohl(x) lwip_ntohl(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Functions that are not available as standard implementations.
|
/* Functions that are not available as standard implementations.
|
||||||
* In cc.h, you can #define these to implementations available on
|
* In cc.h, you can #define these to implementations available on
|
||||||
* your platform to save some code bytes if you use these functions
|
* your platform to save some code bytes if you use these functions
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ struct dhcp
|
|||||||
|
|
||||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
||||||
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
||||||
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
|
#define dhcp_remove_struct(netif) netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP, NULL)
|
||||||
void dhcp_cleanup(struct netif *netif);
|
void dhcp_cleanup(struct netif *netif);
|
||||||
err_t dhcp_start(struct netif *netif);
|
err_t dhcp_start(struct netif *netif);
|
||||||
err_t dhcp_renew(struct netif *netif);
|
err_t dhcp_renew(struct netif *netif);
|
||||||
|
|||||||
@@ -43,8 +43,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LWIP_PROVIDE_ERRNO 0
|
|
||||||
|
|
||||||
#ifdef LWIP_PROVIDE_ERRNO
|
#ifdef LWIP_PROVIDE_ERRNO
|
||||||
|
|
||||||
#define EPERM 1 /* Operation not permitted */
|
#define EPERM 1 /* Operation not permitted */
|
||||||
@@ -176,13 +174,12 @@ extern "C" {
|
|||||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||||
|
|
||||||
#ifndef errno
|
#ifndef errno
|
||||||
//extern int errno;
|
extern int errno;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* LWIP_PROVIDE_ERRNO */
|
#else /* LWIP_PROVIDE_ERRNO */
|
||||||
|
|
||||||
/* Define LWIP_ERRNO_INCLUDE to <errno.h> to include the error defines here */
|
/* Define LWIP_ERRNO_INCLUDE to <errno.h> to include the error defines here */
|
||||||
#define LWIP_ERRNO_INCLUDE <errno.h>
|
|
||||||
#ifdef LWIP_ERRNO_INCLUDE
|
#ifdef LWIP_ERRNO_INCLUDE
|
||||||
#include LWIP_ERRNO_INCLUDE
|
#include LWIP_ERRNO_INCLUDE
|
||||||
#endif /* LWIP_ERRNO_INCLUDE */
|
#endif /* LWIP_ERRNO_INCLUDE */
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ extern "C" {
|
|||||||
/** x.X.x: Minor version of the stack */
|
/** x.X.x: Minor version of the stack */
|
||||||
#define LWIP_VERSION_MINOR 0
|
#define LWIP_VERSION_MINOR 0
|
||||||
/** x.x.X: Revision of the stack */
|
/** x.x.X: Revision of the stack */
|
||||||
#define LWIP_VERSION_REVISION 2
|
#define LWIP_VERSION_REVISION 3
|
||||||
/** For release candidates, this is set to 1..254
|
/** For release candidates, this is set to 1..254
|
||||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||||
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
* For development versions (Git), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
#ifndef LWIP_HDR_MEMP_H
|
#ifndef LWIP_HDR_MEMP_H
|
||||||
#define LWIP_HDR_MEMP_H
|
#define LWIP_HDR_MEMP_H
|
||||||
|
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -387,9 +387,9 @@ void stats_init(void);
|
|||||||
|
|
||||||
#if MEM_STATS
|
#if MEM_STATS
|
||||||
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
|
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
|
||||||
#define MEM_STATS_INC(x) STATS_INC(mem.x)
|
#define MEM_STATS_INC(x) SYS_ARCH_INC(lwip_stats.mem.x, 1)
|
||||||
#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y)
|
#define MEM_STATS_INC_USED(x, y) SYS_ARCH_INC(lwip_stats.mem.x, y)
|
||||||
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
|
#define MEM_STATS_DEC_USED(x, y) SYS_ARCH_DEC(lwip_stats.mem.x, y)
|
||||||
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
|
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
|
||||||
#else
|
#else
|
||||||
#define MEM_STATS_AVAIL(x, y)
|
#define MEM_STATS_AVAIL(x, y)
|
||||||
|
|||||||
154
ext/lwip/test/unit/ip4/test_ip4.c
Executable file
154
ext/lwip/test/unit/ip4/test_ip4.c
Executable file
@@ -0,0 +1,154 @@
|
|||||||
|
#include "test_ip4.h"
|
||||||
|
|
||||||
|
#include "lwip/ip4.h"
|
||||||
|
#include "lwip/inet_chksum.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
#include "lwip/prot/ip.h"
|
||||||
|
#include "lwip/prot/ip4.h"
|
||||||
|
|
||||||
|
#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
|
||||||
|
#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Helper functions */
|
||||||
|
static void
|
||||||
|
create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last)
|
||||||
|
{
|
||||||
|
struct pbuf *p;
|
||||||
|
struct netif *input_netif = netif_list; /* just use any netif */
|
||||||
|
fail_unless((start & 7) == 0);
|
||||||
|
fail_unless(((len & 7) == 0) || last);
|
||||||
|
fail_unless(input_netif != NULL);
|
||||||
|
|
||||||
|
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM);
|
||||||
|
fail_unless(p != NULL);
|
||||||
|
if (p != NULL) {
|
||||||
|
err_t err;
|
||||||
|
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
|
||||||
|
IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4);
|
||||||
|
IPH_TOS_SET(iphdr, 0);
|
||||||
|
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
|
||||||
|
IPH_ID_SET(iphdr, lwip_htons(ip_id));
|
||||||
|
if (last) {
|
||||||
|
IPH_OFFSET_SET(iphdr, lwip_htons(start / 8));
|
||||||
|
} else {
|
||||||
|
IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF));
|
||||||
|
}
|
||||||
|
IPH_TTL_SET(iphdr, 5);
|
||||||
|
IPH_PROTO_SET(iphdr, IP_PROTO_UDP);
|
||||||
|
IPH_CHKSUM_SET(iphdr, 0);
|
||||||
|
ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif));
|
||||||
|
iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1);
|
||||||
|
ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif));
|
||||||
|
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr)));
|
||||||
|
|
||||||
|
err = ip4_input(p, input_netif);
|
||||||
|
if (err != ERR_OK) {
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
fail_unless(err == ERR_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setups/teardown functions */
|
||||||
|
|
||||||
|
static void
|
||||||
|
ip4_setup(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ip4_teardown(void)
|
||||||
|
{
|
||||||
|
if (netif_list->loop_first != NULL) {
|
||||||
|
pbuf_free(netif_list->loop_first);
|
||||||
|
netif_list->loop_first = NULL;
|
||||||
|
}
|
||||||
|
netif_list->loop_last = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Test functions */
|
||||||
|
|
||||||
|
START_TEST(test_ip4_reass)
|
||||||
|
{
|
||||||
|
const u16_t ip_id = 128;
|
||||||
|
LWIP_UNUSED_ARG(_i);
|
||||||
|
|
||||||
|
memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 8*200, 200, 1);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 1);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 0*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 2);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 1*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 3);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 2*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 4);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 3*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 5);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 4*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 6);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 7*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 7);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 6*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 8);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||||
|
|
||||||
|
create_ip4_input_fragment(ip_id, 5*200, 200, 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.recv == 9);
|
||||||
|
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||||
|
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||||
|
fail_unless(lwip_stats.mib2.ipreasmoks == 1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
|
||||||
|
/** Create the suite including all tests for this module */
|
||||||
|
Suite *
|
||||||
|
ip4_suite(void)
|
||||||
|
{
|
||||||
|
testfunc tests[] = {
|
||||||
|
TESTFUNC(test_ip4_reass),
|
||||||
|
};
|
||||||
|
return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown);
|
||||||
|
}
|
||||||
8
ext/lwip/test/unit/ip4/test_ip4.h
Executable file
8
ext/lwip/test/unit/ip4/test_ip4.h
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef LWIP_HDR_TEST_IP4_H
|
||||||
|
#define LWIP_HDR_TEST_IP4_H
|
||||||
|
|
||||||
|
#include "../lwip_check.h"
|
||||||
|
|
||||||
|
Suite* ip4_suite(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "lwip_check.h"
|
#include "lwip_check.h"
|
||||||
|
|
||||||
|
#include "ip4/test_ip4.h"
|
||||||
#include "udp/test_udp.h"
|
#include "udp/test_udp.h"
|
||||||
#include "tcp/test_tcp.h"
|
#include "tcp/test_tcp.h"
|
||||||
#include "tcp/test_tcp_oos.h"
|
#include "tcp/test_tcp_oos.h"
|
||||||
@@ -37,6 +38,7 @@ int main(void)
|
|||||||
SRunner *sr;
|
SRunner *sr;
|
||||||
size_t i;
|
size_t i;
|
||||||
suite_getter_fn* suites[] = {
|
suite_getter_fn* suites[] = {
|
||||||
|
ip4_suite,
|
||||||
udp_suite,
|
udp_suite,
|
||||||
tcp_suite,
|
tcp_suite,
|
||||||
tcp_oos_suite,
|
tcp_oos_suite,
|
||||||
|
|||||||
@@ -59,4 +59,7 @@
|
|||||||
/* Minimal changes to opt.h required for etharp unit tests: */
|
/* Minimal changes to opt.h required for etharp unit tests: */
|
||||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
||||||
|
|
||||||
|
/* MIB2 stats are required to check IPv4 reassembly results */
|
||||||
|
#define MIB2_STATS 1
|
||||||
|
|
||||||
#endif /* LWIP_HDR_LWIPOPTS_H */
|
#endif /* LWIP_HDR_LWIPOPTS_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user