Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Documentation/components/net/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Network Support
tcp_network_perf.rst
delay_act_and_tcp_perf.rst
tcp_state_machine.rst
lwip.rst

``net`` Directory Structure ::

Expand Down
51 changes: 51 additions & 0 deletions Documentation/components/net/lwip.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
====================
Auxiliary lwIP Stack
====================

Overview
========

``CONFIG_NET_LWIP`` builds lwIP 2.0.3 as an auxiliary TCP/IP stack alongside
the native NuttX network stack. It does not replace NuttX socket routing.
Applications select lwIP explicitly through its prefixed API, such as
``lwip_socket()``, ``lwip_connect()``, and ``lwip_send()``.

The initial integration supports the simulator Ethernet driver. Both stacks
share the same simulated Ethernet device through an L2 tap. The lwIP
interface therefore uses ``10.0.1.3`` by default while the native NuttX
interface uses ``10.0.1.2``.

Configuration
=============

Use the simulator configuration as a starting point::

./tools/configure.sh sim:lwip
make

The main options are under ``Networking Support -> lwIP Auxiliary Stack``.
DHCP is disabled by default because the native and auxiliary stacks share one
link. The static address, network mask, and gateway are derived from the
``CONFIG_NETINIT_*`` values.

Initialization
==============

Call ``nuttx_lwip_initialize()`` once from a long-lived initialization
context before using the lwIP API. The call is idempotent and creates the
lwIP TCP/IP and receive threads. In a protected or kernel build, place the
call in an equivalent persistent system service.

The lifetime requirement is important on NuttX: initializing from a
short-lived application associates the worker threads with that
application's task group, so they are reclaimed when the application exits.

Simulator Network
=================

The simulator must have a TAP interface whose host address is
``10.0.1.1/24``. Once the interface and a host receiver are ready, UDP and
TCP traffic can be sent from lwIP applications to the host. A continuous
test should run UDP, TCP, and throughput cases in the same NSH session; this
also verifies that the lwIP worker threads remain alive between application
invocations.
17 changes: 17 additions & 0 deletions arch/sim/src/sim/sim_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,23 @@ int sim_netdriver_init(void);
void sim_netdriver_setmacaddr(int devidx, unsigned char *macaddr);
void sim_netdriver_setmtu(int devidx, int mtu);

#ifdef CONFIG_NET_LWIP
typedef void (*sim_netdriver_l2rx_cb_t)(void *arg,
const uint8_t *buf,
unsigned int len);

int sim_netdriver_l2tap_register(int devidx,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not reuse sim_tapdev_xxx

sim_netdriver_l2rx_cb_t callback,
void *arg);
int sim_netdriver_l2tap_unregister(int devidx,
sim_netdriver_l2rx_cb_t callback,
void *arg);
int sim_netdriver_l2tap_xmit(int devidx, const uint8_t *buf,
unsigned int len);
int sim_netdriver_l2tap_getmac(int devidx, uint8_t *mac);
int sim_netdriver_ifname_to_devidx(const char *ifname);
#endif

/* sim_rptun.c **************************************************************/

#ifdef CONFIG_RPTUN
Expand Down
110 changes: 107 additions & 3 deletions arch/sim/src/sim/sim_netdriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <nuttx/config.h>

#include <nuttx/debug.h>
#include <stdlib.h>
#include <string.h>

#include <nuttx/compiler.h>
Expand Down Expand Up @@ -133,6 +134,17 @@ static int netdriver_rmmac(struct netdev_lowerhalf_s *dev,
/* Ethernet peripheral state */

static struct sim_netdev_s g_sim_dev[CONFIG_SIM_NETDEV_NUMBER];

#ifdef CONFIG_NET_LWIP
struct sim_l2tap_s
{
sim_netdriver_l2rx_cb_t callback;
void *arg;
};

static struct sim_l2tap_s g_l2tap[CONFIG_SIM_NETDEV_NUMBER];
#endif

static const struct netdev_ops_s g_ops =
{
netdriver_ifup, /* ifup */
Expand Down Expand Up @@ -174,6 +186,8 @@ static netpkt_t *netdriver_recv(struct netdev_lowerhalf_s *dev)

if (sim_netdev_avail(DEVIDX(dev)))
{
FAR uint8_t *rxbuf;

pkt = netpkt_alloc(dev, NETPKT_RX);
if (pkt == NULL)
{
Expand All @@ -185,17 +199,26 @@ static netpkt_t *netdriver_recv(struct netdev_lowerhalf_s *dev)
*/

#ifdef SIM_NETDEV_RECV_OFFLOAD
len = sim_netdev_read(DEVIDX(dev), netpkt_getdata(dev, pkt),
SIM_NETDEV_BUFSIZE);
rxbuf = netpkt_getdata(dev, pkt);
len = sim_netdev_read(DEVIDX(dev), rxbuf, SIM_NETDEV_BUFSIZE);
#else
len = sim_netdev_read(DEVIDX(dev), DEVBUF(dev), SIM_NETDEV_BUFSIZE);
rxbuf = DEVBUF(dev);
len = sim_netdev_read(DEVIDX(dev), rxbuf, SIM_NETDEV_BUFSIZE);
#endif
if (len == 0)
{
netpkt_free(dev, pkt, NETPKT_RX);
return NULL;
}

#ifdef CONFIG_NET_LWIP
if (g_l2tap[DEVIDX(dev)].callback != NULL)
{
g_l2tap[DEVIDX(dev)].callback(g_l2tap[DEVIDX(dev)].arg,
rxbuf, len);
}
#endif

#ifdef SIM_NETDEV_RECV_OFFLOAD
netpkt_setdatalen(dev, pkt, len);
#else
Expand Down Expand Up @@ -259,12 +282,14 @@ static int netdriver_rmmac(struct netdev_lowerhalf_s *dev,
static void netdriver_txdone_interrupt(void *priv)
{
struct netdev_lowerhalf_s *dev = (struct netdev_lowerhalf_s *)priv;

netdev_lower_txdone(dev);
}

static void netdriver_rxready_interrupt(void *priv)
{
struct netdev_lowerhalf_s *dev = (struct netdev_lowerhalf_s *)priv;

netdev_lower_rxready(dev);
}

Expand Down Expand Up @@ -353,6 +378,7 @@ void sim_netdriver_setmtu(int devidx, int mtu)
void sim_netdriver_loop(void)
{
int devidx;

for (devidx = 0; devidx < CONFIG_SIM_NETDEV_NUMBER; devidx++)
{
if (sim_netdev_avail(devidx))
Expand All @@ -361,3 +387,81 @@ void sim_netdriver_loop(void)
}
}
}

#ifdef CONFIG_NET_LWIP
int sim_netdriver_l2tap_register(int devidx,
sim_netdriver_l2rx_cb_t callback,
void *arg)
{
if (devidx < 0 || devidx >= CONFIG_SIM_NETDEV_NUMBER || callback == NULL)
{
return -EINVAL;
}

g_l2tap[devidx].callback = callback;
g_l2tap[devidx].arg = arg;
return OK;
}

int sim_netdriver_l2tap_unregister(int devidx,
sim_netdriver_l2rx_cb_t callback,
void *arg)
{
if (devidx < 0 || devidx >= CONFIG_SIM_NETDEV_NUMBER)
{
return -EINVAL;
}

if (g_l2tap[devidx].callback == callback && g_l2tap[devidx].arg == arg)
{
g_l2tap[devidx].callback = NULL;
g_l2tap[devidx].arg = NULL;
}

return OK;
}

int sim_netdriver_l2tap_xmit(int devidx, const uint8_t *buf,
unsigned int len)
{
if (devidx < 0 || devidx >= CONFIG_SIM_NETDEV_NUMBER ||
buf == NULL || len == 0)
{
return -EINVAL;
}

sim_netdev_send(devidx, (unsigned char *)buf, len);
return OK;
}

int sim_netdriver_l2tap_getmac(int devidx, uint8_t *mac)
{
if (devidx < 0 || devidx >= CONFIG_SIM_NETDEV_NUMBER || mac == NULL)
{
return -EINVAL;
}

memcpy(mac, IDXDEV(devidx)->netdev.d_mac.ether.ether_addr_octet,
IFHWADDRLEN);
return OK;
}

int sim_netdriver_ifname_to_devidx(const char *ifname)
{
char *endptr;
long devidx;

if (ifname == NULL || strncmp(ifname, "eth", 3) != 0)
{
return -ENODEV;
}

devidx = strtol(ifname + 3, &endptr, 10);
if (*endptr != '\0' || devidx < 0 || devidx >= CONFIG_SIM_NETDEV_NUMBER)
{
return -ENODEV;
}

return (int)devidx;
}
#endif
78 changes: 78 additions & 0 deletions boards/sim/sim/sim/configs/lwip/defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
CONFIG_ALLOW_BSD_COMPONENTS=y
CONFIG_ARCH="sim"
CONFIG_ARCH_BOARD="sim"
CONFIG_ARCH_BOARD_SIM=y
CONFIG_ARCH_CHIP="sim"
CONFIG_ARCH_SIM=y
CONFIG_BOARDCTL_POWEROFF=y
CONFIG_BUILTIN=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_NET=y
CONFIG_DEBUG_NET_ERROR=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEV_LOOP=y
CONFIG_DRIVERS_VIDEO=y
CONFIG_FS_BINFS=y
CONFIG_FS_HOSTFS=y
CONFIG_FS_PROCFS=y
CONFIG_FS_TMPFS=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_IOB_NBUFFERS=1024
CONFIG_IOB_NCHAINS=128
CONFIG_IOB_NOTIFIER=y
CONFIG_IOB_THROTTLE=16
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBC_FLOATINGPOINT=y
CONFIG_LIBC_LOCALE=y
CONFIG_LIBC_LOCALTIME=y
CONFIG_LIBC_MAX_EXITFUNS=1
CONFIG_LIBM=y
CONFIG_MM_REGIONS=2
CONFIG_MQ_MAXMSGSIZE=64
CONFIG_NET=y
CONFIG_NETDEV_LATEINIT=y
CONFIG_NETDEV_PHY_IOCTL=y
CONFIG_NETDEV_STATISTICS=y
CONFIG_NETINIT_DRIPADDR=0x0a000101
CONFIG_NETINIT_IPADDR=0x0a000102
CONFIG_NET_BINDTODEVICE=y
CONFIG_NET_IPv6=y
CONFIG_NET_LOOPBACK=y
CONFIG_NET_LWIP=y
CONFIG_NET_PKT=y
CONFIG_NET_PKT_PREALLOC_CONNS=2
CONFIG_NET_STATISTICS=y
CONFIG_NET_TCP_NO_STACK=y
CONFIG_NET_UDP_NO_STACK=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILE_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_PREALLOC_TIMERS=4
CONFIG_PSEUDOFS_SOFTLINKS=y
CONFIG_PSEUDOTERM=y
CONFIG_PTHREAD_MUTEX_TYPES=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_READLINE_TABCOMPLETION=y
CONFIG_SCHED_CHILD_STATUS=y
CONFIG_SCHED_HAVE_PARENT=y
CONFIG_SERIAL_TERMIOS=y
CONFIG_SIG_DEFAULT=y
CONFIG_SIG_EVTHREAD=y
CONFIG_SIM_NETDEV=y
CONFIG_STACK_COLORATION=y
CONFIG_SYSLOG_BUFFER=y
CONFIG_SYSLOG_CONSOLE=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_SYSTEM=y
CONFIG_SYSTEM_TIME64=y
CONFIG_TASK_NAME_SIZE=32
CONFIG_TLS_NCLEANUP=2
CONFIG_TTY_SIGINT=y
CONFIG_TTY_SIGINT_CHAR=0x3
CONFIG_TTY_SIGTSTP=y
1 change: 1 addition & 0 deletions net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ source "net/arp/Kconfig"
source "net/procfs/Kconfig"
source "net/usrsock/Kconfig"
source "net/utils/Kconfig"
source "net/lwip/Kconfig"

config NET_STATISTICS
bool "Collect network statistics"
Expand Down
1 change: 1 addition & 0 deletions net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ include route/Make.defs
include procfs/Make.defs
include usrsock/Make.defs
include utils/Make.defs
include lwip/Make.defs
endif

CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)net
Expand Down
25 changes: 25 additions & 0 deletions net/lwip/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
if(CONFIG_NET_LWIP)
set(LWIP_BASE ${CMAKE_CURRENT_LIST_DIR}/lwip-2.0.3/src)

file(GLOB LWIP_CORE_SRCS
${LWIP_BASE}/core/*.c
${LWIP_BASE}/core/ipv4/*.c
${LWIP_BASE}/api/*.c
${LWIP_BASE}/netif/*.c)

if(CONFIG_NET_LWIP_IPV6)
file(GLOB LWIP_IPV6_SRCS ${LWIP_BASE}/core/ipv6/*.c)
list(APPEND LWIP_CORE_SRCS ${LWIP_IPV6_SRCS})
endif()

target_sources(net PRIVATE
${LWIP_CORE_SRCS}
${CMAKE_CURRENT_LIST_DIR}/lwip_init.c
${CMAKE_CURRENT_LIST_DIR}/sys_arch_nuttx.c
${CMAKE_CURRENT_LIST_DIR}/ethernetif_nuttx.c
$<$<AND:$<BOOL:${CONFIG_ARCH_BOARD_SIM}>,$<BOOL:${CONFIG_NET_PKT}>>:${CMAKE_CURRENT_LIST_DIR}/lwip_pktif_sim.c>)

target_include_directories(net PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/lwip-2.0.3/src/include)
endif()
Loading
Loading