napt/tests: add ip4 routing tests

Added tests:
- lwip native ip-forward tests
- napt feature test udp, tcp
- napt feature, test add/release of nat records

Testing configurations: lwip unit tests are executed in the following
three configurations:
- default
- IP_FORWARD=1
- IP_FORWARD=1 & IP_NAPT=1
Note that debugging option ESP_TEST_DEBUG was introduced to enable running only
IP-FORWARD/IP-NAPT tests with verbose output
This commit is contained in:
David Cermak
2020-03-16 14:17:20 +01:00
parent 4b4d6b2871
commit 754b8d5dcb
7 changed files with 692 additions and 5 deletions
+15 -4
View File
@@ -27,10 +27,21 @@ run_lwip_unittests:
- cd ports/unix/check/
# updating environment
- export LWIPDIR=../../../../src && export CK_DEFAULT_TIMEOUT=${TEST_TIMEOUT}
- export TESTFILES=`find $LWIPDIR/../test/unit -name '*.c' | tr '\n' ' '`
- export CFLAGS=-I$LWIPDIR/../test/unit/esp
# build and run tests
- make "TESTFILES=$TESTFILES" check
- export EXTRA_CFLAGS="" && export CC="cc $EXTRA_CFLAGS" && export CCDEP=cc
# build and run default lwip tests
- make -j 4 check
# retest with IP_FORWARD enabled
- make clean
- export EXTRA_CFLAGS="-DIP_FORWARD=1" && export CC="cc $EXTRA_CFLAGS"
- make -j 4 check
# retest with IP_FORWARD and IP_NAPT enabled
- make clean
- export EXTRA_CFLAGS="-DIP_FORWARD=1 -DIP_NAPT=1 -DLWIP_ARCH_CC_H -include cc_esp_platform.h" && export CC="cc $EXTRA_CFLAGS"
- make -j 4 check
# Please uncomment the below to test IP_FORWARD/IP_NAPT tests with debug output (only ip4_route test suite will be executed)
#- make clean
#- export EXTRA_CFLAGS="-DIP_FORWARD=1 -DESP_TEST_DEBUG=1 -DIP_NAPT=1 -DLWIP_ARCH_CC_H -include cc_esp_platform.h" && export CC="cc $EXTRA_CFLAGS"
#- make -j 4 check
.add_gh_key_remote: &add_gh_key_remote |
command -v ssh-agent >/dev/null || exit 1
+1
View File
@@ -36,6 +36,7 @@ TESTFILES=$(TESTDIR)/lwip_unittests.c \
$(TESTDIR)/core/test_def.c \
$(TESTDIR)/core/test_mem.c \
$(TESTDIR)/core/test_netif.c \
$(TESTDIR)/core/test_ip4_route.c \
$(TESTDIR)/core/test_pbuf.c \
$(TESTDIR)/core/test_timers.c \
$(TESTDIR)/dhcp/test_dhcp.c \
+88
View File
@@ -0,0 +1,88 @@
/*
* 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 <adam@sics.se>
*
*/
#ifndef LWIP_ARCH_CC_ESP_H
#define LWIP_ARCH_CC_ESP_H
/* see https://sourceforge.net/p/predef/wiki/OperatingSystems/ */
#if defined __ANDROID__
#define LWIP_UNIX_ANDROID
#elif defined __linux__
#define LWIP_UNIX_LINUX
#elif defined __APPLE__
#define LWIP_UNIX_MACH
#elif defined __OpenBSD__
#define LWIP_UNIX_OPENBSD
#elif defined __CYGWIN__
#define LWIP_UNIX_CYGWIN
#elif defined __GNU__
#define LWIP_UNIX_HURD
#endif
#define LWIP_TIMEVAL_PRIVATE 0
#include <sys/time.h>
#define LWIP_ERRNO_INCLUDE <errno.h>
#if defined(LWIP_UNIX_LINUX) || defined(LWIP_UNIX_HURD)
#define LWIP_ERRNO_STDINCLUDE 1
#endif
#ifdef LWIP_RAND
#define LWIP_RAND() ((u32_t)rand())
#endif
/* different handling for unit test, normally not needed */
#ifdef LWIP_NOASSERT_ON_ERROR
#define LWIP_ERROR(message, expression, handler) do { if (!(expression)) { \
handler;}} while(0)
#endif
#if defined(LWIP_UNIX_ANDROID) && defined(FD_SET)
typedef __kernel_fd_set fd_set;
#endif
#if defined(LWIP_UNIX_MACH)
/* sys/types.h and signal.h bring in Darwin byte order macros. pull the
header here and disable LwIP's version so that apps still can get
the macros via LwIP headers and use system headers */
#include <sys/types.h>
#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
#endif
struct sio_status_s;
typedef struct sio_status_s sio_status_t;
#define sio_fd_t sio_status_t*
#define __sio_fd_t_defined
typedef unsigned int sys_prot_t;
#endif /* LWIP_ARCH_CC_ESP_H */
+560
View File
@@ -0,0 +1,560 @@
#include "test_ip4_route.h"
#include "lwip/netif.h"
#include "lwip/stats.h"
#include "lwip/etharp.h"
#include "netif/ethernet.h"
#include "lwip/ip4.h"
#include "lwip/udp.h"
#include "lwip/inet_chksum.h"
#include "lwip/stats.h"
#include "lwip/prot/ip.h"
#include "lwip/prot/ip4.h"
#include "lwip/lwip_napt.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/tcpip.h"
#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
#endif
#if !LWIP_NETIF_EXT_STATUS_CALLBACK
#error "This tests needs LWIP_NETIF_EXT_STATUS_CALLBACK enabled"
#endif
static struct netif sta;
static struct netif ap;
static int ap_cnt = 0;
static int sta_cnt = 0;
static u32_t last_src_addr = 0;
static u32_t last_dst_addr = 0;
static u16_t last_src_port = 0;
#if IP_NAPT
static int random_mock = -1;
/* Mock the esp-random to return 0 for easier result checking */
uint32_t esp_random(void)
{
if (random_mock == -1) {
/* fall back to default "port/unix" rand (if other tests are launched with IP_NAPT ON) */
return rand();
}
return random_mock;
}
#endif
/* Setups/teardown functions */
static void
ip4route_setup(void)
{
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
}
static void
ip4route_teardown(void)
{
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
}
/* test helper functions */
static void debug_print_packet(struct pbuf *q)
{
struct ip_hdr *iphdr = (struct ip_hdr *)q->payload;
u16_t iphdr_hlen;
iphdr_hlen = IPH_HL_BYTES(iphdr);
fail_unless(0 == inet_chksum((struct ip_hdr *)q->payload, iphdr_hlen));
ip4_debug_print(q);
last_src_addr = iphdr->src.addr;
last_dst_addr = iphdr->dest.addr;
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
struct udp_hdr *udphdr = (struct udp_hdr *)(( u8_t *)iphdr + iphdr_hlen);
udp_debug_print(udphdr);
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
ip_addr_debug_print_val(UDP_DEBUG, *ip_current_dest_addr());
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest)));
ip_addr_debug_print_val(UDP_DEBUG, *ip_current_src_addr());
LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src)));
last_src_port = udphdr->src;
} else if (IPH_PROTO(iphdr) == IP_PROTO_TCP) {
struct tcp_hdr* tcphdr;
pbuf_header(q, -(s16_t)sizeof(struct ip_hdr));
tcphdr = (struct tcp_hdr*)q->payload;
tcp_debug_print(tcphdr);
last_src_port = tcphdr->src;
}
}
static err_t
ap_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
{
ap_cnt++;
debug_print_packet(q);
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(q);
LWIP_UNUSED_ARG(ipaddr);
return ERR_OK;
}
static err_t
sta_output(struct netif *netif, struct pbuf *q, const ip4_addr_t *ipaddr)
{
sta_cnt++;
debug_print_packet(q);
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(q);
LWIP_UNUSED_ARG(ipaddr);
return ERR_OK;
}
static err_t
sta_tx_func(struct netif *netif, struct pbuf *p)
{
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(p);
return ERR_OK;
}
static err_t
ap_tx_func(struct netif *netif, struct pbuf *p)
{
LWIP_UNUSED_ARG(netif);
LWIP_UNUSED_ARG(p);
return ERR_OK;
}
#if IP_NAPT
static struct pbuf*
test_create_tcp_packet(u32_t src_ip4, u32_t dst_ip4,
u16_t src_port, u16_t dst_port,
u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd)
{
struct pbuf *p, *q;
ip_addr_t src_ip;
ip_addr_t dst_ip;
struct ip_hdr* iphdr;
struct tcp_hdr* tcphdr;
u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr));
src_ip.u_addr.ip4.addr = src_ip4;
dst_ip.u_addr.ip4.addr = dst_ip4;
p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
EXPECT_RETNULL(p != NULL);
/* first pbuf must be big enough to hold the headers */
EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr)));
for(q = p; q != NULL; q = q->next) {
memset(q->payload, 0, q->len);
}
iphdr = (struct ip_hdr*)p->payload;
/* fill IP header */
iphdr->dest.addr = ip_2_ip4(&dst_ip)->addr;
iphdr->src.addr = ip_2_ip4(&src_ip)->addr;
IPH_VHL_SET(iphdr, 4, IP_HLEN / 4);
IPH_TOS_SET(iphdr, 0);
IPH_LEN_SET(iphdr, htons(p->tot_len));
iphdr->_ttl = 32;
iphdr->_proto = IP_PROTO_TCP;
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
/* let p point to TCP header */
pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
tcphdr = (struct tcp_hdr*)p->payload;
tcphdr->src = htons(src_port);
tcphdr->dest = htons(dst_port);
tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno);
TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
TCPH_FLAGS_SET(tcphdr, headerflags);
tcphdr->wnd = htons(wnd);
/* calculate checksum */
tcphdr->chksum = ip_chksum_pseudo(p,
IP_PROTO_TCP, p->tot_len, &src_ip, &dst_ip);
pbuf_header(p, sizeof(struct ip_hdr));
return p;
}
#endif
static struct pbuf *
test_udp_create_test_packet(u16_t length, u16_t dst_port, u16_t src_port, u32_t dst_addr, u32_t src_addr)
{
err_t err;
u8_t ret;
struct udp_hdr *uh;
struct ip_hdr *ih;
struct pbuf *p;
const u8_t test_data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL);
fail_unless(p != NULL);
if (p == NULL) {
return NULL;
}
fail_unless(p->next == NULL);
err = pbuf_take(p, test_data, length);
fail_unless(err == ERR_OK);
/* add UDP header */
ret = pbuf_add_header(p, sizeof(struct udp_hdr));
fail_unless(!ret);
uh = (struct udp_hdr *)p->payload;
uh->chksum = 0;
uh->dest = lwip_htons(dst_port);
uh->src = lwip_htons(src_port);
uh->len = lwip_htons(p->tot_len);
/* add IPv4 header */
ret = pbuf_add_header(p, sizeof(struct ip_hdr));
fail_unless(!ret);
ih = (struct ip_hdr *)p->payload;
memset(ih, 0, sizeof(*ih));
ih->dest.addr = dst_addr;
ih->src.addr = src_addr;
ih->_len = lwip_htons(p->tot_len);
ih->_ttl = 32;
ih->_proto = IP_PROTO_UDP;
IPH_VHL_SET(ih, 4, sizeof(struct ip_hdr) / 4);
IPH_CHKSUM_SET(ih, inet_chksum(ih, sizeof(struct ip_hdr)));
return p;
}
static void
send_to_netif(struct netif *input_netif, struct pbuf *p)
{
err_t err;
if (p != NULL) {
err = ip4_input(p, input_netif);
fail_unless(err == ERR_OK);
}
}
static err_t
testif_init_sta(struct netif *netif)
{
netif->name[0] = 's';
netif->name[1] = 't';
netif->output = sta_output;
netif->linkoutput = sta_tx_func;
netif->mtu = 1500;
netif->hwaddr_len = 6;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP;
netif->hwaddr[0] = 0x02;
netif->hwaddr[1] = 0x03;
netif->hwaddr[2] = 0x04;
netif->hwaddr[3] = 0x05;
netif->hwaddr[4] = 0x06;
netif->hwaddr[5] = 0x08;
return ERR_OK;
}
static err_t
testif_init_ap(struct netif *netif)
{
netif->name[0] = 'a';
netif->name[1] = 'p';
netif->output = ap_output;
netif->linkoutput = ap_tx_func;
netif->mtu = 1500;
netif->hwaddr_len = 6;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP;
netif->hwaddr[0] = 0x02;
netif->hwaddr[1] = 0x03;
netif->hwaddr[2] = 0x04;
netif->hwaddr[3] = 0x05;
netif->hwaddr[4] = 0x06;
netif->hwaddr[5] = 0x07;
return ERR_OK;
}
/* Test functions */
START_TEST(test_ip4_route_netif_forward)
{
#define UDP_PORT 1234
ip4_addr_t addr, src_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 1, 2, 3, 5);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 3, 4);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 1, 2, 3, 5);
p = test_udp_create_test_packet(16, UDP_PORT, UDP_PORT, addr.addr, src_addr.addr);
send_to_netif(&ap, p);
/* cleanup */
netif_set_down(&ap);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
fail_unless(ap_cnt == 0);
#if IP_FORWARD
fail_unless(sta_cnt == 1);
fail_unless(last_src_port == lwip_ntohs(UDP_PORT));
fail_unless(last_src_addr == src_addr.addr);
#else
/* if IP FORWARD disabled, no packet to be found on the other interface */
fail_unless(sta_cnt == 0);
#endif
#undef UDP_PORT
}
END_TEST
#if IP_NAPT
START_TEST(test_ip4_route_netif_napt_udp)
{
#define UDP_PORT 1234
ip4_addr_t addr, src_addr, sta_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&sta_addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &sta_addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 10, 0, 0, 1);
IP4_ADDR(&netmask, 255, 255, 0, 0);
IP4_ADDR(&gw, 10, 0, 0, 1);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
ip_napt_enable(addr.addr, 1);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 10, 0, 0, 2);
p = test_udp_create_test_packet(16, UDP_PORT, UDP_PORT, addr.addr, src_addr.addr);
random_mock = 1;
send_to_netif(&ap, p);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+random_mock));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(ap_cnt == 0);
fail_unless(sta_cnt == 1);
p = test_udp_create_test_packet(16, IP_NAPT_PORT_RANGE_START+random_mock, UDP_PORT, sta_addr.addr, addr.addr);
send_to_netif(&sta, p);
fail_unless(ap_cnt == 1);
fail_unless(sta_cnt == 1);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(UDP_PORT));
fail_unless(last_dst_addr == src_addr.addr);
/* cleanup */
netif_set_down(&ap);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
IP4_ADDR(&addr, 10, 0, 0, 1);
ip_napt_enable(addr.addr, 0);
#undef UDP_PORT
}
END_TEST
START_TEST(test_ip4_route_netif_napt_tcp)
{
#define TCP_PORT 2222
ip4_addr_t addr, src_addr, sta_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&sta_addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &sta_addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 10, 0, 0, 1);
IP4_ADDR(&netmask, 255, 255, 0, 0);
IP4_ADDR(&gw, 10, 0, 0, 1);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
ip_napt_enable_no(ap.num, 1);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 10, 0, 0, 2);
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT, TCP_PORT, 0, 0, TCP_SYN, 0);
random_mock = 2;
send_to_netif(&ap, p);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+random_mock));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(ap_cnt == 0);
fail_unless(sta_cnt == 1);
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT, IP_NAPT_PORT_RANGE_START+random_mock, 0, 0, TCP_SYN|TCP_ACK, 0);
send_to_netif(&sta, p);
fail_unless(ap_cnt == 1);
fail_unless(sta_cnt == 1);
/* expect to see a random port and translated source address to be station address */
fail_unless(last_src_port == lwip_ntohs(TCP_PORT));
fail_unless(last_dst_addr == src_addr.addr);
/* cleanup */
ip_napt_enable_no(ap.num, 0);
netif_set_down(&ap);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
#undef TCP_PORT
}
END_TEST
START_TEST(test_ip4_route_netif_max_napt)
{
#define TCP_PORT 2222
ip4_addr_t addr, src_addr, sta_addr;
ip4_addr_t netmask;
ip4_addr_t gw;
struct pbuf *p;
LWIP_UNUSED_ARG(_i);
/* setup station */
IP4_ADDR(&sta_addr, 1, 2, 4, 4);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gw, 1, 2, 4, 10);
netif_add(&sta, &sta_addr, &netmask, &gw, &sta, testif_init_sta, ethernet_input);
netif_set_up(&sta);
/* setup access point */
IP4_ADDR(&addr, 10, 0, 0, 1);
IP4_ADDR(&netmask, 255, 255, 0, 0);
IP4_ADDR(&gw, 10, 0, 0, 1);
netif_add(&ap, &addr, &netmask, &gw, &ap, testif_init_ap, ethernet_input);
netif_set_up(&ap);
ip_napt_enable_no(ap.num, 1);
/* create packet and send it to the AP */
IP4_ADDR(&addr, 1, 2, 4, 100);
IP4_ADDR(&src_addr, 10, 0, 0, 2);
for (int i=0; i<IP_NAPT_MAX*2; ++i) {
random_mock = i;
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT + i, TCP_PORT + i, 0, 0, TCP_SYN, 0);
send_to_netif(&ap, p);
if (i<IP_NAPT_MAX) {
/* if translated pairs of addr/port still below IP_NAT_MAX -> expect to see an outgoing packet */
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+random_mock));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(sta_cnt == 1+i);
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT+i, IP_NAPT_PORT_RANGE_START+random_mock, 0, 0, TCP_SYN | TCP_ACK, 0);
send_to_netif(&sta, p);
} else {
/* if more than NAPT_MAX, no more packet to be forwarded */
fail_unless(sta_cnt == IP_NAPT_MAX);
}
}
/* moves time forward to test releasing: */
lwip_sys_now += IP_NAPT_TIMEOUT_MS_TCP_DISCON + 1;
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT, IP_NAPT_PORT_RANGE_START+0, 0, 0, TCP_PSH, 0);
send_to_netif(&sta, p);
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT + IP_NAPT_MAX*2, TCP_PORT + IP_NAPT_MAX*2, 0, 0, TCP_PSH | TCP_ACK, 0);
sta_cnt = 0;
send_to_netif(&ap, p);
/* should not be released yet, since all the TCP connections are active */
fail_unless(sta_cnt == 0); /* expect no packet forwarded */
/* FIN the first connection so it could be released */
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT+0, IP_NAPT_PORT_RANGE_START+0, 0, 0, TCP_FIN, 0);
send_to_netif(&sta, p);
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT+0, TCP_PORT + 0, 0, 0, TCP_FIN | TCP_ACK, 0);
send_to_netif(&ap, p);
p = test_create_tcp_packet(addr.addr, sta_addr.addr, TCP_PORT+0, IP_NAPT_PORT_RANGE_START+0, 0, 0, TCP_ACK, 0);
send_to_netif(&sta, p);
/* moves time forward to test releasing: */
lwip_sys_now += IP_NAPT_TIMEOUT_MS_TCP_DISCON + 1;
/* now sending a new packet with max port, that should be forwarded */
p = test_create_tcp_packet(src_addr.addr, addr.addr, TCP_PORT + IP_NAPT_MAX*2, TCP_PORT + IP_NAPT_MAX*2, 0, 0, TCP_SYN, 0);
random_mock = 0;
sta_cnt = 0;
send_to_netif(&ap, p);
fail_unless(last_src_port == lwip_ntohs(IP_NAPT_PORT_RANGE_START+0));
fail_unless(last_src_addr == sta_addr.addr);
fail_unless(sta_cnt == 1); /* expect this packet gets forwarded */
/* cleanup */
netif_set_down(&ap);
ip_napt_enable_no(ap.num, 0);
netif_remove(&ap);
netif_set_down(&sta);
netif_remove(&sta);
#undef TCP_PORT
}
END_TEST
#endif
/** Create the suite including all tests for this module */
Suite *
ip4route_suite(void)
{
testfunc tests[] = {
TESTFUNC(test_ip4_route_netif_forward),
#if IP_NAPT
TESTFUNC(test_ip4_route_netif_napt_udp),
TESTFUNC(test_ip4_route_netif_napt_tcp),
TESTFUNC(test_ip4_route_netif_max_napt),
#endif
};
return create_suite("IP4_ROUTE", tests, sizeof(tests)/sizeof(testfunc), ip4route_setup, ip4route_teardown);
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef LWIP_HDR_TEST_IP4ROUTE_H
#define LWIP_HDR_TEST_IP4ROUTE_H
#include "../lwip_check.h"
Suite *ip4route_suite(void);
#endif
+5 -1
View File
@@ -8,6 +8,7 @@
#include "core/test_def.h"
#include "core/test_mem.h"
#include "core/test_netif.h"
#include "core/test_ip4_route.h"
#include "core/test_pbuf.h"
#include "core/test_timers.h"
#include "etharp/test_etharp.h"
@@ -62,6 +63,7 @@ int main(void)
SRunner *sr;
size_t i;
suite_getter_fn* suites[] = {
#ifndef ESP_TEST_DEBUG
ip4_suite,
ip6_suite,
udp_suite,
@@ -76,7 +78,9 @@ int main(void)
dhcp_suite,
mdns_suite,
mqtt_suite,
sockets_suite
sockets_suite,
#endif
ip4route_suite
};
size_t num = sizeof(suites)/sizeof(void*);
LWIP_ASSERT("No suites defined", num > 0);
+15
View File
@@ -102,4 +102,19 @@
#define ESP_LWIP_SELECT 1
#define ESP_LWIP_LOCK 1
#ifdef IP_NAPT
#define IP_NAPT_MAX 16
#undef LWIP_RAND
#define LWIP_RAND() (esp_random())
#include "lwip/arch.h"
u32_t esp_random(void);
#endif /* IP_NAPT */
/* ESP debug options */
#ifdef ESP_TEST_DEBUG
#define NAPT_DEBUG LWIP_DBG_ON
#define IP_DEBUG LWIP_DBG_ON
#define UDP_DEBUG LWIP_DBG_ON
#define TCP_DEBUG LWIP_DBG_ON
#endif /* ESP_TEST_DEBUG */
#endif /* LWIP_HDR_LWIPOPTS_H */