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.

This commit is contained in:
fbernon 2007-03-06 14:18:02 +00:00
parent 7115975212
commit ed07d481d6
6 changed files with 175 additions and 60 deletions

View File

@ -5,10 +5,6 @@ FUTURE
problems with exoteric (/DSP) architectures showing these problems. problems with exoteric (/DSP) architectures showing these problems.
We still have to fix some of these issues neatly. 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 * TODO: the PPP code is broken in a few ways. There are namespace
collisions on BSD systems and many assumptions on word-length collisions on BSD systems and many assumptions on word-length
(sizeof(int)). In ppp.c an assumption is made on the availability of (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. * api_lib.c: Use memcpy in netbuf_copy_partial.
++ Bug fixes: ++ 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) 2007-03-06 Simon Goldschmidt (based on patch from Dmitry Potapov)
* err.h, err.c: fixed compiler warning "initialization dircards qualifiers * err.h, err.c: fixed compiler warning "initialization dircards qualifiers

View File

@ -37,6 +37,8 @@
#include "lwip/memp.h" #include "lwip/memp.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "netif/etharp.h"
#include "lwip/ip.h" #include "lwip/ip.h"
#include "lwip/ip_frag.h" #include "lwip/ip_frag.h"
#include "lwip/udp.h" #include "lwip/udp.h"
@ -61,7 +63,7 @@ tcpip_tcp_timer(void *arg)
/* timer still needed? */ /* timer still needed? */
if (tcp_active_pcbs || tcp_tw_pcbs) { if (tcp_active_pcbs || tcp_tw_pcbs) {
/* restart timer */ /* restart timer */
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL); sys_timeout( TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
} else { } else {
/* disable timer */ /* disable timer */
tcpip_tcp_timer_active = 0; tcpip_tcp_timer_active = 0;
@ -76,7 +78,7 @@ tcp_timer_needed(void)
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) { if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
/* enable and start timer */ /* enable and start timer */
tcpip_tcp_timer_active = 1; 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 */ #endif /* !NO_SYS */
@ -88,18 +90,67 @@ ip_timer(void *data)
{ {
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n")); LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
ip_reass_tmr(); ip_reass_tmr();
sys_timeout(1000, ip_timer, NULL); sys_timeout( IP_TMR_INTERVAL, ip_timer, NULL);
} }
#endif #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 static void
tcpip_thread(void *arg) tcpip_thread(void *arg)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
#if IP_REASSEMBLY #if IP_REASSEMBLY
sys_timeout(1000, ip_timer, NULL); sys_timeout( IP_TMR_INTERVAL, ip_timer, NULL);
#endif #endif
sys_timeout( ARP_TMR_INTERVAL, arp_timer, NULL);
if (tcpip_init_done != NULL) { if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg); 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)); LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
api_msg_input(msg->msg.apimsg); api_msg_input(msg->msg.apimsg);
break; break;
#if ETHARP_TCPIP_INPUT
case TCPIP_MSG_INPUT: case TCPIP_MSG_INPUT:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg)); LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));
ip_input(msg->msg.inp.p, msg->msg.inp.netif); ip_input(msg->msg.inp.p, msg->msg.inp.netif);
break; 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: case TCPIP_MSG_CALLBACK:
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
msg->msg.cb.f(msg->msg.cb.ctx); msg->msg.cb.f(msg->msg.cb.ctx);
@ -126,6 +188,7 @@ tcpip_thread(void *arg)
} }
} }
#if ETHARP_TCPIP_INPUT
err_t err_t
tcpip_input(struct pbuf *p, struct netif *inp) 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); sys_mbox_post(mbox, msg);
return ERR_OK; 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 err_t
tcpip_callback(void (*f)(void *ctx), void *ctx) tcpip_callback(void (*f)(void *ctx), void *ctx)

View File

@ -39,6 +39,9 @@
#include "lwip/netif.h" #include "lwip/netif.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
/* The IP timer interval in milliseconds. */
#define IP_TMR_INTERVAL 1000
void ip_frag_init(void); void ip_frag_init(void);
void ip_reass_tmr(void); void ip_reass_tmr(void);
struct pbuf * ip_reass(struct pbuf *p); struct pbuf * ip_reass(struct pbuf *p);

View File

@ -199,6 +199,16 @@ a lot of data that needs to be copied, this should be set high. */
#define ETHARP_TRUST_IP_MAC 1 #define ETHARP_TRUST_IP_MAC 1
#endif #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 */ /* This option is deprecated */
#ifdef ETHARP_QUEUE_FIRST #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 */ /* IP reassemly default age in seconds */
#ifndef IP_REASS_MAXAGE #ifndef IP_REASS_MAXAGE
#define IP_REASS_MAXAGE 3 #define IP_REASS_MAXAGE 3
#endif #endif
/* IP reassembly buffer size (minus IP header) */ /* IP reassembly buffer size (minus IP header) */
#ifndef IP_REASS_BUFSIZE #ifndef IP_REASS_BUFSIZE
#define IP_REASS_BUFSIZE 5760 #define IP_REASS_BUFSIZE 5760
#endif #endif
/* Assumed max MTU on any interface for IP frag buffer */ /* Assumed max MTU on any interface for IP frag buffer */
#ifndef IP_FRAG_MAX_MTU #ifndef IP_FRAG_MAX_MTU
#define IP_FRAG_MAX_MTU 1500 #define IP_FRAG_MAX_MTU 1500
#endif #endif
/** Global default value for Time To Live used by transport layers. */ /** 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 ---------- */ /* ---------- ICMP options ---------- */
#ifndef ICMP_TTL #ifndef ICMP_TTL
#define ICMP_TTL (IP_DEFAULT_TTL) #define ICMP_TTL (IP_DEFAULT_TTL)
#endif #endif
/* ---------- RAW options ---------- */ /* ---------- 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. /* 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. */ It also came with many ugly goto's, Christiaan Simons. */
#error "SO_REUSE currently unavailable, this was a hack" #error "SO_REUSE currently unavailable, this was a hack"
#endif #endif
/* ---------- Statistics options ---------- */ /* ---------- Statistics options ---------- */
@ -430,67 +440,67 @@ a lot of data that needs to be copied, this should be set high. */
#if LWIP_STATS #if LWIP_STATS
#ifndef LWIP_STATS_DISPLAY #ifndef LWIP_STATS_DISPLAY
#define LWIP_STATS_DISPLAY 0 #define LWIP_STATS_DISPLAY 0
#endif #endif
#ifndef LINK_STATS #ifndef LINK_STATS
#define LINK_STATS 1 #define LINK_STATS 1
#endif #endif
#ifndef IP_STATS #ifndef IP_STATS
#define IP_STATS 1 #define IP_STATS 1
#endif #endif
#ifndef IPFRAG_STATS #ifndef IPFRAG_STATS
#define IPFRAG_STATS 1 #define IPFRAG_STATS 1
#endif #endif
#ifndef ICMP_STATS #ifndef ICMP_STATS
#define ICMP_STATS 1 #define ICMP_STATS 1
#endif #endif
#ifndef UDP_STATS #ifndef UDP_STATS
#define UDP_STATS 1 #define UDP_STATS 1
#endif #endif
#ifndef TCP_STATS #ifndef TCP_STATS
#define TCP_STATS 1 #define TCP_STATS 1
#endif #endif
#ifndef MEM_STATS #ifndef MEM_STATS
#define MEM_STATS 1 #define MEM_STATS 1
#endif #endif
#ifndef MEMP_STATS #ifndef MEMP_STATS
#define MEMP_STATS 1 #define MEMP_STATS 1
#endif #endif
#ifndef PBUF_STATS #ifndef PBUF_STATS
#define PBUF_STATS 1 #define PBUF_STATS 1
#endif #endif
#ifndef SYS_STATS #ifndef SYS_STATS
#define SYS_STATS 1 #define SYS_STATS 1
#endif #endif
#ifndef RAW_STATS #ifndef RAW_STATS
#define RAW_STATS 0 #define RAW_STATS 0
#endif #endif
#else #else
#define LINK_STATS 0 #define LINK_STATS 0
#define IP_STATS 0 #define IP_STATS 0
#define IPFRAG_STATS 0 #define IPFRAG_STATS 0
#define ICMP_STATS 0 #define ICMP_STATS 0
#define UDP_STATS 0 #define UDP_STATS 0
#define TCP_STATS 0 #define TCP_STATS 0
#define MEM_STATS 0 #define MEM_STATS 0
#define MEMP_STATS 0 #define MEMP_STATS 0
#define PBUF_STATS 0 #define PBUF_STATS 0
#define SYS_STATS 0 #define SYS_STATS 0
#define RAW_STATS 0 #define RAW_STATS 0
#define LWIP_STATS_DISPLAY 0 #define LWIP_STATS_DISPLAY 0
#endif /* LWIP_STATS */ #endif /* LWIP_STATS */

View File

@ -37,14 +37,24 @@
void tcpip_init(void (* tcpip_init_done)(void *), void *arg); void tcpip_init(void (* tcpip_init_done)(void *), void *arg);
void tcpip_apimsg(struct api_msg *apimsg); void tcpip_apimsg(struct api_msg *apimsg);
#if ETHARP_TCPIP_INPUT
err_t tcpip_input(struct pbuf *p, struct netif *inp); 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); err_t tcpip_callback(void (*f)(void *ctx), void *ctx);
void tcpip_tcp_timer_needed(void); void tcpip_tcp_timer_needed(void);
enum tcpip_msg_type { enum tcpip_msg_type {
TCPIP_MSG_API, TCPIP_MSG_API,
#if ETHARP_TCPIP_INPUT
TCPIP_MSG_INPUT, TCPIP_MSG_INPUT,
#endif /* ETHARP_TCPIP_INPUT */
#if ETHARP_TCPIP_ETHINPUT
TCPIP_MSG_ETHINPUT,
#endif /* ETHARP_TCPIP_ETHINPUT */
TCPIP_MSG_CALLBACK TCPIP_MSG_CALLBACK
}; };

View File

@ -237,36 +237,44 @@ ethernetif_input(struct netif *netif)
ethhdr = p->payload; ethhdr = p->payload;
switch (htons(ethhdr->type)) { 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? */ /* IP packet? */
case ETHTYPE_IP: case ETHTYPE_IP:
#if 0 #if ETHARP_TRUST_IP_MAC
/* CSi disabled ARP table update on ingress IP packets.
This seems to work but needs thorough testing. */
/* update ARP table */ /* update ARP table */
etharp_ip_input(netif, p); etharp_ip_input(netif, p);
#endif #endif /* ETHARP_TRUST_IP_MAC */
/* skip Ethernet header */ /* skip Ethernet header */
pbuf_header(p, -sizeof(struct eth_hdr)); pbuf_header(p, -sizeof(struct eth_hdr));
/* pass to network layer */ /* pass to network layer */
netif->input(p, netif); netif->input(p, netif);
break; break;
case ETHTYPE_ARP: /* ARP packet? */
/* pass p to ARP module */ case ETHTYPE_ARP:
etharp_arp_input(netif, ethernetif->ethaddr, p); /* pass p to ARP module */
break; etharp_arp_input(netif, ethernetif->ethaddr, p);
default: break;
pbuf_free(p);
p = NULL; #endif /* ETHARP_TCPIP_INPUT */
break; #endif /* ETHARP_TCPIP_ETHINPUT */
}
}
static void default:
arp_timer(void *arg) pbuf_free(p);
{ p = NULL;
etharp_tmr(); break;
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL); }
} }
/* /*
@ -317,10 +325,6 @@ ethernetif_init(struct netif *netif)
low_level_init(netif); low_level_init(netif);
etharp_init();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
return ERR_OK; return ERR_OK;
} }