Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed
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 19:17:23 by 1.7.2