MeterLogger
netif.c
Go to the documentation of this file.
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 
75 struct netif *netif_list;
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  */
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  */
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
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 *
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  netif->dhcps_pcb = NULL;
153 #endif /* LWIP_DHCP */
154 #if LWIP_AUTOIP
155  /* netif not under AutoIP control by default */
156  netif->autoip = NULL;
157 #endif /* LWIP_AUTOIP */
158 #if LWIP_NETIF_STATUS_CALLBACK
159  netif->status_callback = NULL;
160 #endif /* LWIP_NETIF_STATUS_CALLBACK */
161 #if LWIP_NETIF_LINK_CALLBACK
162  netif->link_callback = NULL;
163 #endif /* LWIP_NETIF_LINK_CALLBACK */
164 #if LWIP_IGMP
165  netif->igmp_mac_filter = NULL;
166 #endif /* LWIP_IGMP */
167 #if ENABLE_LOOPBACK
168  netif->loop_first = NULL;
169  netif->loop_last = NULL;
170 #endif /* ENABLE_LOOPBACK */
171 
172  /* remember netif specific state information data */
173  netif->state = state;
174  netif->num = netifnum++;
175  netif->input = input;
176 #if LWIP_NETIF_HWADDRHINT
177  netif->addr_hint = NULL;
178 #endif /* LWIP_NETIF_HWADDRHINT*/
179 #if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
180  netif->loop_cnt_current = 0;
181 #endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
182 
183 #if IP_NAPT
184  netif->napt = 0;
185 #endif /* IP_NAPT */
186 
187  netif_set_addr(netif, ipaddr, netmask, gw);
188 
189  /* call user specified initialization function for netif */
190  if (init(netif) != ERR_OK) {
191  return NULL;
192  }
193 
194  /* add this netif to the list */
195  netif->next = netif_list;
196  netif_list = netif;
197  snmp_inc_iflist();
198 
199 #if LWIP_IGMP
200  /* start IGMP processing */
201  if (netif->flags & NETIF_FLAG_IGMP) {
202  igmp_start(netif);
203  }
204 #endif /* LWIP_IGMP */
205 
206  LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
207  netif->name[0], netif->name[1]));
209  LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
211  LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
213  LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
214  return netif;
215 }
216 
217 /**
218  * Change IP address configuration for a network interface (including netmask
219  * and default gateway).
220  *
221  * @param netif the network interface to change
222  * @param ipaddr the new IP address
223  * @param netmask the new netmask
224  * @param gw the new default gateway
225  */
226 void
228  ip_addr_t *gw)
229 {
230  netif_set_ipaddr(netif, ipaddr);
231  netif_set_netmask(netif, netmask);
232  netif_set_gw(netif, gw);
233 }
234 
235 /**
236  * Remove a network interface from the list of lwIP netifs.
237  *
238  * @param netif the network interface to remove
239  */
240 void
242 {
243  if (netif == NULL) {
244  return;
245  }
246 
247 #if LWIP_IGMP
248  /* stop IGMP processing */
249  if (netif->flags & NETIF_FLAG_IGMP) {
250  igmp_stop(netif);
251  }
252 #endif /* LWIP_IGMP */
253  if (netif_is_up(netif)) {
254  /* set netif down before removing (call callback function) */
255  netif_set_down(netif);
256  }
257 
259 
260  /* is it the first netif? */
261  if (netif_list == netif) {
262  netif_list = netif->next;
263  } else {
264  /* look for netif further down the list */
265  struct netif * tmpNetif;
266  for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
267  if (tmpNetif->next == netif) {
268  tmpNetif->next = netif->next;
269  break;
270  }
271  }
272  if (tmpNetif == NULL)
273  return; /* we didn't find any netif today */
274  }
275  snmp_dec_iflist();
276  /* this netif is default? */
277  if (netif_default == netif) {
278  /* reset default netif */
280  }
281  LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
282 }
283 
284 /**
285  * Find a network interface by searching for its name
286  *
287  * @param name the name of the netif (like netif->name) plus concatenated number
288  * in ascii representation (e.g. 'en0')
289  */
290 struct netif *
292 {
293  struct netif *netif;
294  u8_t num;
295 
296  if (name == NULL) {
297  return NULL;
298  }
299 
300  num = name[2] - '0';
301 
302  for(netif = netif_list; netif != NULL; netif = netif->next) {
303  if (num == netif->num &&
304  name[0] == netif->name[0] &&
305  name[1] == netif->name[1]) {
306  LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
307  return netif;
308  }
309  }
310  LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
311  return NULL;
312 }
313 
314 /**
315  * Change the IP address of a network interface
316  *
317  * @param netif the network interface to change
318  * @param ipaddr the new IP address
319  *
320  * @note call netif_set_addr() if you also want to change netmask and
321  * default gateway
322  */
323 void
325 {
326  /* TODO: Handling of obsolete pcbs */
327  /* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */
328 #if LWIP_TCP
329  struct tcp_pcb *pcb;
330  struct tcp_pcb_listen *lpcb;
331 
332  /* address is actually being changed? */
333  if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) {
334  /* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
335  LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
336  pcb = tcp_active_pcbs;
337  while (pcb != NULL) {
338  /* PCB bound to current local interface address? */
339  if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
340 #if LWIP_AUTOIP
341  /* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
342  && !ip_addr_islinklocal(&(pcb->local_ip))
343 #endif /* LWIP_AUTOIP */
344  ) {
345  /* this connection must be aborted */
346  struct tcp_pcb *next = pcb->next;
347  LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
348  tcp_abort(pcb);
349  pcb = next;
350  } else {
351  pcb = pcb->next;
352  }
353  }
354  for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
355  /* PCB bound to current local interface address? */
356  if ((!(ip_addr_isany(&(lpcb->local_ip)))) &&
357  (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr)))) {
358  /* The PCB is listening to the old ipaddr and
359  * is set to listen to the new one instead */
360  ip_addr_set(&(lpcb->local_ip), ipaddr);
361  }
362  }
363  }
364 #endif
366  snmp_delete_iprteidx_tree(0,netif);
367  /* set new IP address to netif */
368  ip_addr_set(&(netif->ip_addr), ipaddr);
370  snmp_insert_iprteidx_tree(0,netif);
371 
372  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",
373  netif->name[0], netif->name[1],
374  ip4_addr1_16(&netif->ip_addr),
375  ip4_addr2_16(&netif->ip_addr),
376  ip4_addr3_16(&netif->ip_addr),
377  ip4_addr4_16(&netif->ip_addr)));
378 }
379 
380 /**
381  * Change the default gateway for a network interface
382  *
383  * @param netif the network interface to change
384  * @param gw the new default gateway
385  *
386  * @note call netif_set_addr() if you also want to change ip address and netmask
387  */
388 void
390 {
391  ip_addr_set(&(netif->gw), gw);
392  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",
393  netif->name[0], netif->name[1],
394  ip4_addr1_16(&netif->gw),
395  ip4_addr2_16(&netif->gw),
396  ip4_addr3_16(&netif->gw),
397  ip4_addr4_16(&netif->gw)));
398 }
399 
400 /**
401  * Change the netmask of a network interface
402  *
403  * @param netif the network interface to change
404  * @param netmask the new netmask
405  *
406  * @note call netif_set_addr() if you also want to change ip address and
407  * default gateway
408  */
409 void
411 {
412  snmp_delete_iprteidx_tree(0, netif);
413  /* set new netmask to netif */
414  ip_addr_set(&(netif->netmask), netmask);
415  snmp_insert_iprteidx_tree(0, netif);
416  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",
417  netif->name[0], netif->name[1],
418  ip4_addr1_16(&netif->netmask),
419  ip4_addr2_16(&netif->netmask),
420  ip4_addr3_16(&netif->netmask),
421  ip4_addr4_16(&netif->netmask)));
422 }
423 
424 /**
425  * Set a network interface as the default network interface
426  * (used to output all packets for which no specific route is found)
427  *
428  * @param netif the default network interface
429  */
430 void
432 {
433  if (netif == NULL) {
434  /* remove default route */
435  snmp_delete_iprteidx_tree(1, netif);
436  } else {
437  /* install default route */
438  snmp_insert_iprteidx_tree(1, netif);
439  }
440  netif_default = netif;
441  LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
442  netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
443 }
444 
445 /**
446  * Bring an interface up, available for processing
447  * traffic.
448  *
449  * @note: Enabling DHCP on a down interface will make it come
450  * up once configured.
451  *
452  * @see dhcp_start()
453  */
454 void netif_set_up(struct netif *netif)
455 {
456  if (!(netif->flags & NETIF_FLAG_UP)) {
457  netif->flags |= NETIF_FLAG_UP;
458 
459 #if LWIP_SNMP
460  snmp_get_sysuptime(&netif->ts);
461 #endif /* LWIP_SNMP */
462 
463  NETIF_STATUS_CALLBACK(netif);
464 
465  if (netif->flags & NETIF_FLAG_LINK_UP) {
466 #if LWIP_ARP
467  /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
468  if (netif->flags & (NETIF_FLAG_ETHARP)) {
469  etharp_gratuitous(netif);
470  }
471 #endif /* LWIP_ARP */
472 
473 #if LWIP_IGMP
474  /* resend IGMP memberships */
475  if (netif->flags & NETIF_FLAG_IGMP) {
476  igmp_report_groups( netif);
477  }
478 #endif /* LWIP_IGMP */
479  }
480  }
481 }
482 
483 /**
484  * Bring an interface down, disabling any traffic processing.
485  *
486  * @note: Enabling DHCP on a down interface will make it come
487  * up once configured.
488  *
489  * @see dhcp_start()
490  */
492 {
493  if (netif->flags & NETIF_FLAG_UP) {
494  netif->flags &= ~NETIF_FLAG_UP;
495 #if LWIP_SNMP
496  snmp_get_sysuptime(&netif->ts);
497 #endif
498 
499 #if LWIP_ARP
500  if (netif->flags & NETIF_FLAG_ETHARP) {
501  etharp_cleanup_netif(netif);
502  }
503 #endif /* LWIP_ARP */
504  NETIF_STATUS_CALLBACK(netif);
505  }
506 }
507 
508 #if LWIP_NETIF_STATUS_CALLBACK
509 /**
510  * Set callback to be called when interface is brought up/down
511  */
512 void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
513 {
514  if (netif) {
515  netif->status_callback = status_callback;
516  }
517 }
518 #endif /* LWIP_NETIF_STATUS_CALLBACK */
519 
520 /**
521  * Called by a driver when its link goes up
522  */
523 void netif_set_link_up(struct netif *netif )
524 {
525  if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
526  netif->flags |= NETIF_FLAG_LINK_UP;
527 
528 #if LWIP_DHCP
529  if (netif->dhcp) {
530  dhcp_network_changed(netif);
531  }
532 #endif /* LWIP_DHCP */
533 
534 #if LWIP_AUTOIP
535  if (netif->autoip) {
536  autoip_network_changed(netif);
537  }
538 #endif /* LWIP_AUTOIP */
539 
540  if (netif->flags & NETIF_FLAG_UP) {
541 #if LWIP_ARP
542  /* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
543  if (netif->flags & NETIF_FLAG_ETHARP) {
544  etharp_gratuitous(netif);
545  }
546 #endif /* LWIP_ARP */
547 
548 #if LWIP_IGMP
549  /* resend IGMP memberships */
550  if (netif->flags & NETIF_FLAG_IGMP) {
551  igmp_report_groups( netif);
552  }
553 #endif /* LWIP_IGMP */
554  }
555  NETIF_LINK_CALLBACK(netif);
556  }
557 }
558 
559 /**
560  * Called by a driver when its link goes down
561  */
562 void netif_set_link_down(struct netif *netif )
563 {
564  if (netif->flags & NETIF_FLAG_LINK_UP) {
565  netif->flags &= ~NETIF_FLAG_LINK_UP;
566  NETIF_LINK_CALLBACK(netif);
567  }
568 }
569 
570 #if LWIP_NETIF_LINK_CALLBACK
571 /**
572  * Set callback to be called when link is brought up/down
573  */
574 void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
575 {
576  if (netif) {
577  netif->link_callback = link_callback;
578  }
579 }
580 #endif /* LWIP_NETIF_LINK_CALLBACK */
581 
582 #if ENABLE_LOOPBACK
583 /**
584  * Send an IP packet to be received on the same netif (loopif-like).
585  * The pbuf is simply copied and handed back to netif->input.
586  * In multithreaded mode, this is done directly since netif->input must put
587  * the packet on a queue.
588  * In callback mode, the packet is put on an internal queue and is fed to
589  * netif->input by netif_poll().
590  *
591  * @param netif the lwip network interface structure
592  * @param p the (IP) packet to 'send'
593  * @param ipaddr the ip address to send the packet to (not used)
594  * @return ERR_OK if the packet has been sent
595  * ERR_MEM if the pbuf used to copy the packet couldn't be allocated
596  */
597 err_t
598 netif_loop_output(struct netif *netif, struct pbuf *p,
599  ip_addr_t *ipaddr)
600 {
601  struct pbuf *r;
602  err_t err;
603  struct pbuf *last;
604 #if LWIP_LOOPBACK_MAX_PBUFS
605  u8_t clen = 0;
606 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
607  /* If we have a loopif, SNMP counters are adjusted for it,
608  * if not they are adjusted for 'netif'. */
609 #if LWIP_SNMP
610 #if LWIP_HAVE_LOOPIF
611  struct netif *stats_if = &loop_netif;
612 #else /* LWIP_HAVE_LOOPIF */
613  struct netif *stats_if = netif;
614 #endif /* LWIP_HAVE_LOOPIF */
615 #endif /* LWIP_SNMP */
617  LWIP_UNUSED_ARG(ipaddr);
618 
619  /* Allocate a new pbuf */
621  if (r == NULL) {
622  LINK_STATS_INC(link.memerr);
623  LINK_STATS_INC(link.drop);
624  snmp_inc_ifoutdiscards(stats_if);
625  return ERR_MEM;
626  }
627 #if LWIP_LOOPBACK_MAX_PBUFS
628  clen = pbuf_clen(r);
629  /* check for overflow or too many pbuf on queue */
630  if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
631  ((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
632  pbuf_free(r);
633  LINK_STATS_INC(link.memerr);
634  LINK_STATS_INC(link.drop);
635  snmp_inc_ifoutdiscards(stats_if);
636  return ERR_MEM;
637  }
638  netif->loop_cnt_current += clen;
639 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
640 
641  /* Copy the whole pbuf queue p into the single pbuf r */
642  if ((err = pbuf_copy(r, p)) != ERR_OK) {
643  pbuf_free(r);
644  LINK_STATS_INC(link.memerr);
645  LINK_STATS_INC(link.drop);
646  snmp_inc_ifoutdiscards(stats_if);
647  return err;
648  }
649 
650  /* Put the packet on a linked list which gets emptied through calling
651  netif_poll(). */
652 
653  /* let last point to the last pbuf in chain r */
654  for (last = r; last->next != NULL; last = last->next);
655 
656  SYS_ARCH_PROTECT(lev);
657  if(netif->loop_first != NULL) {
658  LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
659  netif->loop_last->next = r;
660  netif->loop_last = last;
661  } else {
662  netif->loop_first = r;
663  netif->loop_last = last;
664  }
665  SYS_ARCH_UNPROTECT(lev);
666 
667  LINK_STATS_INC(link.xmit);
668  snmp_add_ifoutoctets(stats_if, p->tot_len);
669  snmp_inc_ifoutucastpkts(stats_if);
670 
671 #if LWIP_NETIF_LOOPBACK_MULTITHREADING
672  /* For multithreading environment, schedule a call to netif_poll */
673  tcpip_callback((tcpip_callback_fn)netif_poll, netif);
674 #endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
675 
676  return ERR_OK;
677 }
678 
679 /**
680  * Call netif_poll() in the main loop of your application. This is to prevent
681  * reentering non-reentrant functions like tcp_input(). Packets passed to
682  * netif_loop_output() are put on a list that is passed to netif->input() by
683  * netif_poll().
684  */
685 void
686 netif_poll(struct netif *netif)
687 {
688  struct pbuf *in;
689  /* If we have a loopif, SNMP counters are adjusted for it,
690  * if not they are adjusted for 'netif'. */
691 #if LWIP_SNMP
692 #if LWIP_HAVE_LOOPIF
693  struct netif *stats_if = &loop_netif;
694 #else /* LWIP_HAVE_LOOPIF */
695  struct netif *stats_if = netif;
696 #endif /* LWIP_HAVE_LOOPIF */
697 #endif /* LWIP_SNMP */
699 
700  do {
701  /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
702  SYS_ARCH_PROTECT(lev);
703  in = netif->loop_first;
704  if (in != NULL) {
705  struct pbuf *in_end = in;
706 #if LWIP_LOOPBACK_MAX_PBUFS
707  u8_t clen = pbuf_clen(in);
708  /* adjust the number of pbufs on queue */
709  LWIP_ASSERT("netif->loop_cnt_current underflow",
710  ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
711  netif->loop_cnt_current -= clen;
712 #endif /* LWIP_LOOPBACK_MAX_PBUFS */
713  while (in_end->len != in_end->tot_len) {
714  LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
715  in_end = in_end->next;
716  }
717  /* 'in_end' now points to the last pbuf from 'in' */
718  if (in_end == netif->loop_last) {
719  /* this was the last pbuf in the list */
720  netif->loop_first = netif->loop_last = NULL;
721  } else {
722  /* pop the pbuf off the list */
723  netif->loop_first = in_end->next;
724  LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
725  }
726  /* De-queue the pbuf from its successors on the 'loop_' list. */
727  in_end->next = NULL;
728  }
729  SYS_ARCH_UNPROTECT(lev);
730 
731  if (in != NULL) {
732  LINK_STATS_INC(link.recv);
733  snmp_add_ifinoctets(stats_if, in->tot_len);
734  snmp_inc_ifinucastpkts(stats_if);
735  /* loopback packets are always IP packets! */
736  if (ip_input(in, netif) != ERR_OK) {
737  pbuf_free(in);
738  }
739  /* Don't reference the packet any more! */
740  in = NULL;
741  }
742  /* go on while there is a packet on the list */
743  } while (netif->loop_first != NULL);
744 }
745 
746 #if !LWIP_NETIF_LOOPBACK_MULTITHREADING
747 /**
748  * Calls netif_poll() for every netif on the netif_list.
749  */
750 void
751 netif_poll_all(void)
752 {
753  struct netif *netif = netif_list;
754  /* loop through netifs */
755  while (netif != NULL) {
756  netif_poll(netif);
757  /* proceed to next network interface */
758  netif = netif->next;
759  }
760 }
761 #endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
762 #endif /* ENABLE_LOOPBACK */
err_t(* netif_input_fn)(struct pbuf *p, struct netif *inp)
Definition: netif.h:109
u16_t tot_len
Definition: pbuf.h:90
struct netif * netif_list
Definition: netif.c:75
void(* netif_status_callback_fn)(struct netif *netif)
Definition: netif.h:128
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define snmp_add_ifinoctets(ni, value)
Definition: snmp.h:245
struct pbuf * next
Definition: pbuf.h:78
u16_t len
Definition: pbuf.h:93
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from) ICACHE_FLASH_ATTR
Definition: pbuf.c:930
void netif_set_gw(struct netif *netif, ip_addr_t *gw)
Definition: netif.c:389
#define snmp_inc_ifinucastpkts(ni)
Definition: snmp.h:246
struct netif * netif_default
Definition: netif.c:76
void(* tcpip_callback_fn)(void *ctx)
Definition: tcpip.h:78
#define ip_addr_set(dest, src)
Definition: ip_addr.h:164
#define U16_F
Definition: cc.h:61
#define NETIF_FLAG_UP
Definition: netif.h:69
void netif_set_link_down(struct netif *netif)
Definition: netif.c:562
#define NULL
Definition: def.h:47
#define ip_addr_debug_print(debug, ipaddr)
Definition: ip_addr.h:212
#define NETIF_FLAG_LINK_UP
Definition: netif.h:84
netif_output_fn output
Definition: netif.h:154
#define NETIF_DEBUG
Definition: opt.h:1819
#define LWIP_DBG_TRACE
Definition: debug.h:56
void netif_set_default(struct netif *netif)
Definition: netif.c:431
#define ICACHE_FLASH_ATTR
Definition: c_types.h:99
#define snmp_insert_ipaddridx_tree(ni)
Definition: snmp.h:278
#define snmp_inc_ifoutucastpkts(ni)
Definition: snmp.h:250
u8_t num
Definition: netif.h:197
#define SYS_ARCH_DECL_PROTECT(x)
Definition: cc.h:86
Definition: pbuf.h:58
void netif_init(void)
Definition: netif.c:104
#define snmp_delete_ipaddridx_tree(ni)
Definition: snmp.h:279
void netif_set_up(struct netif *netif)
Definition: netif.c:454
Definition: pbuf.h:53
#define snmp_delete_iprteidx_tree(dflt, ni)
Definition: snmp.h:281
struct netif * netif_find(char *name)
Definition: netif.c:291
#define NETIF_STATUS_CALLBACK(n)
Definition: netif.c:66
#define tcpip_callback(f, ctx)
Definition: tcpip.h:99
#define ip_addr_islinklocal(addr1)
Definition: ip_addr.h:210
ip_addr_t gw
Definition: netif.h:146
#define NETIF_FLAG_ETHARP
Definition: netif.h:88
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:94
#define snmp_dec_iflist()
Definition: snmp.h:254
#define ip_addr_cmp(addr1, addr2)
Definition: ip_addr.h:198
struct netif * netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
Definition: netif.c:137
struct netif * next
Definition: netif.h:141
#define snmp_inc_iflist()
Definition: snmp.h:253
#define ERR_OK
Definition: err.h:52
static state_t * state
Definition: aes.c:67
Definition: pbuf.h:76
u8_t flags
Definition: netif.h:193
s8_t err_t
Definition: err.h:47
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
#define LINK_STATS_INC(x)
Definition: stats.h:227
#define LWIP_DBG_STATE
Definition: debug.h:58
Definition: netif.h:139
void netif_remove(struct netif *netif)
Definition: netif.c:241
err_t(* netif_init_fn)(struct netif *netif)
Definition: netif.h:102
#define NETIF_FLAG_IGMP
Definition: netif.h:95
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
ip_addr_t ip_addr
Definition: netif.h:144
err_t tcpip_input(struct pbuf *p, struct netif *inp)
Definition: tcpip.c:156
#define ip_addr_isany(addr1)
Definition: ip_addr.h:200
#define ip_addr_set_zero(ipaddr)
Definition: ip_addr.h:168
#define LWIP_AUTOIP
Definition: opt.h:681
#define NETIF_INIT_SNMP(netif, type, speed)
Definition: netif.h:252
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
Definition: pbuf.c:685
#define SYS_ARCH_PROTECT(x)
Definition: cc.h:87
void netif_set_down(struct netif *netif)
Definition: netif.c:491
void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
Definition: netif.c:324
#define snmp_get_sysuptime(value)
Definition: snmp.h:239
void * state
Definition: netif.h:171
#define NETIF_LINK_CALLBACK(n)
Definition: netif.c:72
#define snmp_add_ifoutoctets(ni, value)
Definition: snmp.h:249
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
unsigned char u8_t
Definition: cc.h:52
#define LWIP_LOOPBACK_MAX_PBUFS
Definition: opt.h:1133
netif_input_fn input
Definition: netif.h:150
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
err_t ip_input(struct pbuf *p, struct netif *inp) ICACHE_FLASH_ATTR
Definition: ip.c:923
#define snmp_inc_ifoutdiscards(ni)
Definition: snmp.h:252
void netif_set_netmask(struct netif *netif, ip_addr_t *netmask)
Definition: netif.c:410
char name[2]
Definition: netif.h:195
void netif_set_link_up(struct netif *netif)
Definition: netif.c:523
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
ip_addr_t netmask
Definition: netif.h:145
#define netif_is_up(netif)
Definition: netif.h:286
#define snmp_insert_iprteidx_tree(dflt, ni)
Definition: snmp.h:280
#define SYS_ARCH_UNPROTECT(x)
Definition: cc.h:88
#define ERR_MEM
Definition: err.h:53
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
struct pbuf * pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) ICACHE_FLASH_ATTR
Definition: pbuf.c:234
void netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw)
Definition: netif.c:227
u8_t pbuf_clen(struct pbuf *p) ICACHE_FLASH_ATTR
Definition: pbuf.c:782
#define IP4_ADDR(ipaddr, a, b, c, d)
Definition: ip_addr.h:139