From ed07d481d64405ff7875219697c3d3c840aa1749 Mon Sep 17 00:00:00 2001 From: fbernon Date: Tue, 6 Mar 2007 14:18:02 +0000 Subject: [PATCH] opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. Allow to do ARP processing for incoming packets inside tcpip_thread (protecting ARP layer against concurrent access). You can also disable old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. Older ports have to use tcpip_ethinput. --- CHANGELOG | 12 +++-- src/api/tcpip.c | 92 +++++++++++++++++++++++++++++++-- src/include/ipv4/lwip/ip_frag.h | 3 ++ src/include/lwip/opt.h | 68 +++++++++++++----------- src/include/lwip/tcpip.h | 10 ++++ src/netif/ethernetif.c | 50 +++++++++--------- 6 files changed, 175 insertions(+), 60 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 3515db96..bf72e831 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,10 +5,6 @@ FUTURE problems with exoteric (/DSP) architectures showing these problems. We still have to fix some of these issues neatly. - * TODO: the ARP layer is not protected against concurrent access. If - you run from a multitasking OS, serialize access to ARP (called from - your network device driver and from a timeout thread.) - * TODO: the PPP code is broken in a few ways. There are namespace collisions on BSD systems and many assumptions on word-length (sizeof(int)). In ppp.c an assumption is made on the availability of @@ -41,6 +37,14 @@ HISTORY * api_lib.c: Use memcpy in netbuf_copy_partial. ++ Bug fixes: + + 2007-03-06 Frédéric Bernon, Simon Goldschmidt + * opt.h, ip_frag.h, tcpip.h, tcpip.c, ethernetif.c: add new configuration + option named ETHARP_TCPIP_ETHINPUT, which enable the new tcpip_ethinput. + Allow to do ARP processing for incoming packets inside tcpip_thread + (protecting ARP layer against concurrent access). You can also disable + old code using tcp_input with new define ETHARP_TCPIP_INPUT set to 0. + Older ports have to use tcpip_ethinput. 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov) * err.h, err.c: fixed compiler warning "initialization dircards qualifiers diff --git a/src/api/tcpip.c b/src/api/tcpip.c index bb4445ae..1e5765ae 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -37,6 +37,8 @@ #include "lwip/memp.h" #include "lwip/pbuf.h" +#include "netif/etharp.h" + #include "lwip/ip.h" #include "lwip/ip_frag.h" #include "lwip/udp.h" @@ -61,7 +63,7 @@ tcpip_tcp_timer(void *arg) /* timer still needed? */ if (tcp_active_pcbs || tcp_tw_pcbs) { /* restart timer */ - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + sys_timeout( TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); } else { /* disable timer */ tcpip_tcp_timer_active = 0; @@ -76,7 +78,7 @@ tcp_timer_needed(void) if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { /* enable and start timer */ tcpip_tcp_timer_active = 1; - sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); + sys_timeout( TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); } } #endif /* !NO_SYS */ @@ -88,18 +90,67 @@ ip_timer(void *data) { LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n")); ip_reass_tmr(); - sys_timeout(1000, ip_timer, NULL); + sys_timeout( IP_TMR_INTERVAL, ip_timer, NULL); } #endif +static void +arp_timer(void *arg) +{ + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n")); + etharp_tmr(); + sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL); +} + +#if ETHARP_TCPIP_ETHINPUT +static void +ethernet_input(struct pbuf *p, struct netif *netif) +{ + struct eth_hdr* ethhdr; + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + +#if LINK_STATS + lwip_stats.link.recv++; +#endif /* LINK_STATS */ + + switch (htons(ethhdr->type)) { + /* IP packet? */ + case ETHTYPE_IP: + #if ETHARP_TRUST_IP_MAC + /* update ARP table */ + etharp_ip_input( netif, p); + #endif + /* skip Ethernet header */ + pbuf_header(p, -sizeof(struct eth_hdr)); + /* pass to IP layer */ + ip_input(p, netif); + break; + + case ETHTYPE_ARP: + /* pass p to ARP module */ + etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); + break; + + default: + pbuf_free(p); + p = NULL; + break; + } +} +#endif /* ETHARP_TCPIP_ETHINPUT */ + static void tcpip_thread(void *arg) { struct tcpip_msg *msg; #if IP_REASSEMBLY - sys_timeout(1000, ip_timer, NULL); + sys_timeout( IP_TMR_INTERVAL, ip_timer, NULL); #endif + sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL); + if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } @@ -111,10 +162,21 @@ tcpip_thread(void *arg) LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); api_msg_input(msg->msg.apimsg); break; + +#if ETHARP_TCPIP_INPUT case TCPIP_MSG_INPUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg)); ip_input(msg->msg.inp.p, msg->msg.inp.netif); break; +#endif /* ETHARP_TCPIP_INPUT */ + +#if ETHARP_TCPIP_ETHINPUT + case TCPIP_MSG_ETHINPUT: + LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Ethernet packet %p\n", (void *)msg)); + ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); + break; +#endif /* ETHARP_TCPIP_ETHINPUT */ + case TCPIP_MSG_CALLBACK: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); msg->msg.cb.f(msg->msg.cb.ctx); @@ -126,6 +188,7 @@ tcpip_thread(void *arg) } } +#if ETHARP_TCPIP_INPUT err_t tcpip_input(struct pbuf *p, struct netif *inp) { @@ -143,6 +206,27 @@ tcpip_input(struct pbuf *p, struct netif *inp) sys_mbox_post(mbox, msg); return ERR_OK; } +#endif /* ETHARP_TCPIP_INPUT */ + +#if ETHARP_TCPIP_ETHINPUT +err_t +tcpip_ethinput(struct pbuf *p, struct netif *inp) +{ + struct tcpip_msg *msg; + + msg = memp_malloc(MEMP_TCPIP_MSG); + if (msg == NULL) { + pbuf_free(p); + return ERR_MEM; + } + + msg->type = TCPIP_MSG_ETHINPUT; + msg->msg.inp.p = p; + msg->msg.inp.netif = inp; + sys_mbox_post(mbox, msg); + return ERR_OK; +} +#endif /* ETHARP_TCPIP_ETHINPUT */ err_t tcpip_callback(void (*f)(void *ctx), void *ctx) diff --git a/src/include/ipv4/lwip/ip_frag.h b/src/include/ipv4/lwip/ip_frag.h index a326c1ce..6153aa13 100644 --- a/src/include/ipv4/lwip/ip_frag.h +++ b/src/include/ipv4/lwip/ip_frag.h @@ -39,6 +39,9 @@ #include "lwip/netif.h" #include "lwip/ip_addr.h" +/* The IP timer interval in milliseconds. */ +#define IP_TMR_INTERVAL 1000 + void ip_frag_init(void); void ip_reass_tmr(void); struct pbuf * ip_reass(struct pbuf *p); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 46972e86..665a3b57 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -199,6 +199,16 @@ a lot of data that needs to be copied, this should be set high. */ #define ETHARP_TRUST_IP_MAC 1 #endif +/* If enabled, allow to do ARP processing for incoming packets inside network driver, before process packets using the tcpip_input. */ +#ifndef ETHARP_TCPIP_INPUT +#define ETHARP_TCPIP_INPUT 1 +#endif + +/* If enabled, allow to do ARP processing for incoming packets inside tcpip_thread, using the tcpip_ethinput (and not tcpip_input). + The aim is to protect ARP layer against concurrent access. Older ports have to be update to use tcpip_ethinput. */ +#ifndef ETHARP_TCPIP_ETHINPUT +#define ETHARP_TCPIP_ETHINPUT 1 +#endif /* This option is deprecated */ #ifdef ETHARP_QUEUE_FIRST @@ -241,17 +251,17 @@ a lot of data that needs to be copied, this should be set high. */ /* IP reassemly default age in seconds */ #ifndef IP_REASS_MAXAGE -#define IP_REASS_MAXAGE 3 +#define IP_REASS_MAXAGE 3 #endif /* IP reassembly buffer size (minus IP header) */ #ifndef IP_REASS_BUFSIZE -#define IP_REASS_BUFSIZE 5760 +#define IP_REASS_BUFSIZE 5760 #endif /* Assumed max MTU on any interface for IP frag buffer */ #ifndef IP_FRAG_MAX_MTU -#define IP_FRAG_MAX_MTU 1500 +#define IP_FRAG_MAX_MTU 1500 #endif /** Global default value for Time To Live used by transport layers. */ @@ -262,7 +272,7 @@ a lot of data that needs to be copied, this should be set high. */ /* ---------- ICMP options ---------- */ #ifndef ICMP_TTL -#define ICMP_TTL (IP_DEFAULT_TTL) +#define ICMP_TTL (IP_DEFAULT_TTL) #endif /* ---------- RAW options ---------- */ @@ -419,7 +429,7 @@ a lot of data that needs to be copied, this should be set high. */ /* I removed the lot since this was an ugly hack. It broke the raw-API. It also came with many ugly goto's, Christiaan Simons. */ #error "SO_REUSE currently unavailable, this was a hack" -#endif +#endif /* ---------- Statistics options ---------- */ @@ -430,67 +440,67 @@ a lot of data that needs to be copied, this should be set high. */ #if LWIP_STATS #ifndef LWIP_STATS_DISPLAY -#define LWIP_STATS_DISPLAY 0 +#define LWIP_STATS_DISPLAY 0 #endif #ifndef LINK_STATS -#define LINK_STATS 1 +#define LINK_STATS 1 #endif #ifndef IP_STATS -#define IP_STATS 1 +#define IP_STATS 1 #endif #ifndef IPFRAG_STATS -#define IPFRAG_STATS 1 +#define IPFRAG_STATS 1 #endif #ifndef ICMP_STATS -#define ICMP_STATS 1 +#define ICMP_STATS 1 #endif #ifndef UDP_STATS -#define UDP_STATS 1 +#define UDP_STATS 1 #endif #ifndef TCP_STATS -#define TCP_STATS 1 +#define TCP_STATS 1 #endif #ifndef MEM_STATS -#define MEM_STATS 1 +#define MEM_STATS 1 #endif #ifndef MEMP_STATS -#define MEMP_STATS 1 +#define MEMP_STATS 1 #endif #ifndef PBUF_STATS -#define PBUF_STATS 1 +#define PBUF_STATS 1 #endif #ifndef SYS_STATS -#define SYS_STATS 1 +#define SYS_STATS 1 #endif #ifndef RAW_STATS -#define RAW_STATS 0 +#define RAW_STATS 0 #endif #else -#define LINK_STATS 0 -#define IP_STATS 0 -#define IPFRAG_STATS 0 -#define ICMP_STATS 0 -#define UDP_STATS 0 -#define TCP_STATS 0 -#define MEM_STATS 0 -#define MEMP_STATS 0 -#define PBUF_STATS 0 -#define SYS_STATS 0 -#define RAW_STATS 0 -#define LWIP_STATS_DISPLAY 0 +#define LINK_STATS 0 +#define IP_STATS 0 +#define IPFRAG_STATS 0 +#define ICMP_STATS 0 +#define UDP_STATS 0 +#define TCP_STATS 0 +#define MEM_STATS 0 +#define MEMP_STATS 0 +#define PBUF_STATS 0 +#define SYS_STATS 0 +#define RAW_STATS 0 +#define LWIP_STATS_DISPLAY 0 #endif /* LWIP_STATS */ diff --git a/src/include/lwip/tcpip.h b/src/include/lwip/tcpip.h index 316ae4fc..0bbe694f 100644 --- a/src/include/lwip/tcpip.h +++ b/src/include/lwip/tcpip.h @@ -37,14 +37,24 @@ void tcpip_init(void (* tcpip_init_done)(void *), void *arg); void tcpip_apimsg(struct api_msg *apimsg); +#if ETHARP_TCPIP_INPUT err_t tcpip_input(struct pbuf *p, struct netif *inp); +#endif /* ETHARP_TCPIP_INPUT */ +#if ETHARP_TCPIP_ETHINPUT +err_t tcpip_ethinput(struct pbuf *p, struct netif *inp); +#endif /* ETHARP_TCPIP_ETHINPUT */ err_t tcpip_callback(void (*f)(void *ctx), void *ctx); void tcpip_tcp_timer_needed(void); enum tcpip_msg_type { TCPIP_MSG_API, +#if ETHARP_TCPIP_INPUT TCPIP_MSG_INPUT, +#endif /* ETHARP_TCPIP_INPUT */ +#if ETHARP_TCPIP_ETHINPUT + TCPIP_MSG_ETHINPUT, +#endif /* ETHARP_TCPIP_ETHINPUT */ TCPIP_MSG_CALLBACK }; diff --git a/src/netif/ethernetif.c b/src/netif/ethernetif.c index 87d59179..8fb6dbf5 100644 --- a/src/netif/ethernetif.c +++ b/src/netif/ethernetif.c @@ -237,36 +237,44 @@ ethernetif_input(struct netif *netif) ethhdr = p->payload; switch (htons(ethhdr->type)) { + +#if ETHARP_TCPIP_ETHINPUT + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_ARP: + /* full packet send to tcpip_thread to process */ + pnetif->input( p, pnetif); + break; + +#else /* ETHARP_TCPIP_ETHINPUT */ +#if ETHARP_TCPIP_INPUT + /* IP packet? */ case ETHTYPE_IP: -#if 0 -/* CSi disabled ARP table update on ingress IP packets. - This seems to work but needs thorough testing. */ +#if ETHARP_TRUST_IP_MAC /* update ARP table */ etharp_ip_input(netif, p); -#endif +#endif /* ETHARP_TRUST_IP_MAC */ /* skip Ethernet header */ pbuf_header(p, -sizeof(struct eth_hdr)); /* pass to network layer */ netif->input(p, netif); break; - case ETHTYPE_ARP: - /* pass p to ARP module */ - etharp_arp_input(netif, ethernetif->ethaddr, p); - break; - default: - pbuf_free(p); - p = NULL; - break; - } -} + /* ARP packet? */ + case ETHTYPE_ARP: + /* pass p to ARP module */ + etharp_arp_input(netif, ethernetif->ethaddr, p); + break; + +#endif /* ETHARP_TCPIP_INPUT */ +#endif /* ETHARP_TCPIP_ETHINPUT */ -static void -arp_timer(void *arg) -{ - etharp_tmr(); - sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); + default: + pbuf_free(p); + p = NULL; + break; + } } /* @@ -317,10 +325,6 @@ ethernetif_init(struct netif *netif) low_level_init(netif); - etharp_init(); - - sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); - return ERR_OK; }