From b6ffb3c9076a72c087b57468ab3e994bd1eb2f69 Mon Sep 17 00:00:00 2001 From: arighi Date: Mon, 1 Nov 2010 16:26:28 +0000 Subject: [PATCH] lwIP: add ethernet glue for lwIP Implement the "ethernetif" virtual driver to plug lwIP to the BeRTOS generic ethernet layer. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4487 38d2e660-2303-0410-9eaa-f027e97ec537 --- .../net/lwip/src/include/netif/ethernetif.h | 7 + bertos/net/lwip/src/netif/ethernetif.c | 437 ++++++++++-------- 2 files changed, 242 insertions(+), 202 deletions(-) create mode 100644 bertos/net/lwip/src/include/netif/ethernetif.h diff --git a/bertos/net/lwip/src/include/netif/ethernetif.h b/bertos/net/lwip/src/include/netif/ethernetif.h new file mode 100644 index 00000000..0690d17b --- /dev/null +++ b/bertos/net/lwip/src/include/netif/ethernetif.h @@ -0,0 +1,7 @@ +#ifndef ETHERNETIF_H +#define ETHERNETIF_H + +#include +err_t ethernetif_init(struct netif *netif); + +#endif /* ETHERNETIF_H */ diff --git a/bertos/net/lwip/src/netif/ethernetif.c b/bertos/net/lwip/src/netif/ethernetif.c index a5b7d990..9618061c 100644 --- a/bertos/net/lwip/src/netif/ethernetif.c +++ b/bertos/net/lwip/src/netif/ethernetif.c @@ -1,14 +1,45 @@ /** - * @file - * Ethernet Interface Skeleton + * \file + * + * + * \brief Ethernet driver glue for lwIP + * + * \author Andrea Righi */ /* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, @@ -17,21 +48,21 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. - * + * * Author: Adam Dunkels * */ @@ -43,22 +74,29 @@ * something that better describes your network interface. */ -#include "lwip/opt.h" +#include "cfg/cfg_lwip.h" + +#include + +#include -#if 0 /* don't build, this is only a skeleton, see previous comment */ +#include -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/sys.h" +#include +#include +#include +#include #include #include -#include "netif/etharp.h" -#include "netif/ppp_oe.h" + +#include +#include + +#include /* Define those to better describe your network interface. */ #define IFNAME0 'e' -#define IFNAME1 'n' +#define IFNAME1 '0' /** * Helper struct to hold private data used to operate your ethernet interface. @@ -66,14 +104,12 @@ * as it is already kept in the struct netif. * But this is only an example, anyway... */ -struct ethernetif { - struct eth_addr *ethaddr; - /* Add whatever per-interface state that is needed here. */ +struct ethernetif +{ + struct eth_addr *ethaddr; + /* Add whatever per-interface state that is needed here. */ }; -/* Forward declarations. */ -static void ethernetif_input(struct netif *netif); - /** * In this function, the hardware should be initialized. * Called from ethernetif_init(). @@ -81,27 +117,27 @@ static void ethernetif_input(struct netif *netif); * @param netif the already initialized lwip network interface structure * for this ethernetif */ -static void -low_level_init(struct netif *netif) +static void low_level_init(struct netif *netif) { - struct ethernetif *ethernetif = netif->state; - - /* set MAC hardware address length */ - netif->hwaddr_len = ETHARP_HWADDR_LEN; - - /* set MAC hardware address */ - netif->hwaddr[0] = ; - ... - netif->hwaddr[5] = ; - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - - /* Do whatever else is needed to initialize interface. */ + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set MAC hardware address */ + netif->hwaddr[0] = mac_addr[0]; + netif->hwaddr[1] = mac_addr[1]; + netif->hwaddr[2] = mac_addr[2]; + netif->hwaddr[3] = mac_addr[3]; + netif->hwaddr[4] = mac_addr[4]; + netif->hwaddr[5] = mac_addr[5]; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + eth_init(); } /** @@ -120,34 +156,27 @@ low_level_init(struct netif *netif) * dropped because of memory failure (except for the TCP timers). */ -static err_t -low_level_output(struct netif *netif, struct pbuf *p) +static err_t low_level_output(UNUSED_ARG(struct netif *, netif), struct pbuf *p) { - struct ethernetif *ethernetif = netif->state; - struct pbuf *q; + struct pbuf *q; - initiate transfer(); - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif + #if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ + #endif - for(q = p; q != NULL; q = q->next) { - /* Send the data from the pbuf to the interface, one pbuf at a - time. The size of the data in each pbuf is kept in the ->len - variable. */ - send data from(q->payload, q->len); - } + proc_forbid(); + for (q = p; q != NULL; q = q->next) + eth_putFrame(q->payload, q->len); + eth_sendFrame(); - signal that packet should be sent(); + #if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ + #endif -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.xmit); + LINK_STATS_INC(link.xmit); + proc_permit(); - return ERR_OK; + return ERR_OK; } /** @@ -158,57 +187,45 @@ low_level_output(struct netif *netif, struct pbuf *p) * @return a pbuf filled with the received packet (including MAC header) * NULL on memory error */ -static struct pbuf * -low_level_input(struct netif *netif) +static struct pbuf *low_level_input(UNUSED_ARG(struct netif *, netif)) { - struct ethernetif *ethernetif = netif->state; - struct pbuf *p, *q; - u16_t len; - - /* Obtain the size of the packet and put it into the "len" - variable. */ - len = ; - -#if ETH_PAD_SIZE - len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ -#endif - - /* We allocate a pbuf chain of pbufs from the pool. */ - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - - if (p != NULL) { - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - - /* We iterate over the pbuf chain until we have read the entire - * packet into the pbuf. */ - for(q = p; q != NULL; q = q->next) { - /* Read enough bytes to fill this pbuf in the chain. The - * available data in the pbuf is given by the q->len - * variable. - * This does not necessarily have to be a memcpy, you can also preallocate - * pbufs for a DMA-enabled MAC and after receiving truncate it to the - * actually received size. In this case, ensure the tot_len member of the - * pbuf is the sum of the chained pbuf len members. - */ - read data into(q->payload, q->len); - } - acknowledge that packet has been read(); - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.recv); - } else { - drop packet(); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - } - - return p; + struct pbuf *p, *q; + size_t len; + + len = eth_getFrameLen(); + if (UNLIKELY(len <= 0)) + return NULL; + + #if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ + #endif + + proc_forbid(); + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) + { + #if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ + #endif + + for (q = p; q != NULL; q = q->next) + eth_getFrame(q->payload, q->len); + + #if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ + #endif + + LINK_STATS_INC(link.recv); + } + else + { + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + proc_permit(); + + return p; } /** @@ -220,44 +237,52 @@ low_level_input(struct netif *netif) * * @param netif the lwip network interface structure for this ethernetif */ -static void -ethernetif_input(struct netif *netif) +static void ethernetif_input(struct netif *netif) { - struct ethernetif *ethernetif; - struct eth_hdr *ethhdr; - struct pbuf *p; - - ethernetif = netif->state; - - /* move received packet into a new pbuf */ - p = low_level_input(netif); - /* no packet could be read, silently ignore this */ - if (p == NULL) return; - /* points to packet payload, which starts with an Ethernet header */ - ethhdr = p->payload; - - switch (htons(ethhdr->type)) { - /* IP or ARP packet? */ - case ETHTYPE_IP: - case ETHTYPE_ARP: -#if PPPOE_SUPPORT - /* PPPoE packet? */ - case ETHTYPE_PPPOEDISC: - case ETHTYPE_PPPOE: -#endif /* PPPOE_SUPPORT */ - /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif)!=ERR_OK) - { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); - pbuf_free(p); - p = NULL; - } - break; - - default: - pbuf_free(p); - p = NULL; - break; - } + struct ethernetif *ethernetif; + struct eth_hdr *ethhdr; + struct pbuf *p; + + ethernetif = netif->state; + + /* move received packet into a new pbuf */ + p = low_level_input(netif); + /* no packet could be read, silently ignore this */ + if (p == NULL) return; + + ethhdr = p->payload; + + switch (htons(ethhdr->type)) + { + case ETHTYPE_ARP: + etharp_arp_input(netif, ethernetif->ethaddr, p); + break; + + case ETHTYPE_IP: +#if DHCP_DOES_ARP_CHECK + etharp_ip_input(netif, p); +#endif + pbuf_header(p, (int16_t) - sizeof(struct eth_hdr)); + + if (netif->input(p, netif) != ERR_OK) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + break; + default: + pbuf_free(p); + p = NULL; + break; + } +} + +static NORETURN void ethernetif_loop(void *arg) +{ + struct netif *netif = (struct netif *)arg; + while (1) + ethernetif_input(netif); } /** @@ -272,47 +297,55 @@ ethernetif_input(struct netif *netif) * ERR_MEM if private data couldn't be allocated * any other err_t on error */ -err_t -ethernetif_init(struct netif *netif) +err_t ethernetif_init(struct netif *netif) { - struct ethernetif *ethernetif; - - LWIP_ASSERT("netif != NULL", (netif != NULL)); - - ethernetif = mem_malloc(sizeof(struct ethernetif)); - if (ethernetif == NULL) { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); - return ERR_MEM; - } - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwip"; -#endif /* LWIP_NETIF_HOSTNAME */ - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); - - netif->state = ethernetif; - netif->name[0] = IFNAME0; - netif->name[1] = IFNAME1; - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; - netif->linkoutput = low_level_output; - - ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); - - /* initialize the hardware */ - low_level_init(netif); - - return ERR_OK; + struct ethernetif *ethernetif; + + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + ethernetif = mem_malloc(sizeof(struct ethernetif)); + if (ethernetif == NULL) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n")); + return ERR_MEM; + } + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); + + netif->state = ethernetif; + + netif->hwaddr_len = 6; + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + netif->mtu = 1500; + + + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) + */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); + + /* initialize the hardware */ + low_level_init(netif); + etharp_init(); + + if (!sys_thread_new((char *)"eth_thread", ethernetif_loop, netif, + DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO)) + { + LWIP_DEBUGF(NETIF_DEBUG, + ("ethernetif_init: max number of threads exceeded\n")); + mem_free(ethernetif); + return ERR_MEM; + } + return ERR_OK; } - -#endif /* 0 */ -- 2.25.1