X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Flwip%2Fnetif%2Floopif.c;fp=geekos%2Fsrc%2Flwip%2Fnetif%2Floopif.c;h=adffdcf39f0e396fb3dc3850aec448431b086aa2;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/lwip/netif/loopif.c b/geekos/src/lwip/netif/loopif.c new file mode 100644 index 0000000..adffdcf --- /dev/null +++ b/geekos/src/lwip/netif/loopif.c @@ -0,0 +1,217 @@ +/** + * @file + * Loop Interface + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * 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, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * 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. + * + * 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 + * + */ +#include "lwip/opt.h" + +#if LWIP_HAVE_LOOPIF + +#include "netif/loopif.h" +#include "lwip/pbuf.h" +#include "lwip/snmp.h" + +#include + +#if !LWIP_LOOPIF_MULTITHREADING + +#include "lwip/sys.h" +#include "lwip/mem.h" + +/* helper struct for the linked list of pbufs */ +struct loopif_private { + struct pbuf *first; + struct pbuf *last; +}; + +/** + * Call loopif_poll() in the main loop of your application. This is to prevent + * reentering non-reentrant functions like tcp_input(). Packets passed to + * loopif_output() are put on a list that is passed to netif->input() by + * loopif_poll(). + * + * @param netif the lwip network interface structure for this loopif + */ +void +loopif_poll(struct netif *netif) +{ + SYS_ARCH_DECL_PROTECT(lev); + struct pbuf *in, *in_end; + struct loopif_private *priv = (struct loopif_private*)netif->state; + + LWIP_ERROR("priv != NULL", (priv != NULL), return;); + + do { + /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ + SYS_ARCH_PROTECT(lev); + in = priv->first; + if(in) { + in_end = in; + 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 == priv->last) { + /* this was the last pbuf in the list */ + priv->first = priv->last = NULL; + } else { + /* pop the pbuf off the list */ + priv->first = in_end->next; + LWIP_ASSERT("should not be null since first != last!", priv->first != NULL); + } + } + SYS_ARCH_UNPROTECT(lev); + + if(in != NULL) { + if(in_end->next != NULL) { + /* De-queue the pbuf from its successors on the 'priv' list. */ + in_end->next = NULL; + } + if(netif->input(in, netif) != ERR_OK) { + pbuf_free(in); + } + /* Don't reference the packet any more! */ + in = NULL; + in_end = NULL; + } + /* go on while there is a packet on the list */ + } while(priv->first != NULL); +} +#endif /* LWIP_LOOPIF_MULTITHREADING */ + +/** + * Send an IP packet over the loopback interface. + * The pbuf is simply copied and handed back to netif->input. + * In multithreaded mode, this is done directly since netif->input must put + * the packet on a queue. + * In callback mode, the packet is put on an internal queue and is fed to + * netif->input by loopif_poll(). + * + * @param netif the lwip network interface structure for this loopif + * @param p the (IP) packet to 'send' + * @param ipaddr the ip address to send the packet to (not used for loopif) + * @return ERR_OK if the packet has been sent + * ERR_MEM if the pbuf used to copy the packet couldn't be allocated + */ +static err_t +loopif_output(struct netif *netif, struct pbuf *p, + struct ip_addr *ipaddr) +{ +#if !LWIP_LOOPIF_MULTITHREADING + SYS_ARCH_DECL_PROTECT(lev); + struct loopif_private *priv; + struct pbuf *last; +#endif /* LWIP_LOOPIF_MULTITHREADING */ + struct pbuf *r; + err_t err; + + LWIP_UNUSED_ARG(ipaddr); + + /* Allocate a new pbuf */ + r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if (r == NULL) { + return ERR_MEM; + } + + /* Copy the whole pbuf queue p into the single pbuf r */ + if ((err = pbuf_copy(r, p)) != ERR_OK) { + pbuf_free(r); + r = NULL; + return err; + } + +#if LWIP_LOOPIF_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!!!) */ + if(netif->input(r, netif) != ERR_OK) { + pbuf_free(r); + r = NULL; + } +#else /* LWIP_LOOPIF_MULTITHREADING */ + /* Raw API without threads: put the packet on a linked list which gets emptied + through calling loopif_poll(). */ + priv = (struct loopif_private*)netif->state; + + /* let last point to the last pbuf in chain r */ + for (last = r; last->next != NULL; last = last->next); + SYS_ARCH_PROTECT(lev); + if(priv->first != NULL) { + LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL); + priv->last->next = r; + priv->last = last; + } else { + priv->first = r; + priv->last = last; + } + SYS_ARCH_UNPROTECT(lev); +#endif /* LWIP_LOOPIF_MULTITHREADING */ + + return ERR_OK; +} + +/** + * 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 + */ +err_t +loopif_init(struct netif *netif) +{ +#if !LWIP_LOOPIF_MULTITHREADING + struct loopif_private *priv; + + priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private)); + if(priv == NULL) + return ERR_MEM; + priv->first = priv->last = NULL; + netif->state = priv; +#endif /* LWIP_LOOPIF_MULTITHREADING */ + + /* 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 = loopif_output; + return ERR_OK; +} + +#endif /* LWIP_HAVE_LOOPIF */