mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-03-08 19:13:47 +00:00
Checked in slightly modified version of patch # 6370: Moved loopif code to netif.c so that loopback traffic is supported on all netifs (all local IPs).
This commit is contained in:
parent
24e0b25215
commit
88ff8c83e9
@ -53,6 +53,11 @@ HISTORY
|
|||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
|
|
||||||
|
2008-03-10 Simon Goldschmidt (patch by Luca Ceresoli)
|
||||||
|
* netif.c, loopif.c, ip.c, netif.h, loopif.h, opt.h: Checked in slightly
|
||||||
|
modified version of patch # 6370: Moved loopif code to netif.c so that
|
||||||
|
loopback traffic is supported on all netifs (all local IPs).
|
||||||
|
|
||||||
2008-03-10 Jonathan Larmour
|
2008-03-10 Jonathan Larmour
|
||||||
* inet_chksum.c: Allow choice of one of the sample algorithms to be
|
* inet_chksum.c: Allow choice of one of the sample algorithms to be
|
||||||
made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM.
|
made from lwipopts.h. Fix comment on how to override LWIP_CHKSUM.
|
||||||
|
@ -531,9 +531,19 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
|||||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
||||||
ip_debug_print(p);
|
ip_debug_print(p);
|
||||||
|
|
||||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
#if (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) && !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
if (ip_addr_cmp(dest, &netif->ip_addr)) {
|
||||||
|
/* Packet to self, enqueue it for loopback */
|
||||||
|
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
|
||||||
|
|
||||||
return netif->output(netif, p, dest);
|
return netif_loop_output(netif, p, dest);
|
||||||
|
} else
|
||||||
|
#endif /* (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF) && !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
{
|
||||||
|
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||||
|
|
||||||
|
return netif->output(netif, p, dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
142
src/core/netif.c
142
src/core/netif.c
@ -45,6 +45,9 @@
|
|||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
#include "lwip/igmp.h"
|
#include "lwip/igmp.h"
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
|
#if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
|
||||||
#if LWIP_NETIF_STATUS_CALLBACK
|
#if LWIP_NETIF_STATUS_CALLBACK
|
||||||
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
|
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
|
||||||
@ -106,6 +109,10 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
|||||||
#if LWIP_IGMP
|
#if LWIP_IGMP
|
||||||
netif->igmp_mac_filter = NULL;
|
netif->igmp_mac_filter = NULL;
|
||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
#if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
netif->loop_first = NULL;
|
||||||
|
netif->loop_last = NULL;
|
||||||
|
#endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
|
||||||
/* remember netif specific state information data */
|
/* remember netif specific state information data */
|
||||||
netif->state = state;
|
netif->state = state;
|
||||||
@ -497,3 +504,138 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct
|
|||||||
netif->link_callback = link_callback;
|
netif->link_callback = link_callback;
|
||||||
}
|
}
|
||||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
||||||
|
|
||||||
|
#if ENABLE_LOOPBACK
|
||||||
|
/**
|
||||||
|
* Send an IP packet to be received on the same netif (loopif-like).
|
||||||
|
* The pbuf is simply copied and handed back to netif->input.
|
||||||
|
* In multithreaded mode, this is done directly since netif->input must put
|
||||||
|
* the packet on a queue.
|
||||||
|
* In callback mode, the packet is put on an internal queue and is fed to
|
||||||
|
* netif->input by netif_poll().
|
||||||
|
*
|
||||||
|
* @param netif the lwip network interface structure
|
||||||
|
* @param p the (IP) packet to 'send'
|
||||||
|
* @param ipaddr the ip address to send the packet to (not used)
|
||||||
|
* @return ERR_OK if the packet has been sent
|
||||||
|
* ERR_MEM if the pbuf used to copy the packet couldn't be allocated
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
netif_loop_output(struct netif *netif, struct pbuf *p,
|
||||||
|
struct ip_addr *ipaddr)
|
||||||
|
{
|
||||||
|
struct pbuf *r;
|
||||||
|
err_t err;
|
||||||
|
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
struct pbuf *last;
|
||||||
|
SYS_ARCH_DECL_PROTECT(lev);
|
||||||
|
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
LWIP_UNUSED_ARG(ipaddr);
|
||||||
|
|
||||||
|
/* Allocate a new pbuf */
|
||||||
|
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
|
||||||
|
if (r == NULL) {
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the whole pbuf queue p into the single pbuf r */
|
||||||
|
if ((err = pbuf_copy(r, p)) != ERR_OK) {
|
||||||
|
pbuf_free(r);
|
||||||
|
r = NULL;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
/* Multithreading environment, netif->input() is supposed to put the packet
|
||||||
|
into a mailbox, so we can safely call it here without risking to re-enter
|
||||||
|
functions that are not reentrant (TCP!!!) */
|
||||||
|
LWIP_ASSERT(netif->input != ip_input, "Don't use ip_input as netif->input with LWIP_NETIF_LOOPBACK_MULTITHREADING = 1!");
|
||||||
|
if(netif->input(r, netif) != ERR_OK) {
|
||||||
|
pbuf_free(r);
|
||||||
|
r = NULL;
|
||||||
|
}
|
||||||
|
#else /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
/* Raw API without threads: put the packet on a linked list which gets emptied
|
||||||
|
through calling netif_poll(). */
|
||||||
|
|
||||||
|
/* let last point to the last pbuf in chain r */
|
||||||
|
for (last = r; last->next != NULL; last = last->next);
|
||||||
|
SYS_ARCH_PROTECT(lev);
|
||||||
|
if(netif->loop_first != NULL) {
|
||||||
|
LWIP_ASSERT("if first != NULL, last must also be != NULL", netif->loop_last != NULL);
|
||||||
|
netif->loop_last->next = r;
|
||||||
|
netif->loop_last = last;
|
||||||
|
} else {
|
||||||
|
netif->loop_first = r;
|
||||||
|
netif->loop_last = last;
|
||||||
|
}
|
||||||
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
|
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
/**
|
||||||
|
* Calls netif_poll() for every netif on the netif_list.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
netif_poll_all(void)
|
||||||
|
{
|
||||||
|
struct netif *netif = netif_list;
|
||||||
|
/* loop through netifs */
|
||||||
|
while (netif != NULL) {
|
||||||
|
netif_poll(netif);
|
||||||
|
/* proceed to next network interface */
|
||||||
|
netif = netif->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call netif_poll() in the main loop of your application. This is to prevent
|
||||||
|
* reentering non-reentrant functions like tcp_input(). Packets passed to
|
||||||
|
* netif_loop_output() are put on a list that is passed to netif->input() by
|
||||||
|
* netif_poll().
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
netif_poll(struct netif *netif)
|
||||||
|
{
|
||||||
|
struct pbuf *in;
|
||||||
|
SYS_ARCH_DECL_PROTECT(lev);
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||||
|
SYS_ARCH_PROTECT(lev);
|
||||||
|
in = netif->loop_first;
|
||||||
|
if(in != NULL) {
|
||||||
|
struct pbuf *in_end = in;
|
||||||
|
while(in_end->len != in_end->tot_len) {
|
||||||
|
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||||
|
in_end = in_end->next;
|
||||||
|
}
|
||||||
|
/* 'in_end' now points to the last pbuf from 'in' */
|
||||||
|
if(in_end == netif->loop_last) {
|
||||||
|
/* this was the last pbuf in the list */
|
||||||
|
netif->loop_first = netif->loop_last = NULL;
|
||||||
|
} else {
|
||||||
|
/* pop the pbuf off the list */
|
||||||
|
netif->loop_first = in_end->next;
|
||||||
|
LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
|
||||||
|
}
|
||||||
|
/* De-queue the pbuf from its successors on the 'loop_' list. */
|
||||||
|
in_end->next = NULL;
|
||||||
|
}
|
||||||
|
SYS_ARCH_UNPROTECT(lev);
|
||||||
|
|
||||||
|
if(in != NULL) {
|
||||||
|
if(netif->input(in, netif) != ERR_OK) {
|
||||||
|
pbuf_free(in);
|
||||||
|
}
|
||||||
|
/* Don't reference the packet any more! */
|
||||||
|
in = NULL;
|
||||||
|
}
|
||||||
|
/* go on while there is a packet on the list */
|
||||||
|
} while(netif->loop_first != NULL);
|
||||||
|
}
|
||||||
|
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
#endif /* ENABLE_LOOPBACK */
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
#include "lwip/opt.h"
|
#include "lwip/opt.h"
|
||||||
|
|
||||||
|
#define ENABLE_LOOPBACK (LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF)
|
||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
|
|
||||||
#include "lwip/ip_addr.h"
|
#include "lwip/ip_addr.h"
|
||||||
@ -165,6 +167,11 @@ struct netif {
|
|||||||
#if LWIP_NETIF_HWADDRHINT
|
#if LWIP_NETIF_HWADDRHINT
|
||||||
u8_t *addr_hint;
|
u8_t *addr_hint;
|
||||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||||
|
#if ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
/* List of packets to be queued for ourselves. */
|
||||||
|
struct pbuf *loop_first;
|
||||||
|
struct pbuf *loop_last;
|
||||||
|
#endif /* ENABLE_LOOPBACK && !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
};
|
};
|
||||||
|
|
||||||
#if LWIP_SNMP
|
#if LWIP_SNMP
|
||||||
@ -242,4 +249,12 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_LOOPBACK
|
||||||
|
err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
|
||||||
|
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
void netif_poll_all(void);
|
||||||
|
void netif_poll(struct netif *netif);
|
||||||
|
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||||
|
#endif /* ENABLE_LOOPBACK */
|
||||||
|
|
||||||
#endif /* __LWIP_NETIF_H__ */
|
#endif /* __LWIP_NETIF_H__ */
|
||||||
|
@ -832,6 +832,31 @@
|
|||||||
#define LWIP_NETIF_HWADDRHINT 0
|
#define LWIP_NETIF_HWADDRHINT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_NETIF_LOOPBACK==1: Support sending packets with a destination IP
|
||||||
|
* address equal to the netif IP address, looping them back up the stack.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_NETIF_LOOPBACK
|
||||||
|
#define LWIP_NETIF_LOOPBACK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LWIP_NETIF_LOOPBACK_MULTITHREADING: Indicates whether threading is enabled in
|
||||||
|
* the system, as netifs must change how they behave depending on this setting
|
||||||
|
* for the LWIP_NETIF_LOOPBACK option to work.
|
||||||
|
* Setting this is needed to avoid reentering non-reentrant functions like
|
||||||
|
* tcp_input().
|
||||||
|
* LWIP_NETIF_LOOPBACK_MULTITHREADING==1: Indicates that the user is using a
|
||||||
|
* multithreaded environment like tcpip.c. In this case, netif->input()
|
||||||
|
* is called directly.
|
||||||
|
* LWIP_NETIF_LOOPBACK_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
|
||||||
|
* The packets are put on a list and netif_poll() must be called in
|
||||||
|
* the main application loop.
|
||||||
|
*/
|
||||||
|
#ifndef LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
|
#define LWIP_NETIF_LOOPBACK_MULTITHREADING (!NO_SYS)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------
|
------------------------------------
|
||||||
---------- LOOPIF options ----------
|
---------- LOOPIF options ----------
|
||||||
@ -844,22 +869,6 @@
|
|||||||
#define LWIP_HAVE_LOOPIF 0
|
#define LWIP_HAVE_LOOPIF 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* LWIP_LOOPIF_MULTITHREADING: Indicates whether threading is enabled in
|
|
||||||
* the system, as LOOPIF must change how it behaves depending on this setting.
|
|
||||||
* Setting this is needed to avoid reentering non-reentrant functions like
|
|
||||||
* tcp_input().
|
|
||||||
* LWIP_LOOPIF_MULTITHREADING==1: Indicates that the user is using a
|
|
||||||
* multithreaded environment like tcpip.c. In this case, netif->input()
|
|
||||||
* is called directly.
|
|
||||||
* LWIP_LOOPIF_MULTITHREADING==0: Indicates a polling (or NO_SYS) setup.
|
|
||||||
* The packets are put on a list and loopif_poll() must be called in
|
|
||||||
* the main application loop.
|
|
||||||
*/
|
|
||||||
#ifndef LWIP_LOOPIF_MULTITHREADING
|
|
||||||
#define LWIP_LOOPIF_MULTITHREADING 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
------------------------------------
|
------------------------------------
|
||||||
---------- Thread options ----------
|
---------- Thread options ----------
|
||||||
|
@ -39,8 +39,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !LWIP_LOOPIF_MULTITHREADING
|
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||||
void loopif_poll(struct netif *netif);
|
#define loopif_poll(netif) netif_poll()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
err_t loopif_init(struct netif *netif);
|
err_t loopif_init(struct netif *netif);
|
||||||
|
@ -40,149 +40,8 @@
|
|||||||
#if LWIP_HAVE_LOOPIF
|
#if LWIP_HAVE_LOOPIF
|
||||||
|
|
||||||
#include "netif/loopif.h"
|
#include "netif/loopif.h"
|
||||||
#include "lwip/pbuf.h"
|
|
||||||
#include "lwip/snmp.h"
|
#include "lwip/snmp.h"
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if !LWIP_LOOPIF_MULTITHREADING
|
|
||||||
|
|
||||||
#include "lwip/sys.h"
|
|
||||||
#include "lwip/mem.h"
|
|
||||||
|
|
||||||
/* helper struct for the linked list of pbufs */
|
|
||||||
struct loopif_private {
|
|
||||||
struct pbuf *first;
|
|
||||||
struct pbuf *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call loopif_poll() in the main loop of your application. This is to prevent
|
|
||||||
* reentering non-reentrant functions like tcp_input(). Packets passed to
|
|
||||||
* loopif_output() are put on a list that is passed to netif->input() by
|
|
||||||
* loopif_poll().
|
|
||||||
*
|
|
||||||
* @param netif the lwip network interface structure for this loopif
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
loopif_poll(struct netif *netif)
|
|
||||||
{
|
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
|
||||||
struct pbuf *in, *in_end;
|
|
||||||
struct loopif_private *priv = (struct loopif_private*)netif->state;
|
|
||||||
|
|
||||||
LWIP_ERROR("priv != NULL", (priv != NULL), return;);
|
|
||||||
|
|
||||||
do {
|
|
||||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
|
||||||
SYS_ARCH_PROTECT(lev);
|
|
||||||
in = priv->first;
|
|
||||||
if(in) {
|
|
||||||
in_end = in;
|
|
||||||
while(in_end->len != in_end->tot_len) {
|
|
||||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
|
||||||
in_end = in_end->next;
|
|
||||||
}
|
|
||||||
/* 'in_end' now points to the last pbuf from 'in' */
|
|
||||||
if(in_end == priv->last) {
|
|
||||||
/* this was the last pbuf in the list */
|
|
||||||
priv->first = priv->last = NULL;
|
|
||||||
} else {
|
|
||||||
/* pop the pbuf off the list */
|
|
||||||
priv->first = in_end->next;
|
|
||||||
LWIP_ASSERT("should not be null since first != last!", priv->first != NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
|
||||||
|
|
||||||
if(in != NULL) {
|
|
||||||
if(in_end->next != NULL) {
|
|
||||||
/* De-queue the pbuf from its successors on the 'priv' list. */
|
|
||||||
in_end->next = NULL;
|
|
||||||
}
|
|
||||||
if(netif->input(in, netif) != ERR_OK) {
|
|
||||||
pbuf_free(in);
|
|
||||||
}
|
|
||||||
/* Don't reference the packet any more! */
|
|
||||||
in = NULL;
|
|
||||||
in_end = NULL;
|
|
||||||
}
|
|
||||||
/* go on while there is a packet on the list */
|
|
||||||
} while(priv->first != NULL);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an IP packet over the loopback interface.
|
|
||||||
* The pbuf is simply copied and handed back to netif->input.
|
|
||||||
* In multithreaded mode, this is done directly since netif->input must put
|
|
||||||
* the packet on a queue.
|
|
||||||
* In callback mode, the packet is put on an internal queue and is fed to
|
|
||||||
* netif->input by loopif_poll().
|
|
||||||
*
|
|
||||||
* @param netif the lwip network interface structure for this loopif
|
|
||||||
* @param p the (IP) packet to 'send'
|
|
||||||
* @param ipaddr the ip address to send the packet to (not used for loopif)
|
|
||||||
* @return ERR_OK if the packet has been sent
|
|
||||||
* ERR_MEM if the pbuf used to copy the packet couldn't be allocated
|
|
||||||
*/
|
|
||||||
static err_t
|
|
||||||
loopif_output(struct netif *netif, struct pbuf *p,
|
|
||||||
struct ip_addr *ipaddr)
|
|
||||||
{
|
|
||||||
#if !LWIP_LOOPIF_MULTITHREADING
|
|
||||||
SYS_ARCH_DECL_PROTECT(lev);
|
|
||||||
struct loopif_private *priv;
|
|
||||||
struct pbuf *last;
|
|
||||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
|
||||||
struct pbuf *r;
|
|
||||||
err_t err;
|
|
||||||
|
|
||||||
LWIP_UNUSED_ARG(ipaddr);
|
|
||||||
|
|
||||||
/* Allocate a new pbuf */
|
|
||||||
r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
|
||||||
if (r == NULL) {
|
|
||||||
return ERR_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the whole pbuf queue p into the single pbuf r */
|
|
||||||
if ((err = pbuf_copy(r, p)) != ERR_OK) {
|
|
||||||
pbuf_free(r);
|
|
||||||
r = NULL;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LWIP_LOOPIF_MULTITHREADING
|
|
||||||
/* Multithreading environment, netif->input() is supposed to put the packet
|
|
||||||
into a mailbox, so we can safely call it here without risking to re-enter
|
|
||||||
functions that are not reentrant (TCP!!!) */
|
|
||||||
if(netif->input(r, netif) != ERR_OK) {
|
|
||||||
pbuf_free(r);
|
|
||||||
r = NULL;
|
|
||||||
}
|
|
||||||
#else /* LWIP_LOOPIF_MULTITHREADING */
|
|
||||||
/* Raw API without threads: put the packet on a linked list which gets emptied
|
|
||||||
through calling loopif_poll(). */
|
|
||||||
priv = (struct loopif_private*)netif->state;
|
|
||||||
|
|
||||||
/* let last point to the last pbuf in chain r */
|
|
||||||
for (last = r; last->next != NULL; last = last->next);
|
|
||||||
SYS_ARCH_PROTECT(lev);
|
|
||||||
if(priv->first != NULL) {
|
|
||||||
LWIP_ASSERT("if first != NULL, last must also be != NULL", priv->last != NULL);
|
|
||||||
priv->last->next = r;
|
|
||||||
priv->last = last;
|
|
||||||
} else {
|
|
||||||
priv->first = r;
|
|
||||||
priv->last = last;
|
|
||||||
}
|
|
||||||
SYS_ARCH_UNPROTECT(lev);
|
|
||||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
|
||||||
|
|
||||||
return ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a lwip network interface structure for a loopback interface
|
* Initialize a lwip network interface structure for a loopback interface
|
||||||
*
|
*
|
||||||
@ -193,16 +52,6 @@ loopif_output(struct netif *netif, struct pbuf *p,
|
|||||||
err_t
|
err_t
|
||||||
loopif_init(struct netif *netif)
|
loopif_init(struct netif *netif)
|
||||||
{
|
{
|
||||||
#if !LWIP_LOOPIF_MULTITHREADING
|
|
||||||
struct loopif_private *priv;
|
|
||||||
|
|
||||||
priv = (struct loopif_private*)mem_malloc(sizeof(struct loopif_private));
|
|
||||||
if(priv == NULL)
|
|
||||||
return ERR_MEM;
|
|
||||||
priv->first = priv->last = NULL;
|
|
||||||
netif->state = priv;
|
|
||||||
#endif /* LWIP_LOOPIF_MULTITHREADING */
|
|
||||||
|
|
||||||
/* initialize the snmp variables and counters inside the struct netif
|
/* initialize the snmp variables and counters inside the struct netif
|
||||||
* ifSpeed: no assumption can be made!
|
* ifSpeed: no assumption can be made!
|
||||||
*/
|
*/
|
||||||
@ -210,7 +59,7 @@ loopif_init(struct netif *netif)
|
|||||||
|
|
||||||
netif->name[0] = 'l';
|
netif->name[0] = 'l';
|
||||||
netif->name[1] = 'o';
|
netif->name[1] = 'o';
|
||||||
netif->output = loopif_output;
|
netif->output = netif_loop_output;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user