My fork of the HTTPServer (working)
Embed:
(wiki syntax)
Show/hide line numbers
netif.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * lwIP network interface abstraction 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 00039 #include "lwip/opt.h" 00040 00041 #include "lwip/def.h" 00042 #include "lwip/ip_addr.h" 00043 #include "lwip/netif.h" 00044 #include "lwip/tcp.h" 00045 #include "lwip/snmp.h" 00046 #include "lwip/igmp.h" 00047 #include "netif/etharp.h" 00048 #if ENABLE_LOOPBACK 00049 #include "lwip/sys.h" 00050 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 00051 #include "lwip/tcpip.h" 00052 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00053 #endif /* ENABLE_LOOPBACK */ 00054 00055 #if LWIP_NETIF_STATUS_CALLBACK 00056 #define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); } 00057 #else 00058 #define NETIF_STATUS_CALLBACK(n) { /* NOP */ } 00059 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00060 00061 #if LWIP_NETIF_LINK_CALLBACK 00062 #define NETIF_LINK_CALLBACK(n) { if (n->link_callback) (n->link_callback)(n); } 00063 #else 00064 #define NETIF_LINK_CALLBACK(n) { /* NOP */ } 00065 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00066 00067 struct netif *netif_list; 00068 struct netif *netif_default; 00069 00070 /** 00071 * Add a network interface to the list of lwIP netifs. 00072 * 00073 * @param netif a pre-allocated netif structure 00074 * @param ipaddr IP address for the new netif 00075 * @param netmask network mask for the new netif 00076 * @param gw default gateway IP address for the new netif 00077 * @param state opaque data passed to the new netif 00078 * @param init callback function that initializes the interface 00079 * @param input callback function that is called to pass 00080 * ingress packets up in the protocol layer stack. 00081 * 00082 * @return netif, or NULL if failed. 00083 */ 00084 struct netif * 00085 netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, 00086 struct ip_addr *gw, 00087 void *state, 00088 err_t (* init)(struct netif *netif), 00089 err_t (* input)(struct pbuf *p, struct netif *netif)) 00090 { 00091 static u8_t netifnum = 0; 00092 00093 /* reset new interface configuration state */ 00094 netif->ip_addr.addr = 0; 00095 netif->netmask.addr = 0; 00096 netif->gw.addr = 0; 00097 netif->flags = 0; 00098 #if LWIP_DHCP 00099 /* netif not under DHCP control by default */ 00100 netif->dhcp = NULL; 00101 #endif /* LWIP_DHCP */ 00102 #if LWIP_AUTOIP 00103 /* netif not under AutoIP control by default */ 00104 netif->autoip = NULL; 00105 #endif /* LWIP_AUTOIP */ 00106 #if LWIP_NETIF_STATUS_CALLBACK 00107 netif->status_callback = NULL; 00108 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00109 #if LWIP_NETIF_LINK_CALLBACK 00110 netif->link_callback = NULL; 00111 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00112 #if LWIP_IGMP 00113 netif->igmp_mac_filter = NULL; 00114 #endif /* LWIP_IGMP */ 00115 #if ENABLE_LOOPBACK 00116 netif->loop_first = NULL; 00117 netif->loop_last = NULL; 00118 #endif /* ENABLE_LOOPBACK */ 00119 00120 /* remember netif specific state information data */ 00121 netif->state = state; 00122 netif->num = netifnum++; 00123 netif->input = input; 00124 #if LWIP_NETIF_HWADDRHINT 00125 netif->addr_hint = NULL; 00126 #endif /* LWIP_NETIF_HWADDRHINT*/ 00127 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS 00128 netif->loop_cnt_current = 0; 00129 #endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ 00130 00131 netif_set_addr(netif, ipaddr, netmask, gw); 00132 00133 /* call user specified initialization function for netif */ 00134 if (init(netif) != ERR_OK) { 00135 return (struct netif *)(NULL); 00136 } 00137 00138 /* add this netif to the list */ 00139 netif->next = netif_list; 00140 netif_list = netif; 00141 snmp_inc_iflist(); 00142 00143 #if LWIP_IGMP 00144 /* start IGMP processing */ 00145 if (netif->flags & NETIF_FLAG_IGMP) { 00146 igmp_start( netif); 00147 } 00148 #endif /* LWIP_IGMP */ 00149 00150 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", 00151 netif->name[0], netif->name[1])); 00152 ip_addr_debug_print(NETIF_DEBUG, ipaddr); 00153 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 00154 ip_addr_debug_print(NETIF_DEBUG, netmask); 00155 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 00156 ip_addr_debug_print(NETIF_DEBUG, gw); 00157 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 00158 return netif; 00159 } 00160 00161 /** 00162 * Change IP address configuration for a network interface (including netmask 00163 * and default gateway). 00164 * 00165 * @param netif the network interface to change 00166 * @param ipaddr the new IP address 00167 * @param netmask the new netmask 00168 * @param gw the new default gateway 00169 */ 00170 void 00171 netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask, 00172 struct ip_addr *gw) 00173 { 00174 netif_set_ipaddr(netif, ipaddr); 00175 netif_set_netmask(netif, netmask); 00176 netif_set_gw(netif, gw); 00177 } 00178 00179 /** 00180 * Remove a network interface from the list of lwIP netifs. 00181 * 00182 * @param netif the network interface to remove 00183 */ 00184 void netif_remove(struct netif * netif) 00185 { 00186 if ( netif == NULL ) return; 00187 00188 #if LWIP_IGMP 00189 /* stop IGMP processing */ 00190 if (netif->flags & NETIF_FLAG_IGMP) { 00191 igmp_stop( netif); 00192 } 00193 #endif /* LWIP_IGMP */ 00194 00195 snmp_delete_ipaddridx_tree(netif); 00196 00197 /* is it the first netif? */ 00198 if (netif_list == netif) { 00199 netif_list = netif->next; 00200 snmp_dec_iflist(); 00201 } 00202 else { 00203 /* look for netif further down the list */ 00204 struct netif * tmpNetif; 00205 for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { 00206 if (tmpNetif->next == netif) { 00207 tmpNetif->next = netif->next; 00208 snmp_dec_iflist(); 00209 break; 00210 } 00211 } 00212 if (tmpNetif == NULL) 00213 return; /* we didn't find any netif today */ 00214 } 00215 /* this netif is default? */ 00216 if (netif_default == netif) 00217 /* reset default netif */ 00218 netif_set_default((struct netif *)(NULL)); 00219 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 00220 } 00221 00222 /** 00223 * Find a network interface by searching for its name 00224 * 00225 * @param name the name of the netif (like netif->name) plus concatenated number 00226 * in ascii representation (e.g. 'en0') 00227 */ 00228 struct netif * 00229 netif_find(char *name) 00230 { 00231 struct netif *netif; 00232 u8_t num; 00233 00234 if (name == NULL) { 00235 return (struct netif *)(NULL); 00236 } 00237 00238 num = name[2] - '0'; 00239 00240 for(netif = netif_list; netif != NULL; netif = netif->next) { 00241 if (num == netif->num && 00242 name[0] == netif->name[0] && 00243 name[1] == netif->name[1]) { 00244 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 00245 return netif; 00246 } 00247 } 00248 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 00249 return (struct netif *)(NULL); 00250 } 00251 00252 /** 00253 * Change the IP address of a network interface 00254 * 00255 * @param netif the network interface to change 00256 * @param ipaddr the new IP address 00257 * 00258 * @note call netif_set_addr() if you also want to change netmask and 00259 * default gateway 00260 */ 00261 void 00262 netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr) 00263 { 00264 /* TODO: Handling of obsolete pcbs */ 00265 /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ 00266 #if LWIP_TCP 00267 struct tcp_pcb *pcb; 00268 struct tcp_pcb_listen *lpcb; 00269 00270 /* address is actually being changed? */ 00271 if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) 00272 { 00273 /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ 00274 LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n")); 00275 pcb = tcp_active_pcbs; 00276 while (pcb != NULL) { 00277 /* PCB bound to current local interface address? */ 00278 if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) { 00279 /* this connection must be aborted */ 00280 struct tcp_pcb *next = pcb->next; 00281 LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); 00282 tcp_abort(pcb); 00283 pcb = next; 00284 } else { 00285 pcb = pcb->next; 00286 } 00287 } 00288 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 00289 /* PCB bound to current local interface address? */ 00290 if ((!(ip_addr_isany(&(lpcb->local_ip)))) && 00291 (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) { 00292 /* The PCB is listening to the old ipaddr and 00293 * is set to listen to the new one instead */ 00294 ip_addr_set(&(lpcb->local_ip), ipaddr); 00295 } 00296 } 00297 } 00298 #endif 00299 snmp_delete_ipaddridx_tree(netif); 00300 snmp_delete_iprteidx_tree(0,netif); 00301 /* set new IP address to netif */ 00302 ip_addr_set(&(netif->ip_addr), ipaddr); 00303 snmp_insert_ipaddridx_tree(netif); 00304 snmp_insert_iprteidx_tree(0,netif); 00305 00306 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00307 netif->name[0], netif->name[1], 00308 ip4_addr1(&netif->ip_addr), 00309 ip4_addr2(&netif->ip_addr), 00310 ip4_addr3(&netif->ip_addr), 00311 ip4_addr4(&netif->ip_addr))); 00312 } 00313 00314 /** 00315 * Change the default gateway for a network interface 00316 * 00317 * @param netif the network interface to change 00318 * @param gw the new default gateway 00319 * 00320 * @note call netif_set_addr() if you also want to change ip address and netmask 00321 */ 00322 void 00323 netif_set_gw(struct netif *netif, struct ip_addr *gw) 00324 { 00325 ip_addr_set(&(netif->gw), gw); 00326 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00327 netif->name[0], netif->name[1], 00328 ip4_addr1(&netif->gw), 00329 ip4_addr2(&netif->gw), 00330 ip4_addr3(&netif->gw), 00331 ip4_addr4(&netif->gw))); 00332 } 00333 00334 /** 00335 * Change the netmask of a network interface 00336 * 00337 * @param netif the network interface to change 00338 * @param netmask the new netmask 00339 * 00340 * @note call netif_set_addr() if you also want to change ip address and 00341 * default gateway 00342 */ 00343 void 00344 netif_set_netmask(struct netif *netif, struct ip_addr *netmask) 00345 { 00346 snmp_delete_iprteidx_tree(0, netif); 00347 /* set new netmask to netif */ 00348 ip_addr_set(&(netif->netmask), netmask); 00349 snmp_insert_iprteidx_tree(0, netif); 00350 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", 00351 netif->name[0], netif->name[1], 00352 ip4_addr1(&netif->netmask), 00353 ip4_addr2(&netif->netmask), 00354 ip4_addr3(&netif->netmask), 00355 ip4_addr4(&netif->netmask))); 00356 } 00357 00358 /** 00359 * Set a network interface as the default network interface 00360 * (used to output all packets for which no specific route is found) 00361 * 00362 * @param netif the default network interface 00363 */ 00364 void 00365 netif_set_default(struct netif *netif) 00366 { 00367 if (netif == NULL) 00368 { 00369 /* remove default route */ 00370 snmp_delete_iprteidx_tree(1, netif); 00371 } 00372 else 00373 { 00374 /* install default route */ 00375 snmp_insert_iprteidx_tree(1, netif); 00376 } 00377 netif_default = netif; 00378 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 00379 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 00380 } 00381 00382 /** 00383 * Bring an interface up, available for processing 00384 * traffic. 00385 * 00386 * @note: Enabling DHCP on a down interface will make it come 00387 * up once configured. 00388 * 00389 * @see dhcp_start() 00390 */ 00391 void netif_set_up(struct netif *netif) 00392 { 00393 if ( !(netif->flags & NETIF_FLAG_UP )) { 00394 netif->flags |= NETIF_FLAG_UP; 00395 00396 #if LWIP_SNMP 00397 snmp_get_sysuptime(&netif->ts); 00398 #endif /* LWIP_SNMP */ 00399 00400 NETIF_LINK_CALLBACK(netif); 00401 NETIF_STATUS_CALLBACK(netif); 00402 00403 #if LWIP_ARP 00404 /** For Ethernet network interfaces, we would like to send a 00405 * "gratuitous ARP"; this is an ARP packet sent by a node in order 00406 * to spontaneously cause other nodes to update an entry in their 00407 * ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6. 00408 */ 00409 if (netif->flags & NETIF_FLAG_ETHARP) { 00410 etharp_query(netif, &(netif->ip_addr), (struct pbuf *)(NULL)); 00411 } 00412 #endif /* LWIP_ARP */ 00413 00414 } 00415 } 00416 00417 /** 00418 * Bring an interface down, disabling any traffic processing. 00419 * 00420 * @note: Enabling DHCP on a down interface will make it come 00421 * up once configured. 00422 * 00423 * @see dhcp_start() 00424 */ 00425 void netif_set_down(struct netif *netif) 00426 { 00427 if ( netif->flags & NETIF_FLAG_UP ) 00428 { 00429 netif->flags &= ~NETIF_FLAG_UP; 00430 #if LWIP_SNMP 00431 snmp_get_sysuptime(&netif->ts); 00432 #endif 00433 00434 NETIF_LINK_CALLBACK(netif); 00435 NETIF_STATUS_CALLBACK(netif); 00436 } 00437 } 00438 00439 /** 00440 * Ask if an interface is up 00441 */ 00442 u8_t netif_is_up(struct netif *netif) 00443 { 00444 return (netif->flags & NETIF_FLAG_UP)?1:0; 00445 } 00446 00447 #if LWIP_NETIF_STATUS_CALLBACK 00448 /** 00449 * Set callback to be called when interface is brought up/down 00450 */ 00451 void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif )) 00452 { 00453 if ( netif ) 00454 netif->status_callback = status_callback; 00455 } 00456 #endif /* LWIP_NETIF_STATUS_CALLBACK */ 00457 00458 #if LWIP_NETIF_LINK_CALLBACK 00459 /** 00460 * Called by a driver when its link goes up 00461 */ 00462 void netif_set_link_up(struct netif *netif ) 00463 { 00464 netif->flags |= NETIF_FLAG_LINK_UP; 00465 00466 #if LWIP_ARP 00467 /** For Ethernet network interfaces, we would like to send a 00468 * "gratuitous ARP"; this is an ARP packet sent by a node in order 00469 * to spontaneously cause other nodes to update an entry in their 00470 * ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6. 00471 */ 00472 if (netif->flags & NETIF_FLAG_ETHARP) { 00473 etharp_query(netif, &(netif->ip_addr), NULL); 00474 } 00475 #endif /* LWIP_ARP */ 00476 00477 #if LWIP_IGMP 00478 /* resend IGMP memberships */ 00479 if (netif->flags & NETIF_FLAG_IGMP) { 00480 igmp_report_groups( netif); 00481 } 00482 #endif /* LWIP_IGMP */ 00483 00484 NETIF_LINK_CALLBACK(netif); 00485 } 00486 00487 /** 00488 * Called by a driver when its link goes down 00489 */ 00490 void netif_set_link_down(struct netif *netif ) 00491 { 00492 netif->flags &= ~NETIF_FLAG_LINK_UP; 00493 NETIF_LINK_CALLBACK(netif); 00494 } 00495 00496 /** 00497 * Ask if a link is up 00498 */ 00499 u8_t netif_is_link_up(struct netif *netif) 00500 { 00501 return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0; 00502 } 00503 00504 /** 00505 * Set callback to be called when link is brought up/down 00506 */ 00507 void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif )) 00508 { 00509 if (netif) { 00510 netif->link_callback = link_callback; 00511 } 00512 } 00513 #endif /* LWIP_NETIF_LINK_CALLBACK */ 00514 00515 #if ENABLE_LOOPBACK 00516 /** 00517 * Send an IP packet to be received on the same netif (loopif-like). 00518 * The pbuf is simply copied and handed back to netif->input. 00519 * In multithreaded mode, this is done directly since netif->input must put 00520 * the packet on a queue. 00521 * In callback mode, the packet is put on an internal queue and is fed to 00522 * netif->input by netif_poll(). 00523 * 00524 * @param netif the lwip network interface structure 00525 * @param p the (IP) packet to 'send' 00526 * @param ipaddr the ip address to send the packet to (not used) 00527 * @return ERR_OK if the packet has been sent 00528 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 00529 */ 00530 err_t 00531 netif_loop_output(struct netif *netif, struct pbuf *p, 00532 struct ip_addr *ipaddr) 00533 { 00534 struct pbuf *r; 00535 err_t err; 00536 struct pbuf *last; 00537 #if LWIP_LOOPBACK_MAX_PBUFS 00538 u8_t clen = 0; 00539 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00540 SYS_ARCH_DECL_PROTECT(lev); 00541 LWIP_UNUSED_ARG(ipaddr); 00542 00543 /* Allocate a new pbuf */ 00544 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 00545 if (r == NULL) { 00546 return ERR_MEM; 00547 } 00548 #if LWIP_LOOPBACK_MAX_PBUFS 00549 clen = pbuf_clen(r); 00550 /* check for overflow or too many pbuf on queue */ 00551 if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 00552 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { 00553 pbuf_free(r); 00554 r = NULL; 00555 return ERR_MEM; 00556 } 00557 netif->loop_cnt_current += clen; 00558 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00559 00560 /* Copy the whole pbuf queue p into the single pbuf r */ 00561 if ((err = pbuf_copy(r, p)) != ERR_OK) { 00562 pbuf_free(r); 00563 r = NULL; 00564 return err; 00565 } 00566 00567 /* Put the packet on a linked list which gets emptied through calling 00568 netif_poll(). */ 00569 00570 /* let last point to the last pbuf in chain r */ 00571 for (last = r; last->next != NULL; last = last->next); 00572 00573 SYS_ARCH_PROTECT(lev); 00574 if(netif->loop_first != NULL) { 00575 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 00576 netif->loop_last->next = r; 00577 netif->loop_last = last; 00578 } else { 00579 netif->loop_first = r; 00580 netif->loop_last = last; 00581 } 00582 SYS_ARCH_UNPROTECT(lev); 00583 00584 #if LWIP_NETIF_LOOPBACK_MULTITHREADING 00585 /* For multithreading environment, schedule a call to netif_poll */ 00586 tcpip_callback(netif_poll, netif); 00587 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00588 00589 return ERR_OK; 00590 } 00591 00592 /** 00593 * Call netif_poll() in the main loop of your application. This is to prevent 00594 * reentering non-reentrant functions like tcp_input(). Packets passed to 00595 * netif_loop_output() are put on a list that is passed to netif->input() by 00596 * netif_poll(). 00597 */ 00598 void 00599 netif_poll(struct netif *netif) 00600 { 00601 struct pbuf *in; 00602 SYS_ARCH_DECL_PROTECT(lev); 00603 00604 do { 00605 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 00606 SYS_ARCH_PROTECT(lev); 00607 in = netif->loop_first; 00608 if(in != NULL) { 00609 struct pbuf *in_end = in; 00610 #if LWIP_LOOPBACK_MAX_PBUFS 00611 u8_t clen = pbuf_clen(in); 00612 /* adjust the number of pbufs on queue */ 00613 LWIP_ASSERT("netif->loop_cnt_current underflow", 00614 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 00615 netif->loop_cnt_current -= clen; 00616 #endif /* LWIP_LOOPBACK_MAX_PBUFS */ 00617 while(in_end->len != in_end->tot_len) { 00618 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 00619 in_end = in_end->next; 00620 } 00621 /* 'in_end' now points to the last pbuf from 'in' */ 00622 if(in_end == netif->loop_last) { 00623 /* this was the last pbuf in the list */ 00624 netif->loop_first = netif->loop_last = NULL; 00625 } else { 00626 /* pop the pbuf off the list */ 00627 netif->loop_first = in_end->next; 00628 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 00629 } 00630 /* De-queue the pbuf from its successors on the 'loop_' list. */ 00631 in_end->next = NULL; 00632 } 00633 SYS_ARCH_UNPROTECT(lev); 00634 00635 if(in != NULL) { 00636 /* loopback packets are always IP packets! */ 00637 if(ip_input(in, netif) != ERR_OK) { 00638 pbuf_free(in); 00639 } 00640 /* Don't reference the packet any more! */ 00641 in = NULL; 00642 } 00643 /* go on while there is a packet on the list */ 00644 } while(netif->loop_first != NULL); 00645 } 00646 00647 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING 00648 /** 00649 * Calls netif_poll() for every netif on the netif_list. 00650 */ 00651 void 00652 netif_poll_all(void) 00653 { 00654 struct netif *netif = netif_list; 00655 /* loop through netifs */ 00656 while (netif != NULL) { 00657 netif_poll(netif); 00658 /* proceed to next network interface */ 00659 netif = netif->next; 00660 } 00661 } 00662 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 00663 #endif /* ENABLE_LOOPBACK */
Generated on Tue Jul 12 2022 19:24:05 by 1.7.2