diff options
Diffstat (limited to 'core/lwip/src/core/netif.c')
-rw-r--r-- | core/lwip/src/core/netif.c | 305 |
1 files changed, 188 insertions, 117 deletions
diff --git a/core/lwip/src/core/netif.c b/core/lwip/src/core/netif.c index b52cd02a..f190b1f2 100644 --- a/core/lwip/src/core/netif.c +++ b/core/lwip/src/core/netif.c @@ -41,10 +41,11 @@ #include "lwip/def.h" #include "lwip/ip_addr.h" #include "lwip/netif.h" -#include "lwip/tcp.h" +#include "lwip/tcp_impl.h" #include "lwip/snmp.h" #include "lwip/igmp.h" #include "netif/etharp.h" +#include "lwip/stats.h" #if ENABLE_LOOPBACK #include "lwip/sys.h" #if LWIP_NETIF_LOOPBACK_MULTITHREADING @@ -60,20 +61,64 @@ #endif /* LWIP_DHCP */ #if LWIP_NETIF_STATUS_CALLBACK -#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); } +#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) #else -#define NETIF_STATUS_CALLBACK(n) { /* NOP */ } +#define NETIF_STATUS_CALLBACK(n) #endif /* LWIP_NETIF_STATUS_CALLBACK */ #if LWIP_NETIF_LINK_CALLBACK -#define NETIF_LINK_CALLBACK(n) { if (n->link_callback) (n->link_callback)(n); } +#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) #else -#define NETIF_LINK_CALLBACK(n) { /* NOP */ } +#define NETIF_LINK_CALLBACK(n) #endif /* LWIP_NETIF_LINK_CALLBACK */ struct netif *netif_list; struct netif *netif_default; +#if LWIP_HAVE_LOOPIF +static struct netif loop_netif; + +/** + * Initialize a lwip network interface structure for a loopback interface + * + * @param netif the lwip network interface structure for this loopif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + */ +static err_t +netif_loopif_init(struct netif *netif) +{ + /* initialize the snmp variables and counters inside the struct netif + * ifSpeed: no assumption can be made! + */ + NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); + + netif->name[0] = 'l'; + netif->name[1] = 'o'; + netif->output = netif_loop_output; + return ERR_OK; +} +#endif /* LWIP_HAVE_LOOPIF */ + +void +netif_init(void) +{ +#if LWIP_HAVE_LOOPIF + ip_addr_t loop_ipaddr, loop_netmask, loop_gw; + IP4_ADDR(&loop_gw, 127,0,0,1); + IP4_ADDR(&loop_ipaddr, 127,0,0,1); + IP4_ADDR(&loop_netmask, 255,0,0,0); + +#if NO_SYS + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); +#else /* NO_SYS */ + netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); +#endif /* NO_SYS */ + netif_set_up(&loop_netif); + +#endif /* LWIP_HAVE_LOOPIF */ +} + /** * Add a network interface to the list of lwIP netifs. * @@ -89,18 +134,17 @@ struct netif *netif_default; * @return netif, or NULL if failed. */ struct netif * -netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, - struct ip_addr *gw, - void *state, - err_t (* init)(struct netif *netif), - err_t (* input)(struct pbuf *p, struct netif *netif)) +netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input) { static u8_t netifnum = 0; + LWIP_ASSERT("No init function given", init != NULL); + /* reset new interface configuration state */ - netif->ip_addr.addr = 0; - netif->netmask.addr = 0; - netif->gw.addr = 0; + ip_addr_set_zero(&netif->ip_addr); + ip_addr_set_zero(&netif->netmask); + ip_addr_set_zero(&netif->gw); netif->flags = 0; #if LWIP_DHCP /* netif not under DHCP control by default */ @@ -150,7 +194,7 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, #if LWIP_IGMP /* start IGMP processing */ if (netif->flags & NETIF_FLAG_IGMP) { - igmp_start( netif); + igmp_start(netif); } #endif /* LWIP_IGMP */ @@ -175,8 +219,8 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, * @param gw the new default gateway */ void -netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, - struct ip_addr *gw) +netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, + ip_addr_t *gw) { netif_set_ipaddr(netif, ipaddr); netif_set_netmask(netif, netmask); @@ -188,41 +232,47 @@ netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netm * * @param netif the network interface to remove */ -void netif_remove(struct netif * netif) +void +netif_remove(struct netif *netif) { - if ( netif == NULL ) return; + if (netif == NULL) { + return; + } #if LWIP_IGMP /* stop IGMP processing */ if (netif->flags & NETIF_FLAG_IGMP) { - igmp_stop( netif); + igmp_stop(netif); } #endif /* LWIP_IGMP */ + if (netif_is_up(netif)) { + /* set netif down before removing (call callback function) */ + netif_set_down(netif); + } snmp_delete_ipaddridx_tree(netif); /* is it the first netif? */ if (netif_list == netif) { netif_list = netif->next; - snmp_dec_iflist(); - } - else { + } else { /* look for netif further down the list */ struct netif * tmpNetif; for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { if (tmpNetif->next == netif) { tmpNetif->next = netif->next; - snmp_dec_iflist(); break; } } if (tmpNetif == NULL) return; /* we didn't find any netif today */ } + snmp_dec_iflist(); /* this netif is default? */ - if (netif_default == netif) + if (netif_default == netif) { /* reset default netif */ netif_set_default(NULL); + } LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); } @@ -266,7 +316,7 @@ netif_find(char *name) * default gateway */ void -netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) +netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) { /* TODO: Handling of obsolete pcbs */ /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ @@ -275,14 +325,18 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) struct tcp_pcb_listen *lpcb; /* address is actually being changed? */ - if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) - { + if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); pcb = tcp_active_pcbs; while (pcb != NULL) { /* PCB bound to current local interface address? */ - if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { + if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr)) +#if LWIP_AUTOIP + /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ + && !ip_addr_islinklocal(&(pcb->local_ip)) +#endif /* LWIP_AUTOIP */ + ) { /* this connection must be aborted */ struct tcp_pcb *next = pcb->next; LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); @@ -312,10 +366,10 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], - ip4_addr1(&netif->ip_addr), - ip4_addr2(&netif->ip_addr), - ip4_addr3(&netif->ip_addr), - ip4_addr4(&netif->ip_addr))); + ip4_addr1_16(&netif->ip_addr), + ip4_addr2_16(&netif->ip_addr), + ip4_addr3_16(&netif->ip_addr), + ip4_addr4_16(&netif->ip_addr))); } /** @@ -327,15 +381,15 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) * @note call netif_set_addr() if you also want to change ip address and netmask */ void -netif_set_gw(struct netif *netif, struct ip_addr *gw) +netif_set_gw(struct netif *netif, ip_addr_t *gw) { ip_addr_set(&(netif->gw), gw); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], - ip4_addr1(&netif->gw), - ip4_addr2(&netif->gw), - ip4_addr3(&netif->gw), - ip4_addr4(&netif->gw))); + ip4_addr1_16(&netif->gw), + ip4_addr2_16(&netif->gw), + ip4_addr3_16(&netif->gw), + ip4_addr4_16(&netif->gw))); } /** @@ -348,7 +402,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw) * default gateway */ void -netif_set_netmask(struct netif *netif, struct ip_addr *netmask) +netif_set_netmask(struct netif *netif, ip_addr_t *netmask) { snmp_delete_iprteidx_tree(0, netif); /* set new netmask to netif */ @@ -356,10 +410,10 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask) snmp_insert_iprteidx_tree(0, netif); LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", netif->name[0], netif->name[1], - ip4_addr1(&netif->netmask), - ip4_addr2(&netif->netmask), - ip4_addr3(&netif->netmask), - ip4_addr4(&netif->netmask))); + ip4_addr1_16(&netif->netmask), + ip4_addr2_16(&netif->netmask), + ip4_addr3_16(&netif->netmask), + ip4_addr4_16(&netif->netmask))); } /** @@ -371,13 +425,10 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask) void netif_set_default(struct netif *netif) { - if (netif == NULL) - { + if (netif == NULL) { /* remove default route */ snmp_delete_iprteidx_tree(1, netif); - } - else - { + } else { /* install default route */ snmp_insert_iprteidx_tree(1, netif); } @@ -397,29 +448,30 @@ netif_set_default(struct netif *netif) */ void netif_set_up(struct netif *netif) { - if ( !(netif->flags & NETIF_FLAG_UP )) { + if (!(netif->flags & NETIF_FLAG_UP)) { netif->flags |= NETIF_FLAG_UP; #if LWIP_SNMP snmp_get_sysuptime(&netif->ts); #endif /* LWIP_SNMP */ - NETIF_LINK_CALLBACK(netif); NETIF_STATUS_CALLBACK(netif); + if (netif->flags & NETIF_FLAG_LINK_UP) { #if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ - if (netif->flags & NETIF_FLAG_ETHARP) { - etharp_gratuitous(netif); - } + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & (NETIF_FLAG_ETHARP)) { + etharp_gratuitous(netif); + } #endif /* LWIP_ARP */ #if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups( netif); - } + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } #endif /* LWIP_IGMP */ + } } } @@ -433,73 +485,65 @@ void netif_set_up(struct netif *netif) */ void netif_set_down(struct netif *netif) { - if ( netif->flags & NETIF_FLAG_UP ) - { - netif->flags &= ~NETIF_FLAG_UP; + if (netif->flags & NETIF_FLAG_UP) { + netif->flags &= ~NETIF_FLAG_UP; #if LWIP_SNMP - snmp_get_sysuptime(&netif->ts); + snmp_get_sysuptime(&netif->ts); #endif - - NETIF_LINK_CALLBACK(netif); - NETIF_STATUS_CALLBACK(netif); - } -} -/** - * Ask if an interface is up - */ -u8_t netif_is_up(struct netif *netif) -{ - return (netif->flags & NETIF_FLAG_UP)?1:0; + NETIF_STATUS_CALLBACK(netif); + } } #if LWIP_NETIF_STATUS_CALLBACK /** * Set callback to be called when interface is brought up/down */ -void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif )) +void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) { - if ( netif ) - netif->status_callback = status_callback; + if (netif) { + netif->status_callback = status_callback; + } } #endif /* LWIP_NETIF_STATUS_CALLBACK */ -#if LWIP_NETIF_LINK_CALLBACK /** * Called by a driver when its link goes up */ void netif_set_link_up(struct netif *netif ) { - netif->flags |= NETIF_FLAG_LINK_UP; + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + netif->flags |= NETIF_FLAG_LINK_UP; #if LWIP_DHCP - if (netif->dhcp) { - dhcp_network_changed(netif); - } + if (netif->dhcp) { + dhcp_network_changed(netif); + } #endif /* LWIP_DHCP */ #if LWIP_AUTOIP - if (netif->autoip) { - autoip_network_changed(netif); - } + if (netif->autoip) { + autoip_network_changed(netif); + } #endif /* LWIP_AUTOIP */ - if (netif->flags & NETIF_FLAG_UP) { + if (netif->flags & NETIF_FLAG_UP) { #if LWIP_ARP - /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ - if (netif->flags & NETIF_FLAG_ETHARP) { - etharp_gratuitous(netif); - } + /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ + if (netif->flags & NETIF_FLAG_ETHARP) { + etharp_gratuitous(netif); + } #endif /* LWIP_ARP */ #if LWIP_IGMP - /* resend IGMP memberships */ - if (netif->flags & NETIF_FLAG_IGMP) { - igmp_report_groups( netif); - } + /* resend IGMP memberships */ + if (netif->flags & NETIF_FLAG_IGMP) { + igmp_report_groups( netif); + } #endif /* LWIP_IGMP */ + } + NETIF_LINK_CALLBACK(netif); } - NETIF_LINK_CALLBACK(netif); } /** @@ -507,22 +551,17 @@ void netif_set_link_up(struct netif *netif ) */ void netif_set_link_down(struct netif *netif ) { - netif->flags &= ~NETIF_FLAG_LINK_UP; - NETIF_LINK_CALLBACK(netif); -} - -/** - * Ask if a link is up - */ -u8_t netif_is_link_up(struct netif *netif) -{ - return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0; + if (netif->flags & NETIF_FLAG_LINK_UP) { + netif->flags &= ~NETIF_FLAG_LINK_UP; + NETIF_LINK_CALLBACK(netif); + } } +#if LWIP_NETIF_LINK_CALLBACK /** * Set callback to be called when link is brought up/down */ -void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif )) +void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) { if (netif) { netif->link_callback = link_callback; @@ -547,7 +586,7 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct */ err_t netif_loop_output(struct netif *netif, struct pbuf *p, - struct ip_addr *ipaddr) + ip_addr_t *ipaddr) { struct pbuf *r; err_t err; @@ -555,22 +594,36 @@ netif_loop_output(struct netif *netif, struct pbuf *p, #if LWIP_LOOPBACK_MAX_PBUFS u8_t clen = 0; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ SYS_ARCH_DECL_PROTECT(lev); LWIP_UNUSED_ARG(ipaddr); /* Allocate a new pbuf */ r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); if (r == NULL) { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); 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) > LWIP_LOOPBACK_MAX_PBUFS)) { - pbuf_free(r); - r = NULL; - return ERR_MEM; + ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { + pbuf_free(r); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); + return ERR_MEM; } netif->loop_cnt_current += clen; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ @@ -578,7 +631,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p, /* Copy the whole pbuf queue p into the single pbuf r */ if ((err = pbuf_copy(r, p)) != ERR_OK) { pbuf_free(r); - r = NULL; + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(stats_if); return err; } @@ -599,9 +654,13 @@ netif_loop_output(struct netif *netif, struct pbuf *p, } SYS_ARCH_UNPROTECT(lev); + LINK_STATS_INC(link.xmit); + snmp_add_ifoutoctets(stats_if, p->tot_len); + snmp_inc_ifoutucastpkts(stats_if); + #if LWIP_NETIF_LOOPBACK_MULTITHREADING /* For multithreading environment, schedule a call to netif_poll */ - tcpip_callback((void (*)(void *))(netif_poll), netif); + tcpip_callback((tcpip_callback_fn)netif_poll, netif); #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ return ERR_OK; @@ -617,13 +676,22 @@ void netif_poll(struct netif *netif) { struct pbuf *in; + /* If we have a loopif, SNMP counters are adjusted for it, + * if not they are adjusted for 'netif'. */ +#if LWIP_SNMP +#if LWIP_HAVE_LOOPIF + struct netif *stats_if = &loop_netif; +#else /* LWIP_HAVE_LOOPIF */ + struct netif *stats_if = netif; +#endif /* LWIP_HAVE_LOOPIF */ +#endif /* LWIP_SNMP */ SYS_ARCH_DECL_PROTECT(lev); do { /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ SYS_ARCH_PROTECT(lev); in = netif->loop_first; - if(in != NULL) { + if (in != NULL) { struct pbuf *in_end = in; #if LWIP_LOOPBACK_MAX_PBUFS u8_t clen = pbuf_clen(in); @@ -632,12 +700,12 @@ netif_poll(struct netif *netif) ((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) { + 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; } /* 'in_end' now points to the last pbuf from 'in' */ - if(in_end == netif->loop_last) { + if (in_end == netif->loop_last) { /* this was the last pbuf in the list */ netif->loop_first = netif->loop_last = NULL; } else { @@ -650,16 +718,19 @@ netif_poll(struct netif *netif) } SYS_ARCH_UNPROTECT(lev); - if(in != NULL) { + if (in != NULL) { + LINK_STATS_INC(link.recv); + snmp_add_ifinoctets(stats_if, in->tot_len); + snmp_inc_ifinucastpkts(stats_if); /* loopback packets are always IP packets! */ - if(ip_input(in, netif) != ERR_OK) { + if (ip_input(in, netif) != ERR_OK) { pbuf_free(in); } /* Don't reference the packet any more! */ in = NULL; } /* go on while there is a packet on the list */ - } while(netif->loop_first != NULL); + } while (netif->loop_first != NULL); } #if !LWIP_NETIF_LOOPBACK_MULTITHREADING |