1/** 2 * @file 3 * lwIP network interface abstraction 4 * 5 */ 6 7/* 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, 12 * are permitted provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 * This file is part of the lwIP TCP/IP stack. 34 * 35 * Author: Adam Dunkels <adam@sics.se> 36 * 37 */ 38 39#include "lwip/opt.h" 40 41#include "lwip/def.h" 42#include "lwip/ip_addr.h" 43#include "lwip/netif.h" 44#include "lwip/tcp_impl.h" 45#include "lwip/snmp.h" 46#include "lwip/igmp.h" 47#include "netif/etharp.h" 48#include "lwip/stats.h" 49#if ENABLE_LOOPBACK 50#include "lwip/sys.h" 51#if LWIP_NETIF_LOOPBACK_MULTITHREADING 52#include "lwip/tcpip.h" 53#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 54#endif /* ENABLE_LOOPBACK */ 55 56#if LWIP_AUTOIP 57#include "lwip/autoip.h" 58#endif /* LWIP_AUTOIP */ 59#if LWIP_DHCP 60#include "lwip/dhcp.h" 61#endif /* LWIP_DHCP */ 62 63#if LWIP_NETIF_STATUS_CALLBACK 64#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) 65#else 66#define NETIF_STATUS_CALLBACK(n) 67#endif /* LWIP_NETIF_STATUS_CALLBACK */ 68 69#if LWIP_NETIF_LINK_CALLBACK 70#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0) 71#else 72#define NETIF_LINK_CALLBACK(n) 73#endif /* LWIP_NETIF_LINK_CALLBACK */ 74 75struct netif *netif_list; 76struct netif *netif_default; 77 78#if LWIP_HAVE_LOOPIF 79static struct netif loop_netif; 80 81/** 82 * Initialize a lwip network interface structure for a loopback interface 83 * 84 * @param netif the lwip network interface structure for this loopif 85 * @return ERR_OK if the loopif is initialized 86 * ERR_MEM if private data couldn't be allocated 87 */ 88static err_t 89netif_loopif_init(struct netif *netif) 90{ 91 /* initialize the snmp variables and counters inside the struct netif 92 * ifSpeed: no assumption can be made! 93 */ 94 NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0); 95 96 netif->name[0] = 'l'; 97 netif->name[1] = 'o'; 98 netif->output = netif_loop_output; 99 return ERR_OK; 100} 101#endif /* LWIP_HAVE_LOOPIF */ 102 103void 104netif_init(void) 105{ 106#if LWIP_HAVE_LOOPIF 107 ip_addr_t loop_ipaddr, loop_netmask, loop_gw; 108 IP4_ADDR(&loop_gw, 127,0,0,1); 109 IP4_ADDR(&loop_ipaddr, 127,0,0,1); 110 IP4_ADDR(&loop_netmask, 255,0,0,0); 111 112#if NO_SYS 113 netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input); 114#else /* NO_SYS */ 115 netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input); 116#endif /* NO_SYS */ 117 netif_set_up(&loop_netif); 118 119#endif /* LWIP_HAVE_LOOPIF */ 120} 121 122/** 123 * Add a network interface to the list of lwIP netifs. 124 * 125 * @param netif a pre-allocated netif structure 126 * @param ipaddr IP address for the new netif 127 * @param netmask network mask for the new netif 128 * @param gw default gateway IP address for the new netif 129 * @param state opaque data passed to the new netif 130 * @param init callback function that initializes the interface 131 * @param input callback function that is called to pass 132 * ingress packets up in the protocol layer stack. 133 * 134 * @return netif, or NULL if failed. 135 */ 136struct netif * 137netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, 138 ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input) 139{ 140 static u8_t netifnum = 0; 141 142 LWIP_ASSERT("No init function given", init != NULL); 143 144 /* reset new interface configuration state */ 145 ip_addr_set_zero(&netif->ip_addr); 146 ip_addr_set_zero(&netif->netmask); 147 ip_addr_set_zero(&netif->gw); 148 netif->flags = 0; 149#if LWIP_DHCP 150 /* netif not under DHCP control by default */ 151 netif->dhcp = NULL; 152#endif /* LWIP_DHCP */ 153#if LWIP_AUTOIP 154 /* netif not under AutoIP control by default */ 155 netif->autoip = NULL; 156#endif /* LWIP_AUTOIP */ 157#if LWIP_NETIF_STATUS_CALLBACK 158 netif->status_callback = NULL; 159#endif /* LWIP_NETIF_STATUS_CALLBACK */ 160#if LWIP_NETIF_LINK_CALLBACK 161 netif->link_callback = NULL; 162#endif /* LWIP_NETIF_LINK_CALLBACK */ 163#if LWIP_IGMP 164 netif->igmp_mac_filter = NULL; 165#endif /* LWIP_IGMP */ 166#if ENABLE_LOOPBACK 167 netif->loop_first = NULL; 168 netif->loop_last = NULL; 169#endif /* ENABLE_LOOPBACK */ 170 171 /* remember netif specific state information data */ 172 netif->state = state; 173 netif->num = netifnum++; 174 netif->input = input; 175#if LWIP_NETIF_HWADDRHINT 176 netif->addr_hint = NULL; 177#endif /* LWIP_NETIF_HWADDRHINT*/ 178#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS 179 netif->loop_cnt_current = 0; 180#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */ 181 182 netif_set_addr(netif, ipaddr, netmask, gw); 183 184 /* call user specified initialization function for netif */ 185 if (init(netif) != ERR_OK) { 186 return NULL; 187 } 188 189 /* add this netif to the list */ 190 netif->next = netif_list; 191 netif_list = netif; 192 snmp_inc_iflist(); 193 194#if LWIP_IGMP 195 /* start IGMP processing */ 196 if (netif->flags & NETIF_FLAG_IGMP) { 197 igmp_start(netif); 198 } 199#endif /* LWIP_IGMP */ 200 201 LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ", 202 netif->name[0], netif->name[1])); 203 ip_addr_debug_print(NETIF_DEBUG, ipaddr); 204 LWIP_DEBUGF(NETIF_DEBUG, (" netmask ")); 205 ip_addr_debug_print(NETIF_DEBUG, netmask); 206 LWIP_DEBUGF(NETIF_DEBUG, (" gw ")); 207 ip_addr_debug_print(NETIF_DEBUG, gw); 208 LWIP_DEBUGF(NETIF_DEBUG, ("\n")); 209 return netif; 210} 211 212/** 213 * Change IP address configuration for a network interface (including netmask 214 * and default gateway). 215 * 216 * @param netif the network interface to change 217 * @param ipaddr the new IP address 218 * @param netmask the new netmask 219 * @param gw the new default gateway 220 */ 221void 222netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, 223 ip_addr_t *gw) 224{ 225 netif_set_ipaddr(netif, ipaddr); 226 netif_set_netmask(netif, netmask); 227 netif_set_gw(netif, gw); 228} 229 230/** 231 * Remove a network interface from the list of lwIP netifs. 232 * 233 * @param netif the network interface to remove 234 */ 235void 236netif_remove(struct netif *netif) 237{ 238 if (netif == NULL) { 239 return; 240 } 241 242#if LWIP_IGMP 243 /* stop IGMP processing */ 244 if (netif->flags & NETIF_FLAG_IGMP) { 245 igmp_stop(netif); 246 } 247#endif /* LWIP_IGMP */ 248 if (netif_is_up(netif)) { 249 /* set netif down before removing (call callback function) */ 250 netif_set_down(netif); 251 } 252 253 snmp_delete_ipaddridx_tree(netif); 254 255 /* is it the first netif? */ 256 if (netif_list == netif) { 257 netif_list = netif->next; 258 } else { 259 /* look for netif further down the list */ 260 struct netif * tmpNetif; 261 for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) { 262 if (tmpNetif->next == netif) { 263 tmpNetif->next = netif->next; 264 break; 265 } 266 } 267 if (tmpNetif == NULL) 268 return; /* we didn't find any netif today */ 269 } 270 snmp_dec_iflist(); 271 /* this netif is default? */ 272 if (netif_default == netif) { 273 /* reset default netif */ 274 netif_set_default(NULL); 275 } 276 LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); 277} 278 279/** 280 * Find a network interface by searching for its name 281 * 282 * @param name the name of the netif (like netif->name) plus concatenated number 283 * in ascii representation (e.g. 'en0') 284 */ 285struct netif * 286netif_find(char *name) 287{ 288 struct netif *netif; 289 u8_t num; 290 291 if (name == NULL) { 292 return NULL; 293 } 294 295 num = name[2] - '0'; 296 297 for(netif = netif_list; netif != NULL; netif = netif->next) { 298 if (num == netif->num && 299 name[0] == netif->name[0] && 300 name[1] == netif->name[1]) { 301 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); 302 return netif; 303 } 304 } 305 LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); 306 return NULL; 307} 308 309/** 310 * Change the IP address of a network interface 311 * 312 * @param netif the network interface to change 313 * @param ipaddr the new IP address 314 * 315 * @note call netif_set_addr() if you also want to change netmask and 316 * default gateway 317 */ 318void 319netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr) 320{ 321 /* TODO: Handling of obsolete pcbs */ 322 /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */ 323#if LWIP_TCP 324 struct tcp_pcb *pcb; 325 struct tcp_pcb_listen *lpcb; 326 327 /* address is actually being changed? */ 328 if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) { 329 /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */ 330 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n")); 331 pcb = tcp_active_pcbs; 332 while (pcb != NULL) { 333 /* PCB bound to current local interface address? */ 334 if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr)) 335#if LWIP_AUTOIP 336 /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */ 337 && !ip_addr_islinklocal(&(pcb->local_ip)) 338#endif /* LWIP_AUTOIP */ 339 ) { 340 /* this connection must be aborted */ 341 struct tcp_pcb *next = pcb->next; 342 LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb)); 343 tcp_abort(pcb); 344 pcb = next; 345 } else { 346 pcb = pcb->next; 347 } 348 } 349 for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { 350 /* PCB bound to current local interface address? */ 351 if ((!(ip_addr_isany(&(lpcb->local_ip)))) && 352 (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) { 353 /* The PCB is listening to the old ipaddr and 354 * is set to listen to the new one instead */ 355 ip_addr_set(&(lpcb->local_ip), ipaddr); 356 } 357 } 358 } 359#endif 360 snmp_delete_ipaddridx_tree(netif); 361 snmp_delete_iprteidx_tree(0,netif); 362 /* set new IP address to netif */ 363 ip_addr_set(&(netif->ip_addr), ipaddr); 364 snmp_insert_ipaddridx_tree(netif); 365 snmp_insert_iprteidx_tree(0,netif); 366 367 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", 368 netif->name[0], netif->name[1], 369 ip4_addr1_16(&netif->ip_addr), 370 ip4_addr2_16(&netif->ip_addr), 371 ip4_addr3_16(&netif->ip_addr), 372 ip4_addr4_16(&netif->ip_addr))); 373} 374 375/** 376 * Change the default gateway for a network interface 377 * 378 * @param netif the network interface to change 379 * @param gw the new default gateway 380 * 381 * @note call netif_set_addr() if you also want to change ip address and netmask 382 */ 383void 384netif_set_gw(struct netif *netif, ip_addr_t *gw) 385{ 386 ip_addr_set(&(netif->gw), gw); 387 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", 388 netif->name[0], netif->name[1], 389 ip4_addr1_16(&netif->gw), 390 ip4_addr2_16(&netif->gw), 391 ip4_addr3_16(&netif->gw), 392 ip4_addr4_16(&netif->gw))); 393} 394 395/** 396 * Change the netmask of a network interface 397 * 398 * @param netif the network interface to change 399 * @param netmask the new netmask 400 * 401 * @note call netif_set_addr() if you also want to change ip address and 402 * default gateway 403 */ 404void 405netif_set_netmask(struct netif *netif, ip_addr_t *netmask) 406{ 407 snmp_delete_iprteidx_tree(0, netif); 408 /* set new netmask to netif */ 409 ip_addr_set(&(netif->netmask), netmask); 410 snmp_insert_iprteidx_tree(0, netif); 411 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", 412 netif->name[0], netif->name[1], 413 ip4_addr1_16(&netif->netmask), 414 ip4_addr2_16(&netif->netmask), 415 ip4_addr3_16(&netif->netmask), 416 ip4_addr4_16(&netif->netmask))); 417} 418 419/** 420 * Set a network interface as the default network interface 421 * (used to output all packets for which no specific route is found) 422 * 423 * @param netif the default network interface 424 */ 425void 426netif_set_default(struct netif *netif) 427{ 428 if (netif == NULL) { 429 /* remove default route */ 430 snmp_delete_iprteidx_tree(1, netif); 431 } else { 432 /* install default route */ 433 snmp_insert_iprteidx_tree(1, netif); 434 } 435 netif_default = netif; 436 LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", 437 netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); 438} 439 440/** 441 * Bring an interface up, available for processing 442 * traffic. 443 * 444 * @note: Enabling DHCP on a down interface will make it come 445 * up once configured. 446 * 447 * @see dhcp_start() 448 */ 449void netif_set_up(struct netif *netif) 450{ 451 if (!(netif->flags & NETIF_FLAG_UP)) { 452 netif->flags |= NETIF_FLAG_UP; 453 454#if LWIP_SNMP 455 snmp_get_sysuptime(&netif->ts); 456#endif /* LWIP_SNMP */ 457 458 NETIF_STATUS_CALLBACK(netif); 459 460 if (netif->flags & NETIF_FLAG_LINK_UP) { 461#if LWIP_ARP 462 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 463 if (netif->flags & (NETIF_FLAG_ETHARP)) { 464 etharp_gratuitous(netif); 465 } 466#endif /* LWIP_ARP */ 467 468#if LWIP_IGMP 469 /* resend IGMP memberships */ 470 if (netif->flags & NETIF_FLAG_IGMP) { 471 igmp_report_groups( netif); 472 } 473#endif /* LWIP_IGMP */ 474 } 475 } 476} 477 478/** 479 * Bring an interface down, disabling any traffic processing. 480 * 481 * @note: Enabling DHCP on a down interface will make it come 482 * up once configured. 483 * 484 * @see dhcp_start() 485 */ 486void netif_set_down(struct netif *netif) 487{ 488 if (netif->flags & NETIF_FLAG_UP) { 489 netif->flags &= ~NETIF_FLAG_UP; 490#if LWIP_SNMP 491 snmp_get_sysuptime(&netif->ts); 492#endif 493 494 NETIF_STATUS_CALLBACK(netif); 495 } 496} 497 498#if LWIP_NETIF_STATUS_CALLBACK 499/** 500 * Set callback to be called when interface is brought up/down 501 */ 502void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback) 503{ 504 if (netif) { 505 netif->status_callback = status_callback; 506 } 507} 508#endif /* LWIP_NETIF_STATUS_CALLBACK */ 509 510/** 511 * Called by a driver when its link goes up 512 */ 513void netif_set_link_up(struct netif *netif ) 514{ 515 if (!(netif->flags & NETIF_FLAG_LINK_UP)) { 516 netif->flags |= NETIF_FLAG_LINK_UP; 517 518#if LWIP_DHCP 519 if (netif->dhcp) { 520 dhcp_network_changed(netif); 521 } 522#endif /* LWIP_DHCP */ 523 524#if LWIP_AUTOIP 525 if (netif->autoip) { 526 autoip_network_changed(netif); 527 } 528#endif /* LWIP_AUTOIP */ 529 530 if (netif->flags & NETIF_FLAG_UP) { 531#if LWIP_ARP 532 /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */ 533 if (netif->flags & NETIF_FLAG_ETHARP) { 534 etharp_gratuitous(netif); 535 } 536#endif /* LWIP_ARP */ 537 538#if LWIP_IGMP 539 /* resend IGMP memberships */ 540 if (netif->flags & NETIF_FLAG_IGMP) { 541 igmp_report_groups( netif); 542 } 543#endif /* LWIP_IGMP */ 544 } 545 NETIF_LINK_CALLBACK(netif); 546 } 547} 548 549/** 550 * Called by a driver when its link goes down 551 */ 552void netif_set_link_down(struct netif *netif ) 553{ 554 if (netif->flags & NETIF_FLAG_LINK_UP) { 555 netif->flags &= ~NETIF_FLAG_LINK_UP; 556 NETIF_LINK_CALLBACK(netif); 557 } 558} 559 560#if LWIP_NETIF_LINK_CALLBACK 561/** 562 * Set callback to be called when link is brought up/down 563 */ 564void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback) 565{ 566 if (netif) { 567 netif->link_callback = link_callback; 568 } 569} 570#endif /* LWIP_NETIF_LINK_CALLBACK */ 571 572#if ENABLE_LOOPBACK 573/** 574 * Send an IP packet to be received on the same netif (loopif-like). 575 * The pbuf is simply copied and handed back to netif->input. 576 * In multithreaded mode, this is done directly since netif->input must put 577 * the packet on a queue. 578 * In callback mode, the packet is put on an internal queue and is fed to 579 * netif->input by netif_poll(). 580 * 581 * @param netif the lwip network interface structure 582 * @param p the (IP) packet to 'send' 583 * @param ipaddr the ip address to send the packet to (not used) 584 * @return ERR_OK if the packet has been sent 585 * ERR_MEM if the pbuf used to copy the packet couldn't be allocated 586 */ 587err_t 588netif_loop_output(struct netif *netif, struct pbuf *p, 589 ip_addr_t *ipaddr) 590{ 591 struct pbuf *r; 592 err_t err; 593 struct pbuf *last; 594#if LWIP_LOOPBACK_MAX_PBUFS 595 u8_t clen = 0; 596#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 597 /* If we have a loopif, SNMP counters are adjusted for it, 598 * if not they are adjusted for 'netif'. */ 599#if LWIP_SNMP 600#if LWIP_HAVE_LOOPIF 601 struct netif *stats_if = &loop_netif; 602#else /* LWIP_HAVE_LOOPIF */ 603 struct netif *stats_if = netif; 604#endif /* LWIP_HAVE_LOOPIF */ 605#endif /* LWIP_SNMP */ 606 SYS_ARCH_DECL_PROTECT(lev); 607 LWIP_UNUSED_ARG(ipaddr); 608 609 /* Allocate a new pbuf */ 610 r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM); 611 if (r == NULL) { 612 LINK_STATS_INC(link.memerr); 613 LINK_STATS_INC(link.drop); 614 snmp_inc_ifoutdiscards(stats_if); 615 return ERR_MEM; 616 } 617#if LWIP_LOOPBACK_MAX_PBUFS 618 clen = pbuf_clen(r); 619 /* check for overflow or too many pbuf on queue */ 620 if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) || 621 ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) { 622 pbuf_free(r); 623 LINK_STATS_INC(link.memerr); 624 LINK_STATS_INC(link.drop); 625 snmp_inc_ifoutdiscards(stats_if); 626 return ERR_MEM; 627 } 628 netif->loop_cnt_current += clen; 629#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 630 631 /* Copy the whole pbuf queue p into the single pbuf r */ 632 if ((err = pbuf_copy(r, p)) != ERR_OK) { 633 pbuf_free(r); 634 LINK_STATS_INC(link.memerr); 635 LINK_STATS_INC(link.drop); 636 snmp_inc_ifoutdiscards(stats_if); 637 return err; 638 } 639 640 /* Put the packet on a linked list which gets emptied through calling 641 netif_poll(). */ 642 643 /* let last point to the last pbuf in chain r */ 644 for (last = r; last->next != NULL; last = last->next); 645 646 SYS_ARCH_PROTECT(lev); 647 if(netif->loop_first != NULL) { 648 LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL); 649 netif->loop_last->next = r; 650 netif->loop_last = last; 651 } else { 652 netif->loop_first = r; 653 netif->loop_last = last; 654 } 655 SYS_ARCH_UNPROTECT(lev); 656 657 LINK_STATS_INC(link.xmit); 658 snmp_add_ifoutoctets(stats_if, p->tot_len); 659 snmp_inc_ifoutucastpkts(stats_if); 660 661#if LWIP_NETIF_LOOPBACK_MULTITHREADING 662 /* For multithreading environment, schedule a call to netif_poll */ 663 tcpip_callback((tcpip_callback_fn)netif_poll, netif); 664#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */ 665 666 return ERR_OK; 667} 668 669/** 670 * Call netif_poll() in the main loop of your application. This is to prevent 671 * reentering non-reentrant functions like tcp_input(). Packets passed to 672 * netif_loop_output() are put on a list that is passed to netif->input() by 673 * netif_poll(). 674 */ 675void 676netif_poll(struct netif *netif) 677{ 678 struct pbuf *in; 679 /* If we have a loopif, SNMP counters are adjusted for it, 680 * if not they are adjusted for 'netif'. */ 681#if LWIP_SNMP 682#if LWIP_HAVE_LOOPIF 683 struct netif *stats_if = &loop_netif; 684#else /* LWIP_HAVE_LOOPIF */ 685 struct netif *stats_if = netif; 686#endif /* LWIP_HAVE_LOOPIF */ 687#endif /* LWIP_SNMP */ 688 SYS_ARCH_DECL_PROTECT(lev); 689 690 do { 691 /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */ 692 SYS_ARCH_PROTECT(lev); 693 in = netif->loop_first; 694 if (in != NULL) { 695 struct pbuf *in_end = in; 696#if LWIP_LOOPBACK_MAX_PBUFS 697 u8_t clen = pbuf_clen(in); 698 /* adjust the number of pbufs on queue */ 699 LWIP_ASSERT("netif->loop_cnt_current underflow", 700 ((netif->loop_cnt_current - clen) < netif->loop_cnt_current)); 701 netif->loop_cnt_current -= clen; 702#endif /* LWIP_LOOPBACK_MAX_PBUFS */ 703 while (in_end->len != in_end->tot_len) { 704 LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL); 705 in_end = in_end->next; 706 } 707 /* 'in_end' now points to the last pbuf from 'in' */ 708 if (in_end == netif->loop_last) { 709 /* this was the last pbuf in the list */ 710 netif->loop_first = netif->loop_last = NULL; 711 } else { 712 /* pop the pbuf off the list */ 713 netif->loop_first = in_end->next; 714 LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL); 715 } 716 /* De-queue the pbuf from its successors on the 'loop_' list. */ 717 in_end->next = NULL; 718 } 719 SYS_ARCH_UNPROTECT(lev); 720 721 if (in != NULL) { 722 LINK_STATS_INC(link.recv); 723 snmp_add_ifinoctets(stats_if, in->tot_len); 724 snmp_inc_ifinucastpkts(stats_if); 725 /* loopback packets are always IP packets! */ 726 if (ip_input(in, netif) != ERR_OK) { 727 pbuf_free(in); 728 } 729 /* Don't reference the packet any more! */ 730 in = NULL; 731 } 732 /* go on while there is a packet on the list */ 733 } while (netif->loop_first != NULL); 734} 735 736#if !LWIP_NETIF_LOOPBACK_MULTITHREADING 737/** 738 * Calls netif_poll() for every netif on the netif_list. 739 */ 740void 741netif_poll_all(void) 742{ 743 struct netif *netif = netif_list; 744 /* loop through netifs */ 745 while (netif != NULL) { 746 netif_poll(netif); 747 /* proceed to next network interface */ 748 netif = netif->next; 749 } 750} 751#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */ 752#endif /* ENABLE_LOOPBACK */ 753