diff --git a/tests/net/vlan/prj.conf b/tests/net/vlan/prj.conf index a36eb23780c8..b7c11f8c9d6a 100644 --- a/tests/net/vlan/prj.conf +++ b/tests/net/vlan/prj.conf @@ -16,16 +16,18 @@ CONFIG_NET_PKT_TX_COUNT=15 CONFIG_NET_PKT_RX_COUNT=15 CONFIG_NET_BUF_RX_COUNT=15 CONFIG_NET_BUF_TX_COUNT=15 -CONFIG_NET_IF_MAX_IPV6_COUNT=8 +CONFIG_NET_IF_MAX_IPV6_COUNT=9 CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IPV6_ND=n CONFIG_NET_VLAN=y -CONFIG_NET_VLAN_COUNT=4 +CONFIG_NET_VLAN_COUNT=5 CONFIG_NET_CONTEXT_PRIORITY=y CONFIG_NET_SOCKETS=y CONFIG_ZTEST=y CONFIG_NET_CONFIG_SETTINGS=n CONFIG_NET_SHELL=n +CONFIG_NET_INTERFACE_NAME=y +CONFIG_NET_INTERFACE_NAME_LEN=15 # The address check must be disabled so that packet # is properly routed via Ethernet L2. diff --git a/tests/net/vlan/src/main.c b/tests/net/vlan/src/main.c index a6d2f88a892e..628c3c7dd5ae 100644 --- a/tests/net/vlan/src/main.c +++ b/tests/net/vlan/src/main.c @@ -51,6 +51,7 @@ LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL); #define VLAN_TAG_3 300 #define VLAN_TAG_4 400 #define VLAN_TAG_5 500 +#define VLAN_TAG_6 600 #define NET_ETH_MAX_COUNT 2 @@ -78,6 +79,7 @@ static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0, static struct net_if *eth_interfaces[NET_ETH_MAX_COUNT]; static struct net_if *vlan_interfaces[NET_VLAN_MAX_COUNT]; static struct net_if *dummy_interfaces[2]; +static struct net_if *embed_ll_interface; static bool test_failed; static bool test_started; @@ -125,6 +127,13 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) struct eth_context *context = dev->data; int ret; + if (!IS_ENABLED(CONFIG_NET_L2_ETHERNET_RESERVE_HEADER)) { + /* There should be at least two net_buf. The first one should contain + * the link layer header. + */ + zassert_not_equal(pkt->buffer->frags, NULL, "Only one net_buf in chain!"); + } + zassert_equal_ptr(ð_vlan_context, context, "Context pointers do not match (%p vs %p)", eth_vlan_context, context); @@ -159,7 +168,7 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) return ret; } -static enum ethernet_hw_caps eth_capabilities(const struct device *dev) +static enum ethernet_hw_caps eth_vlan_capabilities(const struct device *dev) { return ETHERNET_HW_VLAN; } @@ -167,7 +176,7 @@ static enum ethernet_hw_caps eth_capabilities(const struct device *dev) static struct ethernet_api api_funcs = { .iface_api.init = eth_vlan_iface_init, - .get_capabilities = eth_capabilities, + .get_capabilities = eth_vlan_capabilities, .send = eth_tx, }; @@ -209,6 +218,37 @@ ETH_NET_DEVICE_INIT(eth_test, "eth_test", eth_init, NULL, ð_vlan_context, NULL, CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU); +static int eth_tx_embed_ll_hdr(const struct device *dev, struct net_pkt *pkt) +{ + if (IS_ENABLED(CONFIG_NET_L2_ETHERNET_RESERVE_HEADER)) { + /* There should be only one net_buf */ + zassert_equal(pkt->buffer->frags, NULL, "More than one net_buf in chain!"); + } + + if (test_started) { + k_sleep(K_MSEC(10)); + k_sem_give(&wait_data); + } + + return 0; +} + +static enum ethernet_hw_caps eth_vlan_embed_ll_hdr_capabilities(const struct device *dev) +{ + return ETHERNET_HW_VLAN; +} + +static struct ethernet_api api_vlan_embed_ll_hdr_funcs = { + .iface_api.init = eth_vlan_iface_init, + + .get_capabilities = eth_vlan_embed_ll_hdr_capabilities, + .send = eth_tx_embed_ll_hdr, +}; + +ETH_NET_DEVICE_INIT(eth_embed_ll_hdr_test, "eth_embed_ll_hdr_test", eth_init, NULL, + ð_vlan_context, NULL, CONFIG_ETH_INIT_PRIORITY, + &api_vlan_embed_ll_hdr_funcs, NET_ETH_MTU); + struct net_if_test { uint8_t idx; /* not used for anything, just a dummy value */ uint8_t mac_addr[sizeof(struct net_eth_addr)]; @@ -317,6 +357,16 @@ static void iface_cb(struct net_if *iface, void *user_data) net_if_get_by_iface(iface)); if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) { + /* Ignore one special interface that is used to validate + * ll header embedding. + */ + if (strncmp(net_if_get_device(iface)->name, + "eth_embed_ll_hdr_test", + sizeof("eth_embed_ll_hdr_test") - 1) == 0) { + embed_ll_interface = iface; + return; + } + eth_interfaces[ud->eth_if_count++] = iface; } @@ -836,6 +886,76 @@ ZTEST(net_vlan, test_vlan_ipv6_sendto_recvfrom) zassert_equal(ret, 0, "close failed"); } +/* This should be the last test to be run so add "zz" to the name */ +ZTEST(net_vlan, test_zz_vlan_embed_ll_hdr) +{ + struct net_if *iface; + int ret; + int client_sock; + struct sockaddr_in6 client_addr; + struct sockaddr_in6 dest_addr; + struct net_if_addr *ifaddr; + ssize_t sent = 0; + struct ifreq ifreq = { 0 }; + char ifname[CONFIG_NET_INTERFACE_NAME_LEN]; + + /* embed ll interface addresses */ + static struct in6_addr my_vlan_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0x90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x2 } } }; + + static struct in6_addr peer_vlan_addr = { { { 0x20, 0x01, 0x0d, 0xb8, 0x90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; + + ret = net_eth_vlan_enable(embed_ll_interface, VLAN_TAG_6); + zassert_equal(ret, 0, "Could not enable %d (%d)", VLAN_TAG_6, ret); + + iface = net_eth_get_vlan_iface(embed_ll_interface, VLAN_TAG_6); + ret = net_eth_is_vlan_enabled(NULL, embed_ll_interface); + zassert_equal(ret, true, "VLAN not enabled for interface"); + + ifaddr = net_if_ipv6_addr_add(iface, + &my_vlan_addr, + NET_ADDR_MANUAL, 0); + if (!ifaddr) { + DBG("Cannot add IPv6 address %s\n", + net_sprint_ipv6_addr(&my_vlan_addr)); + zassert_not_null(ifaddr, "vlan addr"); + } + + net_if_up(embed_ll_interface); + net_if_up(iface); + + test_started = true; + + prepare_sock_udp_v6("2001:db8:90::2", ANY_PORT, &client_sock, &client_addr); + + ret = net_if_get_name(iface, ifname, sizeof(ifname)); + zassert_true(ret > 0, "cannot get interface name (%d/%s)", ret, strerror(-ret)); + + strncpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name)); + ret = zsock_setsockopt(client_sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, + sizeof(ifreq)); + zassert_equal(ret, 0, "SO_BINDTODEVICE failed, %d", -errno); + + ret = add_neighbor(iface, &peer_vlan_addr); + zassert_true(ret, "Cannot add neighbor"); + + net_ipaddr_copy(&dest_addr.sin6_addr, &peer_vlan_addr); + + sent = zsock_sendto(client_sock, TEST_STR_SMALL, strlen(TEST_STR_SMALL), + 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + zassert_equal(sent, strlen(TEST_STR_SMALL), "send (%d) failed %d/%s", + sent, -errno, strerror(errno)); + + if (k_sem_take(&wait_data, WAIT_TIME)) { + DBG("Timeout while waiting interface data\n"); + zassert_false(true, "Timeout"); + } + + ret = zsock_close(client_sock); + zassert_equal(ret, 0, "close failed"); +} + static void *setup(void) { test_vlan_setup(); diff --git a/tests/net/vlan/testcase.yaml b/tests/net/vlan/testcase.yaml index 28fda2f11dd6..c036e767a40a 100644 --- a/tests/net/vlan/testcase.yaml +++ b/tests/net/vlan/testcase.yaml @@ -1,8 +1,13 @@ common: depends_on: netif + min_ram: 32 + tags: + - net + - vlan tests: - net.vlan: - min_ram: 32 - tags: - - net - - vlan + net.vlan.separate_net_buf: + extra_configs: + - CONFIG_NET_L2_ETHERNET_RESERVE_HEADER=n + net.vlan.header_reserved: + extra_configs: + - CONFIG_NET_L2_ETHERNET_RESERVE_HEADER=y