diff --git a/src/Options.h b/src/Options.h index 076f1c8..6f476af 100644 --- a/src/Options.h +++ b/src/Options.h @@ -51,7 +51,7 @@ /** * How often the lwIP tcpip thread callback checks for incoming frames */ -#define LWIP_GUARDED_BUF_CHECK_INTERVAL 5 +#define LWIP_GUARDED_BUF_CHECK_INTERVAL 25 /** * Number of packets that can be queued for ingress into the lwIP core diff --git a/src/VirtualTap.cpp b/src/VirtualTap.cpp index 81b2a94..70364fe 100644 --- a/src/VirtualTap.cpp +++ b/src/VirtualTap.cpp @@ -92,7 +92,7 @@ VirtualTap::~VirtualTap() _run = false; ::write(_shutdownSignalPipe[1],"\0",1); _phy.whack(); - lwip_dispose_of_netifs(this); + lwip_dispose_of_netif(this); Thread::join(_thread); ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); diff --git a/src/lwipDriver.cpp b/src/lwipDriver.cpp index f48eeee..0181d8b 100644 --- a/src/lwipDriver.cpp +++ b/src/lwipDriver.cpp @@ -106,33 +106,6 @@ static void tcpip_init_done(void *arg) sys_sem_signal(sem); } -void my_tcpip_callback(void *arg) -{ - if (!_run_lwip_tcpip) { - return; - } - err_t err = ERR_OK; - int loop_score = LWIP_FRAMES_HANDLED_PER_CORE_CALL; // max num of packets to read per polling call - struct zts_sorted_packet *sp; - while (loop_score > 0 && rx_queue.size_approx() > 0) { - struct pbuf *p; - if (rx_queue.try_dequeue(sp)) { - p = sp->p; - // Feed packet into appropriate lwIP netif - if (sp->p && sp->n) { - if ((err = sp->n->input(sp->p, sp->n)) != ERR_OK) { - DEBUG_ERROR("packet input error (p=%p, n=%p)=%d", p, sp->n, err); - pbuf_free(p); - } - sp->p = NULL; - } - delete sp; - sp = NULL; - } - loop_score--; - } -} - static void main_lwip_driver_loop(void *arg) { #if defined(__linux__) @@ -151,9 +124,6 @@ static void main_lwip_driver_loop(void *arg) // Main loop while(_run_lwip_tcpip) { lwip_sleep(LWIP_GUARDED_BUF_CHECK_INTERVAL); - // Handle incoming packets from the core's thread context. - // If you feed frames into the core directly you will violate the core's thread model - tcpip_callback_with_block(my_tcpip_callback, NULL, 1); } _has_exited = true; postEvent(ZTS_EVENT_STACK_DOWN); @@ -213,13 +183,15 @@ void lwip_driver_shutdown() */ } -void lwip_dispose_of_netifs(void *tapref) +void lwip_dispose_of_netif(void *tapref) { VirtualTap *vtap = (VirtualTap*)tapref; if (vtap->netif) { + LOCK_TCPIP_CORE(); netif_remove((struct netif*)(vtap->netif)); netif_set_down((struct netif*)(vtap->netif)); netif_set_link_down((struct netif*)(vtap->netif)); + UNLOCK_TCPIP_CORE(); delete vtap->netif; vtap->netif = NULL; } @@ -295,13 +267,6 @@ void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int e Utils::ntoh(ethhdr.type), flagbuf); } */ - if (etherType == 0x0800 || etherType == 0x0806 || etherType == 0x86DD) { // ip4 or ARP - if (!tap->netif) { - DEBUG_ERROR("dropped packet: no netif to accept this packet (etherType=%x) on this vtap (%p)", etherType, tap); - return; - } - } - p = pbuf_alloc(PBUF_RAW, len+sizeof(struct eth_hdr), PBUF_RAM); if (!p) { DEBUG_ERROR("dropped packet: unable to allocate memory for pbuf"); @@ -315,6 +280,7 @@ void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int e DEBUG_ERROR("dropped packet: first pbuf smaller than ethernet header"); return; } + // Copy frame data into pbuf const char *dataptr = reinterpret_cast(data); memcpy(q->payload,ðhdr,sizeof(ethhdr)); int remainingPayloadSpace = q->len - sizeof(ethhdr); @@ -325,32 +291,12 @@ void lwip_eth_rx(VirtualTap *tap, const MAC &from, const MAC &to, unsigned int e memcpy(q->payload,dataptr,q->len); dataptr += q->len; } - - if (rx_queue.size_approx() >= ZTS_LWIP_MAX_RX_QUEUE_LEN) { - DEBUG_INFO("dropped packet: rx_queue is full (>= %d)", ZTS_LWIP_MAX_RX_QUEUE_LEN); - // TODO: Test performance scenarios: dropping this packet, dropping oldest front packet + // Feed packet into stack + int err; + if ((err = ((struct netif *)tap->netif)->input(p, (struct netif *)tap->netif)) != ERR_OK) { + DEBUG_ERROR("packet input error (%d)", err); pbuf_free(p); - p = NULL; - return; } - - // Construct a pre-sorted packet for lwIP packet feeder timeout - struct zts_sorted_packet *sp = new struct zts_sorted_packet; - sp->p = p; - sp->vtap=tap; - - switch (etherType) - { - case 0x0800: // ip4 - case 0x0806: // ARP - case 0x86DD: // ip6 - sp->n = (struct netif *)tap->netif; - break; - default: - DEBUG_ERROR("dropped packet: unhandled (etherType=%x)", etherType); - break; - } - rx_queue.enqueue(sp); } static void print_netif_info(struct netif *n) { @@ -375,48 +321,10 @@ static void print_netif_info(struct netif *n) { bool lwip_is_netif_up(void *n) { - return netif_is_up((struct netif*)n); -} - -/** - * Called when the status of a netif changes: - * - Interface is up/down (ZTS_EVENT_NETIF_UP, ZTS_EVENT_NETIF_DOWN) - * - Address changes while up (ZTS_EVENT_NETIF_NEW_ADDRESS) - */ -static void netif_status_callback(struct netif *n) -{ - //DEBUG_INFO("netif=%p", n); - // TODO: It appears that there may be a bug in lwIP's handling of callbacks for netifs - // configured to handle ipv4 traffic. For this reason a temporary measure of checking - // the status of the interfaces ourselves from the service is used. - /* - if (!n->state) { - return; - } - uint64_t mac = 0; - memcpy(&mac, n->hwaddr, n->hwaddr_len); - - VirtualTap *tap = (VirtualTap *)n->state; - if (n->flags & NETIF_FLAG_UP) { - VirtualTap *vtap = (VirtualTap*)n->state; - - if (n) { - struct zts_netif_details *ifd = new zts_netif_details; - ifd->nwid = tap->_nwid; - memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len); - ifd->mac = htonl(ifd->mac) >> 16; - postEvent(ZTS_EVENT_NETIF_UP, (void*)ifd); - } - } - if (!(n->flags & NETIF_FLAG_UP)) { - struct zts_netif_details *ifd = new zts_netif_details; - ifd->nwid = tap->_nwid; - memcpy(&(ifd->mac), n->hwaddr, n->hwaddr_len); - ifd->mac = htonl(ifd->mac) >> 16; - postEvent(ZTS_EVENT_NETIF_DOWN, (void*)ifd); - } - */ - // TODO: ZTS_EVENT_NETIF_NEW_ADDRESS + LOCK_TCPIP_CORE(); + bool result = netif_is_up((struct netif*)n); + UNLOCK_TCPIP_CORE(); + return result; } /** @@ -424,6 +332,7 @@ static void netif_status_callback(struct netif *n) */ static void netif_remove_callback(struct netif *n) { + // Called from core, no need to lock if (!n->state) { return; } @@ -442,6 +351,7 @@ static void netif_remove_callback(struct netif *n) */ static void netif_link_callback(struct netif *n) { + // Called from core, no need to lock if (!n->state) { return; } @@ -467,6 +377,7 @@ static void netif_link_callback(struct netif *n) void lwip_set_callbacks(struct netif *n) { #if LWIP_NETIF_STATUS_CALLBACK + // Not currently used netif_set_status_callback(n, netif_status_callback); #endif #if LWIP_NETIF_REMOVE_CALLBACK @@ -493,6 +404,7 @@ static void lwip_prepare_netif_status_msg(struct netif *n) static err_t netif_init(struct netif *n) { + // Called from netif code, no need to lock n->hwaddr_len = 6; n->name[0] = 'z'; n->name[1] = '4'; @@ -507,7 +419,6 @@ static err_t netif_init(struct netif *n) | NETIF_FLAG_LINK_UP | NETIF_FLAG_UP; n->hwaddr_len = sizeof(n->hwaddr); - // lwip_set_callbacks(netif); VirtualTap *tap = (VirtualTap*)(n->state); tap->_mac.copyTo(n->hwaddr, n->hwaddr_len); lwip_prepare_netif_status_msg(n); @@ -534,7 +445,9 @@ void lwip_init_interface(void *tapref, const MAC &mac, const InetAddress &ip) IP4_ADDR(&gw,127,0,0,1); ipaddr.addr = *((u32_t *)ip.rawIpData()); netmask.addr = *((u32_t *)ip.netmask().rawIpData()); + LOCK_TCPIP_CORE(); netif_add(n, &ipaddr, &netmask, &gw, tapref, netif_init, tcpip_input); + UNLOCK_TCPIP_CORE(); /* snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", n->hwaddr[0], n->hwaddr[1], n->hwaddr[2], @@ -549,11 +462,13 @@ void lwip_init_interface(void *tapref, const MAC &mac, const InetAddress &ip) memcpy(&(ipaddr.addr), ip.rawIpData(), sizeof(ipaddr.addr)); n->ip6_autoconfig_enabled = 1; + LOCK_TCPIP_CORE(); netif_ip6_addr_set(n, 1, &ipaddr); netif_create_ip6_linklocal_address(n, 1); netif_ip6_addr_set_state(n, 0, IP6_ADDR_TENTATIVE); netif_ip6_addr_set_state(n, 1, IP6_ADDR_TENTATIVE); n->output_ip6 = ethip6_output; + UNLOCK_TCPIP_CORE(); /* snprintf(macbuf, ZTS_MAC_ADDRSTRLEN, "%02x:%02x:%02x:%02x:%02x:%02x", n->hwaddr[0], n->hwaddr[1], n->hwaddr[2], diff --git a/src/lwipDriver.hpp b/src/lwipDriver.hpp index e8ea7b4..8e24e05 100644 --- a/src/lwipDriver.hpp +++ b/src/lwipDriver.hpp @@ -108,7 +108,7 @@ void lwip_driver_shutdown(); * by re-adding a virtual tap (and associated lwip netifs) * @return */ -void lwip_dispose_of_netifs(void *tapref); +void lwip_dispose_of_netif(void *tapref); /** * @brief Initialize and start the DNS client diff --git a/src/lwipopts.h b/src/lwipopts.h index a539e18..f2199b1 100644 --- a/src/lwipopts.h +++ b/src/lwipopts.h @@ -45,66 +45,179 @@ #define _LWIPOPTS_H_ /*------------------------------------------------------------------------------ -------------------- Custom additions to lwipopts.h for libzt ------------------- +------------------------------- Config for libzt ------------------------------- ------------------------------------------------------------------------------*/ -/* - * Provides its own errno - */ -#if __ANDROID__ -#define LWIP_PROVIDE_ERRNO 1 -#define SOCKLEN_T_DEFINED -#elif !defined(_MSC_VER) -#define LWIP_PROVIDE_ERRNO 1 -#endif - -/** - * Disable assertions - */ -#define LWIP_NOASSERT 1 - -/** - * Don't redefine byte-order functions if they're already available - */ +// Misc +#define LWIP_NOASSERT 1 #if __ANDROID__ #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 0 #endif - -/** - * Checksum for payloads - */ -#define LWIP_CHKSUM_ALGORITHM 2 - -/** - * Used to compute TCP_MSS - */ -#define MTU 2800 - -/** - * Enable or disable debug, see debug ection near end of file - * for more options. - */ -//#define LWIP_DEBUG 0 - -/* flag for LWIP_DEBUGF indicating a tracing message - * (to follow program flow) - */ -#define LWIP_DBG_TRACE 0x40U -/* flag for LWIP_DEBUGF indicating a state debug message - * (to follow module states) - */ -#define LWIP_DBG_STATE 0x20U -/* flag for LWIP_DEBUGF indicating newly added code, - * not thoroughly tested yet - */ -#define LWIP_DBG_FRESH 0x10U -/* flag for LWIP_DEBUGF to halt after printing - * this debug message - */ -#define LWIP_DBG_HALT 0x08U +#if __ANDROID__ +#define LWIP_PROVIDE_ERRNO 1 +#define SOCKLEN_T_DEFINED +#elif !defined(_MSC_VER) +#define LWIP_PROVIDE_ERRNO 1 +#endif +// Sockets +#define LWIP_SOCKET 1 +#define LWIP_COMPAT_SOCKETS 0 +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 1 +#define SO_REUSE 1 +#define LWIP_FIONREAD_LINUXMODE 1 +// TCP +#define LWIP_TCP_KEEPALIVE 1 +#define TCP_LISTEN_BACKLOG 1 +#define TCP_DEFAULT_LISTEN_BACKLOG 0xff +// ARP +#define ARP_TABLE_SIZE 3 +#define ARP_MAXAGE 300 +#define ARP_QUEUEING 1 +#define ARP_QUEUE_LEN 3 +// netif +#define LWIP_NETIF_STATUS_CALLBACK 0 +#define LWIP_NETIF_EXT_STATUS_CALLBACK 0 +#define LWIP_NETIF_LINK_CALLBACK 0 +#define LWIP_NETIF_REMOVE_CALLBACK 0 /*------------------------------------------------------------------------------ ----------------------------------- Timers -------------------------------------- +------------------------------------ Presets ----------------------------------- +------------------------------------------------------------------------------*/ + +// Embedded applications (lwIP out-of-the-box defaults) +#if 0 + #define TCP_TMR_INTERVAL 250 +#endif + +// Desktop-class applications +#if 1 + #define MTU 2800 + #define LWIP_CHKSUM_ALGORITHM 2 + // memory + #define MEMP_NUM_NETCONN 1024 + #define MEMP_NUM_NETBUF 2 + #define MEMP_NUM_TCPIP_MSG_API 64 + #define MEMP_NUM_TCPIP_MSG_INPKT 64 + #define PBUF_POOL_SIZE 128 + // ip + #define IP_REASS_MAXAGE 15 + #define IP_REASS_MAX_PBUFS 32 + // tcp + #define TCP_TMR_INTERVAL 25 + #define TCP_WND 0xffff + #define TCP_MAXRTX 12 + #define TCP_SYNMAXRTX 12 + #define LWIP_TCP_SACK_OUT 1 + #define LWIP_TCP_MAX_SACK_NUM 4 + #define TCP_MSS (MTU - 40) + #define TCP_SND_BUF (64 * TCP_MSS) + #define TCP_SND_QUEUELEN (64 * (2 * (TCP_SND_BUF/TCP_MSS))) + #define TCP_SNDLOWAT (0xffff - (4*TCP_MSS) - 1) + #define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) + #define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) + #define LWIP_WND_SCALE 1 + #define TCP_RCV_SCALE 0 + // tcpip + #define TCPIP_MBOX_SIZE 0 + #define LWIP_TCPIP_CORE_LOCKING 1 + #define LWIP_TCPIP_CORE_LOCKING_INPUT 1 + // netconn + #define LWIP_NETCONN_FULLDUPLEX 0 + // netif + #define LWIP_SINGLE_NETIF 0 + #define LWIP_NETIF_HWADDRHINT 1 + #define LWIP_NETIF_TX_SINGLE_PBUF 0 + #define TCPIP_THREAD_PRIO 1 +#endif + +// Desktop-class applications +#if 0 + #define MTU 2800 + #define LWIP_CHKSUM_ALGORITHM 2 + // memory + #define MEMP_NUM_NETCONN 1024 + #define MEMP_NUM_NETBUF 2 + #define MEMP_NUM_TCPIP_MSG_API 64 + #define MEMP_NUM_TCPIP_MSG_INPKT 64 + #define PBUF_POOL_SIZE 128 + // ip + #define IP_REASS_MAXAGE 15 + #define IP_REASS_MAX_PBUFS 32 + // tcp + #define TCP_TMR_INTERVAL 25 + #define TCP_WND 0xffff + #define TCP_MAXRTX 12 + #define TCP_SYNMAXRTX 12 + #define LWIP_TCP_SACK_OUT 1 + #define LWIP_TCP_MAX_SACK_NUM 4 + #define TCP_MSS (MTU - 40) + #define TCP_SND_BUF (32 * TCP_MSS) + #define TCP_SND_QUEUELEN (64 * (2 * (TCP_SND_BUF/TCP_MSS))) + #define TCP_SNDLOWAT (0xffff - (4*TCP_MSS) - 1) + #define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5) + #define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) + #define LWIP_WND_SCALE 1 + #define TCP_RCV_SCALE 0 + // tcpip + #define TCPIP_MBOX_SIZE 0 + #define LWIP_TCPIP_CORE_LOCKING 1 + #define LWIP_TCPIP_CORE_LOCKING_INPUT 1 + // netconn + #define LWIP_NETCONN_FULLDUPLEX 0 + // netif + #define LWIP_SINGLE_NETIF 0 + #define LWIP_NETIF_HWADDRHINT 1 + #define LWIP_NETIF_TX_SINGLE_PBUF 0 + #define TCPIP_THREAD_PRIO 1 +#endif + +// Stable +#if 0 + #define MTU 2800 + #define LWIP_CHKSUM_ALGORITHM 2 + // memory + #define MEMP_NUM_NETCONN 1024 + #define MEMP_NUM_NETBUF 2 + #define MEMP_NUM_TCPIP_MSG_API 64 + #define MEMP_NUM_TCPIP_MSG_INPKT 64 + #define PBUF_POOL_SIZE 128 + // ip + #define IP_REASS_MAXAGE 15 + #define IP_REASS_MAX_PBUFS 32 + // tcp + #define TCP_TMR_INTERVAL 25 + #define TCP_WND 0xffff + #define TCP_MAXRTX 12 + #define TCP_SYNMAXRTX 12 + #define LWIP_TCP_SACK_OUT 0 + #define LWIP_TCP_MAX_SACK_NUM 4 + #define TCP_MSS (MTU - 40) + #define TCP_SND_BUF (32 * TCP_MSS) + #define TCP_SND_QUEUELEN (64 * (2 * (TCP_SND_BUF/TCP_MSS))) + #define TCP_SNDLOWAT (0xffff - (4*TCP_MSS) - 1) + #define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) + #define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) + #define LWIP_WND_SCALE 1 + #define TCP_RCV_SCALE 0 + // tcpip + #define TCPIP_MBOX_SIZE 0 + #define LWIP_TCPIP_CORE_LOCKING 1 + #define LWIP_TCPIP_CORE_LOCKING_INPUT 1 + // netconn + #define LWIP_NETCONN_FULLDUPLEX 0 + // netif + #define LWIP_SINGLE_NETIF 0 + #define LWIP_NETIF_HWADDRHINT 1 + #define LWIP_NETIF_TX_SINGLE_PBUF 0 + #define TCPIP_THREAD_PRIO 1 +#endif + +/*------------------------------------------------------------------------------ +------------------------------------ Timers ------------------------------------ ------------------------------------------------------------------------------*/ /* Be careful about setting this too small. lwIP just counts the number @@ -117,7 +230,7 @@ happening sooner than they should. /* these are originally defined in tcp_impl.h */ #ifndef TCP_TMR_INTERVAL /* The TCP timer interval in milliseconds. */ -#define TCP_TMR_INTERVAL 250 +#define TCP_TMR_INTERVAL 25 #endif /* TCP_TMR_INTERVAL */ #ifndef TCP_FAST_INTERVAL @@ -377,7 +490,7 @@ happening sooner than they should. * a lot of data that needs to be copied, this should be set high. */ #if !defined MEM_SIZE || defined __DOXYGEN__ -#define MEM_SIZE 1024 * 1024 +#define MEM_SIZE 1024 * 1024 * 32 #endif /** @@ -550,7 +663,7 @@ happening sooner than they should. * reassembly (whole packets, not fragments!) */ #if !defined MEMP_NUM_REASSDATA || defined __DOXYGEN__ -#define MEMP_NUM_REASSDATA 16 +#define MEMP_NUM_REASSDATA 1024 #endif /** @@ -612,7 +725,7 @@ happening sooner than they should. * (only needed if you use the sequential API, like api_lib.c) */ #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ -#define MEMP_NUM_NETCONN 256 +#define MEMP_NUM_NETCONN 1024 #endif /** @@ -1319,7 +1432,7 @@ happening sooner than they should. * will be TCP_WND >> TCP_RCV_SCALE */ #if !defined TCP_WND || defined __DOXYGEN__ -#define TCP_WND 0xFFFF // (4 * TCP_MSS) +#define TCP_WND (1 * 0xffff) // *1024 //0xFFFF // (4 * TCP_MSS) #endif /** @@ -1348,7 +1461,7 @@ happening sooner than they should. * LWIP_TCP_SACK_OUT==1: TCP will support sending selective acknowledgements (SACKs). */ #if !defined LWIP_TCP_SACK_OUT || defined __DOXYGEN__ -#define LWIP_TCP_SACK_OUT 0 +#define LWIP_TCP_SACK_OUT 1 #endif /** @@ -1519,6 +1632,7 @@ happening sooner than they should. * explicit window update */ #if !defined TCP_WND_UPDATE_THRESHOLD || defined __DOXYGEN__ +//#define TCP_WND_UPDATE_THRESHOLD (TCP_MSS) #define TCP_WND_UPDATE_THRESHOLD LWIP_MIN((TCP_WND / 4), (TCP_MSS * 4)) #endif