commit 0d1a19767c8e4f2d7ea81a0664a32023f9ae79d2 Author: Renzo Davoli Date: Mon Jan 2 12:21:44 2023 +0100 contrib/ports/unix: add vdeif diff --git a/contrib/ports/unix/linuxlib/CMakeLists.txt b/contrib/ports/unix/linuxlib/CMakeLists.txt index f283b068..d4152965 100644 --- a/contrib/ports/unix/linuxlib/CMakeLists.txt +++ b/contrib/ports/unix/linuxlib/CMakeLists.txt @@ -16,6 +16,14 @@ endif() set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../..) +find_library(LIB_VDEPLUGOK vdeplug) +check_include_file(libvdeplug.h INCLUDE_VDEPLUGOK) +if (LIB_VDEPLUGOK AND INCLUDE_VDEPLUGOK) + message(STATUS "Found libvdeplug: vde support added") +else() + message(STATUS "Libvdeplug needs to be installed to add vde support") +endif() + include(${LWIP_DIR}/contrib/ports/CMakeCommon.cmake) set (LWIP_DEFINITIONS -DLWIP_DEBUG) @@ -31,11 +39,20 @@ include(${LWIP_CONTRIB_DIR}/ports/unix/Filelists.cmake) include(${LWIP_DIR}/src/Filelists.cmake) list(REMOVE_ITEM lwipnoapps_SRCS ${LWIP_DIR}/src/netif/slipif.c) +if (LIB_VDEPLUGOK AND INCLUDE_VDEPLUGOK) +set(lwipnoapps_SRCS ${lwipnoapps_SRCS} + ${LWIP_DIR}/contrib/ports/unix/port/netif/vdeif.c) +endif() + add_library(lwip ${lwipnoapps_SRCS} ${lwipcontribportunix_SRCS} ${lwipcontribportunixnetifs_SRCS}) target_compile_options(lwip PRIVATE ${LWIP_COMPILER_FLAGS}) target_compile_definitions(lwip PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS}) target_include_directories(lwip PRIVATE ${LWIP_INCLUDE_DIRS} ${LWIP_MBEDTLS_INCLUDE_DIRS}) -target_link_libraries(lwip ${LWIP_SANITIZER_LIBS}) +if (LIB_VDEPLUGOK AND INCLUDE_VDEPLUGOK) + target_link_libraries(lwip ${LWIP_SANITIZER_LIBS} vdeplug) +else() + target_link_libraries(lwip ${LWIP_SANITIZER_LIBS}) +endif() find_library(LIBPTHREAD pthread) target_link_libraries(lwip ${LIBPTHREAD}) diff --git a/contrib/ports/unix/port/include/netif/vdeif.h b/contrib/ports/unix/port/include/netif/vdeif.h new file mode 100644 index 00000000..01df2d14 --- /dev/null +++ b/contrib/ports/unix/port/include/netif/vdeif.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ +#ifndef LWIP_VDEIF_H +#define LWIP_VDEIF_H + +#include "lwip/netif.h" + +err_t vdeif_init(struct netif *netif); +void vdeif_poll(struct netif *netif); +#if NO_SYS +int vdeif_select(struct netif *netif); +#endif /* NO_SYS */ + +#endif /* LWIP_VDEIF_H */ diff --git a/contrib/ports/unix/port/netif/vdeif.c b/contrib/ports/unix/port/netif/vdeif.c new file mode 100644 index 00000000..9b6b50e9 --- /dev/null +++ b/contrib/ports/unix/port/netif/vdeif.c @@ -0,0 +1,344 @@ +/* + * VDE (virtual distributed ethernet) interface for ale4net + * (based on tapif interface Adam Dunkels ) + * 2005,2010,2011,2023 Renzo Davoli University of Bologna - Italy + */ + +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lwip/opt.h" + +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/ip.h" +#include "lwip/mem.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/timeouts.h" +#include "netif/etharp.h" +#include "lwip/ethip6.h" +#include + +#include "netif/vdeif.h" + +/* Define those to better describe your network interface. */ +#define IFNAME0 'v' +#define IFNAME1 'd' + +#ifndef VDEIF_DEBUG +#define VDEIF_DEBUG LWIP_DBG_OFF +#endif + +static char vdedescr[] = "lwip"; + +struct vdeif { + VDECONN *vdeconn; +}; + +/* Forward declarations. */ +static void vdeif_input(struct netif *netif); +#if !NO_SYS +static void vdeif_thread(void *arg); +#endif /* !NO_SYS */ + +/*-----------------------------------------------------------------------------------*/ +static void +low_level_init(struct netif *netif, char *vderl) +{ + struct vdeif *vdeif; + int randaddr; + struct timeval now; + + vdeif = (struct vdeif *)netif->state; + gettimeofday(&now, NULL); + srand(now.tv_sec + now.tv_usec); + randaddr = rand(); + + /* Obtain MAC address from network interface. */ + + /* (We just fake an address...) */ + netif->hwaddr[0] = 0x02; + netif->hwaddr[1] = 0x2; + netif->hwaddr[2] = randaddr >> 24; + netif->hwaddr[3] = randaddr >> 16; + netif->hwaddr[4] = randaddr >> 8; + netif->hwaddr[5] = randaddr; + netif->hwaddr_len = 6; + + /* device capabilities */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP; + + vdeif->vdeconn = vde_open(vderl, vdedescr, NULL); + LWIP_DEBUGF(VDEIF_DEBUG, ("vdeif_init: ok = %d\n", !!vdeif->vdeconn)); + if (vdeif->vdeconn == NULL) { + perror("vdeif_init: cannot open vde net"); + exit(1); + } + + netif_set_link_up(netif); + +#if !NO_SYS + sys_thread_new("vdeif_thread", vdeif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO); +#endif /* !NO_SYS */ +} +/*-----------------------------------------------------------------------------------*/ +/* + * low_level_output(): + * + * Should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + */ +/*-----------------------------------------------------------------------------------*/ + +static err_t +low_level_output(struct netif *netif, struct pbuf *p) +{ + struct vdeif *vdeif = (struct vdeif *)netif->state; + char buf[1518]; /* max packet size including VLAN excluding CRC */ + ssize_t written; + + if (p->tot_len > sizeof(buf)) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + perror("vdeif: packet too large"); + return ERR_IF; + } + + /* initiate transfer(); */ + pbuf_copy_partial(p, buf, p->tot_len, 0); + + /* signal that packet should be sent(); */ + written = vde_send(vdeif->vdeconn, buf, p->tot_len, 0); + if (written < p->tot_len) { + MIB2_STATS_NETIF_INC(netif, ifoutdiscards); + perror("vdeif: write"); + return ERR_IF; + } else { + MIB2_STATS_NETIF_ADD(netif, ifoutoctets, (u32_t)written); + return ERR_OK; + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * low_level_input(): + * + * Should allocate a pbuf and transfer the bytes of the incoming + * packet from the interface into the pbuf. + * + */ +/*-----------------------------------------------------------------------------------*/ +static struct pbuf * +low_level_input(struct netif *netif) +{ + struct pbuf *p; + u16_t len; + ssize_t readlen; + char buf[1518]; /* max packet size including VLAN excluding CRC */ + struct vdeif *vdeif = (struct vdeif *)netif->state; + + /* Obtain the size of the packet and put it into the "len" + variable. */ + readlen = vde_recv(vdeif->vdeconn, buf, sizeof(buf), 0); + if (readlen < 0) { + perror("read returned -1"); + exit(1); + } + len = (u16_t)readlen; + + MIB2_STATS_NETIF_ADD(netif, ifinoctets, len); + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + if (p != NULL) { + pbuf_take(p, buf, len); + /* acknowledge that packet has been read(); */ + } else { + /* drop packet(); */ + MIB2_STATS_NETIF_INC(netif, ifindiscards); + LWIP_DEBUGF(NETIF_DEBUG, ("vdeif_input: could not allocate pbuf\n")); + } + + return p; +} + +/*-----------------------------------------------------------------------------------*/ +/* + * vdeif_input(): + * + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. + * + */ +/*-----------------------------------------------------------------------------------*/ +static void +vdeif_input(struct netif *netif) +{ + struct pbuf *p = low_level_input(netif); + + if (p == NULL) { +#if LINK_STATS + LINK_STATS_INC(link.recv); +#endif /* LINK_STATS */ + LWIP_DEBUGF(VDEIF_DEBUG, ("vdeif_input: low_level_input returned NULL\n")); + return; + } + + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("vdeif_input: netif input error\n")); + pbuf_free(p); + } +} +/*-----------------------------------------------------------------------------------*/ +/* + * vdeif_init(): + * + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + */ +/*-----------------------------------------------------------------------------------*/ +err_t +vdeif_init(struct netif *netif) +{ + char *vderl = (char *) netif->state; + struct vdeif *vdeif = (struct vdeif *)mem_malloc(sizeof(struct vdeif)); + + if (vdeif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("vdeif_init: out of memory for vdeif\n")); + return ERR_MEM; + } + netif->state = vdeif; + MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000); + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; +#if LWIP_IPV4 + netif->output = etharp_output; +#endif /* LWIP_IPV4 */ +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + netif->mtu = 1500; + + low_level_init(netif, vderl); + + return ERR_OK; +} + + +/*-----------------------------------------------------------------------------------*/ +void +vdeif_poll(struct netif *netif) +{ + vdeif_input(netif); +} + +#if NO_SYS + +int +vdeif_select(struct netif *netif) +{ + fd_set fdset; + int ret; + struct timeval tv; + struct vdeif *vdeif; + u32_t msecs = sys_timeouts_sleeptime(); + int datafd; + + vdeif = (struct vdeif *)netif->state; + datafd = vde_datafd(vdeif->vdeconn); + + tv.tv_sec = msecs / 1000; + tv.tv_usec = (msecs % 1000) * 1000; + + FD_ZERO(&fdset); + FD_SET(datafd, &fdset); + + ret = select(datafd + 1, &fdset, NULL, NULL, &tv); + if (ret > 0) { + vdeif_input(netif); + } + return ret; +} + +#else /* NO_SYS */ + +static void +vdeif_thread(void *arg) +{ + struct netif *netif; + struct vdeif *vdeif; + fd_set fdset; + int ret; + int datafd; + + netif = (struct netif *)arg; + vdeif = (struct vdeif *)netif->state; + datafd = vde_datafd(vdeif->vdeconn); + + while(1) { + FD_ZERO(&fdset); + FD_SET(datafd, &fdset); + + /* Wait for a packet to arrive. */ + ret = select(datafd + 1, &fdset, NULL, NULL, NULL); + + if(ret == 1) { + /* Handle incoming packet. */ + vdeif_input(netif); + } else if(ret == -1) { + perror("vdeif_thread: select"); + } + } +} + +#endif /* NO_SYS */