From eba83ab740bc3f804badef86c2f3cf576bb2bcb2 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Tue, 17 Jun 2008 19:39:22 +0000 Subject: [PATCH] Changed loopback code (less difference between NO_SYS = 0 / 1), added setting LWIP_LOOPBACK_MAX_PBUFS to limit loopback-queued pbufs --- CHANGELOG | 1 + src/core/ipv4/ip.c | 4 +- src/core/netif.c | 92 +++++++++++++++++++++++++--------------- src/include/lwip/netif.h | 10 +++-- src/include/lwip/opt.h | 8 ++++ 5 files changed, 75 insertions(+), 40 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6af7c072..1ae3fae9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,7 @@ HISTORY * netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly modified version of patch # 6370: Moved loopif code to netif.c so that loopback traffic is supported on all netifs (all local IPs). + Added option to limit loopback packets for each netifs. ++ Bugfixes: diff --git a/src/core/ipv4/ip.c b/src/core/ipv4/ip.c index 696217b0..f74f423e 100644 --- a/src/core/ipv4/ip.c +++ b/src/core/ipv4/ip.c @@ -531,14 +531,14 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num)); ip_debug_print(p); -#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) && !LWIP_NETIF_LOOPBACK_MULTITHREADING +#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) if (ip_addr_cmp(dest, &netif->ip_addr)) { /* Packet to self, enqueue it for loopback */ LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); return netif_loop_output(netif, p, dest); } else -#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) && !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) */ { LWIP_DEBUGF(IP_DEBUG, ("netif->output()")); diff --git a/src/core/netif.c b/src/core/netif.c index 4ab1f8a6..84ff165b 100644 --- a/src/core/netif.c +++ b/src/core/netif.c @@ -47,6 +47,8 @@ #include "netif/etharp.h" #if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING #include "lwip/sys.h" +#else /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#include "lwip/tcpip.h" #endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */ #if LWIP_NETIF_STATUS_CALLBACK @@ -109,10 +111,10 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, #if LWIP_IGMP netif->igmp_mac_filter = NULL; #endif /* LWIP_IGMP */ -#if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING +#if ENABLE_LOOPBACK netif->loop_first = NULL; netif->loop_last = NULL; -#endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#endif /* ENABLE_LOOPBACK */ /* remember netif specific state information data */ netif->state = state; @@ -121,6 +123,10 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, #if LWIP_NETIF_HWADDRHINT netif->addr_hint = NULL; #endif /* LWIP_NETIF_HWADDRHINT*/ +#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS + netif->loop_cnt_max = LWIP_LOOPBACK_MAX_PBUFS; + netif->loop_cnt_current = 0; +#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ netif_set_addr(netif, ipaddr, netmask, gw); @@ -500,8 +506,9 @@ u8_t netif_is_link_up(struct netif *netif) */ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif )) { - if ( netif ) - netif->link_callback = link_callback; + if (netif) { + netif->link_callback = link_callback; + } } #endif /* LWIP_NETIF_LINK_CALLBACK */ @@ -526,10 +533,11 @@ netif_loop_output(struct netif *netif, struct pbuf *p, { struct pbuf *r; err_t err; -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING struct pbuf *last; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = 0; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ SYS_ARCH_DECL_PROTECT(lev); -#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ LWIP_UNUSED_ARG(ipaddr); /* Allocate a new pbuf */ @@ -537,6 +545,17 @@ netif_loop_output(struct netif *netif, struct pbuf *p, if (r == NULL) { return ERR_MEM; } +#if LWIP_LOOPBACK_MAX_PBUFS + clen = pbuf_clen(r); + /* check for overflow or too many pbuf on queue */ + if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || + ((netif->loop_cnt_current + clen) > netif->loop_cnt_max)) { + pbuf_free(r); + r = NULL; + return ERR_MEM; + } + netif->loop_cnt_current += clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ /* Copy the whole pbuf queue p into the single pbuf r */ if ((err = pbuf_copy(r, p)) != ERR_OK) { @@ -545,21 +564,12 @@ netif_loop_output(struct netif *netif, struct pbuf *p, return err; } -#if LWIP_NETIF_LOOPBACK_MULTITHREADING - /* Multithreading environment, netif->input() is supposed to put the packet - into a mailbox, so we can safely call it here without risking to re-enter - functions that are not reentrant (TCP!!!) */ - LWIP_ASSERT(netif->input != ip_input, "Don't use ip_input as netif->input with LWIP_NETIF_LOOPBACK_MULTITHREADING = 1!"); - if(netif->input(r, netif) != ERR_OK) { - pbuf_free(r); - r = NULL; - } -#else /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ - /* Raw API without threads: put the packet on a linked list which gets emptied - through calling netif_poll(). */ + /* Put the packet on a linked list which gets emptied through calling + netif_poll(). */ /* let last point to the last pbuf in chain r */ for (last = r; last->next != NULL; last = last->next); + SYS_ARCH_PROTECT(lev); if(netif->loop_first != NULL) { LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); @@ -570,27 +580,15 @@ netif_loop_output(struct netif *netif, struct pbuf *p, netif->loop_last = last; } SYS_ARCH_UNPROTECT(lev); + +#if LWIP_NETIF_LOOPBACK_MULTITHREADING + /* For multithreading environment, schedule a call to netif_poll */ + tcpip_callback(netif_poll, netif); #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ return ERR_OK; } -#if !LWIP_NETIF_LOOPBACK_MULTITHREADING -/** - * Calls netif_poll() for every netif on the netif_list. - */ -void -netif_poll_all(void) -{ - struct netif *netif = netif_list; - /* loop through netifs */ - while (netif != NULL) { - netif_poll(netif); - /* proceed to next network interface */ - netif = netif->next; - } -} - /** * Call netif_poll() in the main loop of your application. This is to prevent * reentering non-reentrant functions like tcp_input(). Packets passed to @@ -609,6 +607,13 @@ netif_poll(struct netif *netif) in = netif->loop_first; if(in != NULL) { struct pbuf *in_end = in; +#if LWIP_LOOPBACK_MAX_PBUFS + u8_t clen = pbuf_clen(in); + /* adjust the number of pbufs on queue */ + LWIP_ASSERT("netif->loop_cnt_current underflow", + ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); + netif->loop_cnt_current -= clen; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ while(in_end->len != in_end->tot_len) { LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); in_end = in_end->next; @@ -628,7 +633,8 @@ netif_poll(struct netif *netif) SYS_ARCH_UNPROTECT(lev); if(in != NULL) { - if(netif->input(in, netif) != ERR_OK) { + /* loopback packets are always IP packets! */ + if(ip_input(in, netif) != ERR_OK) { pbuf_free(in); } /* Don't reference the packet any more! */ @@ -637,5 +643,21 @@ netif_poll(struct netif *netif) /* go on while there is a packet on the list */ } while(netif->loop_first != NULL); } + +#if !LWIP_NETIF_LOOPBACK_MULTITHREADING +/** + * Calls netif_poll() for every netif on the netif_list. + */ +void +netif_poll_all(void) +{ + struct netif *netif = netif_list; + /* loop through netifs */ + while (netif != NULL) { + netif_poll(netif); + /* proceed to next network interface */ + netif = netif->next; + } +} #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* ENABLE_LOOPBACK */ diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h index b8dbfcde..012e65a2 100644 --- a/src/include/lwip/netif.h +++ b/src/include/lwip/netif.h @@ -167,11 +167,15 @@ struct netif { #if LWIP_NETIF_HWADDRHINT u8_t *addr_hint; #endif /* LWIP_NETIF_HWADDRHINT */ -#if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING +#if ENABLE_LOOPBACK /* List of packets to be queued for ourselves. */ struct pbuf *loop_first; struct pbuf *loop_last; -#endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */ +#if LWIP_LOOPBACK_MAX_PBUFS + u16_t loop_cnt_max; + u16_t loop_cnt_current; +#endif /* LWIP_LOOPBACK_MAX_PBUFS */ +#endif /* ENABLE_LOOPBACK */ }; #if LWIP_SNMP @@ -251,9 +255,9 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct #if ENABLE_LOOPBACK err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip); +void netif_poll(struct netif *netif); #if !LWIP_NETIF_LOOPBACK_MULTITHREADING void netif_poll_all(void); -void netif_poll(struct netif *netif); #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ #endif /* ENABLE_LOOPBACK */ diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 7f45eabd..f362b0b1 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -840,6 +840,14 @@ #define LWIP_NETIF_LOOPBACK 0 #endif +/** + * LWIP_LOOPBACK_MAX_PBUFS: Maximum number of pbufs on queue for loopback + * sending for each netif (0 = disabled) + */ +#ifndef LWIP_LOOPBACK_MAX_PBUFS +#define LWIP_LOOPBACK_MAX_PBUFS 0 +#endif + /** * LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in * the system, as netifs must change how they behave depending on this setting