Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
netif.c
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