A version of LWIP, provided for backwards compatibility.
Dependents: AA_DemoBoard DemoBoard HelloServerDemo DemoBoard_RangeIndicator ... more
loopif.c
00001 /** 00002 * @file 00003 * Loop Interface 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 #include "lwip/opt.h" 00039 00040 #if LWIP_HAVE_LOOPIF 00041 00042 #include "netif/loopif.h" 00043 #include "lwip/pbuf.h" 00044 #include "lwip/snmp.h" 00045 00046 #include <string.h> 00047 00048 #if !LWIP_LOOPIF_MULTITHREADING 00049 00050 #include "lwip/sys.h" 00051 #include "lwip/mem.h" 00052 00053 /* helper struct for the linked list of pbufs */ 00054 struct loopif_private { 00055 struct pbuf *first; 00056 struct pbuf *last; 00057 }; 00058 00059 /** 00060 * Call loopif_poll() in the main loop of your application. This is to prevent 00061 * reentering non-reentrant functions like tcp_input(). Packets passed to 00062 * loopif_output() are put on a list that is passed to netif->input() by 00063 * loopif_poll(). 00064 * 00065 * @param netif the lwip network interface structure for this loopif 00066 */ 00067 void 00068 loopif_poll(struct netif *netif) 00069 { 00070 SYS_ARCH_DECL_PROTECT(lev); 00071 struct pbuf *in, *in_end; 00072 struct loopif_private *priv = (struct loopif_private*)netif->state; 00073 00074 LWIP_ERROR("priv != NULL", (priv != NULL), return;); 00075 00076 do { 00077 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 00078 SYS_ARCH_PROTECT(lev); 00079 in = priv->first; 00080 if(in) { 00081 in_end = in; 00082 while(in_end->len != in_end->tot_len) { 00083 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 00084 in_end = in_end->next; 00085 } 00086 /* 'in_end' now points to the last pbuf from 'in' */ 00087 if(in_end == priv->last) { 00088 /* this was the last pbuf in the list */ 00089 priv->first = priv->last = NULL; 00090 } else { 00091 /* pop the pbuf off the list */ 00092 priv->first = in_end->next; 00093 LWIP_ASSERT("should not be null since first != last!", priv->first != NULL); 00094 } 00095 } 00096 SYS_ARCH_UNPROTECT(lev); 00097 00098 if(in != NULL) { 00099 if(in_end->next != NULL) { 00100 /* De-queue the pbuf from its successors on the 'priv' list. */ 00101 in_end->next = NULL; 00102 } 00103 if(netif->input(in, netif) != ERR_OK) { 00104 pbuf_free(in); 00105 } 00106 /* Don't reference the packet any more! */ 00107 in = NULL; 00108 in_end = NULL; 00109 } 00110 /* go on while there is a packet on the list */ 00111 } while(priv->first != NULL); 00112 } 00113 #endif /* LWIP_LOOPIF_MULTITHREADING */ 00114 00115 /** 00116 * Send an IP packet over the loopback interface. 00117 * The pbuf is simply copied and handed back to netif->input. 00118 * In multithreaded mode, this is done directly since netif->input must put 00119 * the packet on a queue. 00120 * In callback mode, the packet is put on an internal queue and is fed to 00121 * netif->input by loopif_poll(). 00122 * 00123 * @param netif the lwip network interface structure for this loopif 00124 * @param p the (IP) packet to 'send' 00125 * @param ipaddr the ip address to send the packet to (not used for loopif) 00126 * @return ERR_OK if the packet has been sent 00127 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 00128 */ 00129 static err_t 00130 loopif_output(struct netif *netif, struct pbuf *p, 00131 struct ip_addr *ipaddr) 00132 { 00133 #if !LWIP_LOOPIF_MULTITHREADING 00134 SYS_ARCH_DECL_PROTECT(lev); 00135 struct loopif_private *priv; 00136 struct pbuf *last; 00137 #endif /* LWIP_LOOPIF_MULTITHREADING */ 00138 struct pbuf *r; 00139 err_t err; 00140 00141 LWIP_UNUSED_ARG(ipaddr); 00142 00143 /* Allocate a new pbuf */ 00144 r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 00145 if (r == NULL) { 00146 return ERR_MEM; 00147 } 00148 00149 /* Copy the whole pbuf queue p into the single pbuf r */ 00150 if ((err = pbuf_copy(r, p)) != ERR_OK) { 00151 pbuf_free(r); 00152 r = NULL; 00153 return err; 00154 } 00155 00156 #if LWIP_LOOPIF_MULTITHREADING 00157 /* Multithreading environment, netif->input() is supposed to put the packet 00158 into a mailbox, so we can safely call it here without risking to re-enter 00159 functions that are not reentrant (TCP!!!) */ 00160 if(netif->input(r, netif) != ERR_OK) { 00161 pbuf_free(r); 00162 r = NULL; 00163 } 00164 #else /* LWIP_LOOPIF_MULTITHREADING */ 00165 /* Raw API without threads: put the packet on a linked list which gets emptied 00166 through calling loopif_poll(). */ 00167 priv = (struct loopif_private*)netif->state; 00168 00169 /* let last point to the last pbuf in chain r */ 00170 for (last = r; last->next != NULL; last = last->next); 00171 SYS_ARCH_PROTECT(lev); 00172 if(priv->first != NULL) { 00173 LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL); 00174 priv->last->next = r; 00175 priv->last = last; 00176 } else { 00177 priv->first = r; 00178 priv->last = last; 00179 } 00180 SYS_ARCH_UNPROTECT(lev); 00181 #endif /* LWIP_LOOPIF_MULTITHREADING */ 00182 00183 return ERR_OK; 00184 } 00185 00186 /** 00187 * Initialize a lwip network interface structure for a loopback interface 00188 * 00189 * @param netif the lwip network interface structure for this loopif 00190 * @return ERR_OK if the loopif is initialized 00191 * ERR_MEM if private data couldn't be allocated 00192 */ 00193 err_t 00194 loopif_init(struct netif *netif) 00195 { 00196 #if !LWIP_LOOPIF_MULTITHREADING 00197 struct loopif_private *priv; 00198 00199 priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private)); 00200 if(priv == NULL) 00201 return ERR_MEM; 00202 priv->first = priv->last = NULL; 00203 netif->state = priv; 00204 #endif /* LWIP_LOOPIF_MULTITHREADING */ 00205 00206 /* initialize the snmp variables and counters inside the struct netif 00207 * ifSpeed: no assumption can be made! 00208 */ 00209 NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); 00210 00211 netif->name[0] = 'l'; 00212 netif->name[1] = 'o'; 00213 netif->output = loopif_output; 00214 return ERR_OK; 00215 } 00216 00217 #endif /* LWIP_HAVE_LOOPIF */
Generated on Tue Jul 12 2022 16:06:14 by 1.7.2