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 (at) 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 75 struct netif *netif_list; 76 struct netif *netif_default; 77 78 #if LWIP_HAVE_LOOPIF 79 static 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 */ 88 static err_t 89 netif_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 103 void 104 netif_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 */ 136 struct netif * 137 netif_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 */ 221 void 222 netif_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 */ 235 void 236 netif_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 */ 285 struct netif * 286 netif_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 */ 318 void 319 netif_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 */ 383 void 384 netif_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 */ 404 void 405 netif_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 */ 425 void 426 netif_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 */ 449 void 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 */ 486 void 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 */ 502 void 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 */ 513 void 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 */ 552 void 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 */ 564 void 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 */ 587 err_t 588 netif_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 */ 675 void 676 netif_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 */ 740 void 741 netif_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