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