Skip to content

Commit

Permalink
tests: net: vlan: Add testing of link layer header embedding
Browse files Browse the repository at this point in the history
Create a special Ethernet interface that supports link layer
embedding. Add a test that uses this special Ethernet interface
to verify that the L2 header is embedded to the first net_buf.

Signed-off-by: Jukka Rissanen <[email protected]>
  • Loading branch information
jukkar authored and kartben committed Dec 19, 2024
1 parent 420c4b1 commit a2a0cc8
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 9 deletions.
6 changes: 4 additions & 2 deletions tests/net/vlan/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
124 changes: 122 additions & 2 deletions tests/net/vlan/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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(&eth_vlan_context, context,
"Context pointers do not match (%p vs %p)",
eth_vlan_context, context);
Expand Down Expand Up @@ -159,15 +168,15 @@ 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;
}

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,
};

Expand Down Expand Up @@ -209,6 +218,37 @@ ETH_NET_DEVICE_INIT(eth_test, "eth_test", eth_init, NULL,
&eth_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,
&eth_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)];
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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();
Expand Down
15 changes: 10 additions & 5 deletions tests/net/vlan/testcase.yaml
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit a2a0cc8

Please sign in to comment.