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