Skip to content

Commit cac932d

Browse files
glarsennordiccarlescufi
authored andcommitted
tests: net: Add tests for offloaded_netdev
Adds integration tests for offloaded_netdev iface API extension Signed-off-by: Georges Oates_Larsen <[email protected]>
1 parent 3c6b7dc commit cac932d

File tree

4 files changed

+368
-0
lines changed

4 files changed

+368
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(offloaded_netdev)
6+
7+
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip)
8+
FILE(GLOB app_sources src/*.c)
9+
target_sources(app PRIVATE ${app_sources})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CONFIG_NETWORKING=y
2+
CONFIG_NET_TEST=y
3+
CONFIG_NET_SOCKETS=y
4+
CONFIG_NET_SOCKETS_OFFLOAD=y
5+
CONFIG_NET_LOG=y
6+
CONFIG_ZTEST=y
7+
CONFIG_ZTEST_NEW_API=y
8+
CONFIG_TEST_USERSPACE=y
9+
CONFIG_NET_OFFLOAD=y
10+
CONFIG_TEST_RANDOM_GENERATOR=y
Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
/*
2+
* Copyright (c) 2022 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/types.h>
8+
#include <stdbool.h>
9+
#include <stddef.h>
10+
#include <string.h>
11+
#include <errno.h>
12+
13+
#include <zephyr/sys/printk.h>
14+
#include <zephyr/linker/sections.h>
15+
16+
#include <zephyr/ztest.h>
17+
#include <zephyr/net/offloaded_netdev.h>
18+
#include <zephyr/net/net_offload.h>
19+
#include <zephyr/net/net_if.h>
20+
#include <zephyr/net/net_l2.h>
21+
22+
/* Offloaded L2 initializer, mandatory for offloaded L2s */
23+
static int offload_l2_init(const struct device *dev)
24+
{
25+
ARG_UNUSED(dev);
26+
27+
return 0;
28+
}
29+
30+
/* Dummy socket creator for socket-offloaded ifaces */
31+
int offload_socket(int family, int type, int proto)
32+
{
33+
return -1;
34+
}
35+
36+
/* Dummy offload API for net-offloaded ifaces */
37+
struct net_offload net_offload_api;
38+
39+
/* Dummy init function for socket-offloaded ifaces */
40+
static void sock_offload_l2_iface_init(struct net_if *iface)
41+
{
42+
/* This must be called, and the passed-in socket creator cannot be NULL,
43+
* or the iface will not be recognized as offloaded
44+
*/
45+
net_if_socket_offload_set(iface, offload_socket);
46+
net_if_flag_set(iface, NET_IF_NO_AUTO_START);
47+
}
48+
49+
/* Dummy init function for net-offloaded ifaces */
50+
static void net_offload_l2_iface_init(struct net_if *iface)
51+
{
52+
/* Reviewers: Is there a better way to do this?
53+
* I couldn't find any actual examples in the source
54+
*/
55+
iface->if_dev->offload = &net_offload_api;
56+
net_if_flag_set(iface, NET_IF_NO_AUTO_START);
57+
}
58+
59+
/* Tracks the total number of ifaces that are up (theoretically). */
60+
atomic_t up_count = ATOMIC_INIT(0);
61+
62+
/* Tracks the total number of times that the offload_impl_enable callback was called. */
63+
atomic_t call_count = ATOMIC_INIT(0);
64+
65+
/* Expected return value from offload_impl_enable */
66+
atomic_t retval = ATOMIC_INIT(0);
67+
68+
/* Functionality under test */
69+
static int offload_impl_enable(const struct net_if *iface, bool enabled)
70+
{
71+
atomic_inc(&call_count);
72+
if (enabled) {
73+
atomic_inc(&up_count);
74+
} else {
75+
atomic_dec(&up_count);
76+
}
77+
return atomic_get(&retval);
78+
}
79+
80+
/* Net-dev APIs for L2s with offloaded sockets, with and without .enable */
81+
static struct offloaded_if_api sock_offloaded_impl_api = {
82+
.iface_api.init = sock_offload_l2_iface_init,
83+
.enable = offload_impl_enable
84+
};
85+
86+
static struct offloaded_if_api sock_offloaded_no_impl_api = {
87+
.iface_api.init = sock_offload_l2_iface_init
88+
};
89+
90+
/* Net-dev APIs for L2s that are net-offloaded, with and without .enable */
91+
static struct offloaded_if_api net_offloaded_impl_api = {
92+
.iface_api.init = net_offload_l2_iface_init,
93+
.enable = offload_impl_enable
94+
};
95+
96+
static struct offloaded_if_api net_offloaded_no_impl_api = {
97+
.iface_api.init = net_offload_l2_iface_init
98+
};
99+
100+
101+
/* Socket-offloaded netdevs, with and without .enable */
102+
NET_DEVICE_OFFLOAD_INIT(sock_offload_test_impl, "sock_offload_test_impl",
103+
offload_l2_init, NULL,
104+
NULL, NULL,
105+
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
106+
&sock_offloaded_impl_api, 0);
107+
108+
NET_DEVICE_OFFLOAD_INIT(sock_offload_test_no_impl, "sock_offload_test_no_impl",
109+
offload_l2_init, NULL,
110+
NULL, NULL,
111+
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
112+
&sock_offloaded_no_impl_api, 0);
113+
114+
/* Net-offloaded netdevs, with and without .enable */
115+
NET_DEVICE_OFFLOAD_INIT(net_offload_test_impl, "net_offload_test_impl",
116+
offload_l2_init, NULL,
117+
NULL, NULL,
118+
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
119+
&net_offloaded_impl_api, 0);
120+
121+
NET_DEVICE_OFFLOAD_INIT(net_offload_test_no_impl, "net_offload_test_no_impl",
122+
offload_l2_init, NULL,
123+
NULL, NULL,
124+
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
125+
&net_offloaded_no_impl_api, 0);
126+
127+
static void net_offloaded_netdev_before(void *fixture)
128+
{
129+
ARG_UNUSED(fixture);
130+
131+
/* Default to successful return value */
132+
atomic_set(&retval, 0);
133+
134+
/* Reset all ifaces */
135+
net_if_down(NET_IF_GET(sock_offload_test_impl, 0));
136+
net_if_down(NET_IF_GET(sock_offload_test_no_impl, 0));
137+
net_if_down(NET_IF_GET(net_offload_test_impl, 0));
138+
net_if_down(NET_IF_GET(net_offload_test_impl, 0));
139+
140+
/* Reset counters */
141+
atomic_set(&call_count, 0);
142+
atomic_set(&up_count, 0);
143+
}
144+
145+
ZTEST(net_offloaded_netdev, test_up_down_sock_off_impl)
146+
{
147+
struct net_if *test_iface = NET_IF_GET(sock_offload_test_impl, 0);
148+
149+
/* Verify iface under test is down before test */
150+
zassert_false(net_if_is_admin_up(test_iface),
151+
"Iface under test must be admin-down before test");
152+
153+
/* Bring iface up. */
154+
(void)net_if_up(test_iface);
155+
156+
/* Verify that a single iface went up once (according to the enable callback) */
157+
zassert_equal(atomic_get(&call_count), 1,
158+
"Bad transition-count, offload_impl_enable not called correctly");
159+
zassert_equal(atomic_get(&up_count), 1,
160+
"Bad up-count, offload_impl_enable not called correctly");
161+
zassert_true(net_if_is_admin_up(test_iface),
162+
"Iface under test should be up after net_if_up");
163+
164+
/* Bring iface down */
165+
(void)net_if_down(test_iface);
166+
167+
/* Verify that a single iface went down once (according to the enable callback)*/
168+
zassert_equal(atomic_get(&call_count), 2,
169+
"Bad transition-count, offload_impl_enable not called correctly");
170+
zassert_equal(atomic_get(&up_count), 0,
171+
"Bad up-count, offload_impl_enable not called correctly");
172+
zassert_false(net_if_is_admin_up(test_iface),
173+
"Iface under test should be down after net_if_down");
174+
}
175+
176+
ZTEST(net_offloaded_netdev, test_up_down_sock_off_no_impl)
177+
{
178+
struct net_if *test_iface = NET_IF_GET(sock_offload_test_no_impl, 0);
179+
180+
/* Verify iface under test is down before test */
181+
zassert_false(net_if_is_admin_up(test_iface),
182+
"Iface under test must be admin-down before test");
183+
184+
/* Bring iface up */
185+
(void)net_if_up(test_iface);
186+
187+
/* Verify that the iface went up, but callbacks were not fired*/
188+
zassert_equal(atomic_get(&call_count), 0,
189+
"offload_impl_enable was called unexpectedly");
190+
zassert_equal(atomic_get(&up_count), 0,
191+
"offload_impl_enable was called unexpectedly");
192+
zassert_true(net_if_is_admin_up(test_iface),
193+
"Iface under test should be up after net_if_up");
194+
195+
/* Bring iface down */
196+
(void)net_if_down(test_iface);
197+
198+
/* Verify that the iface went down, but callbacks were not fired*/
199+
zassert_equal(atomic_get(&call_count), 0,
200+
"offload_impl_enable was called unexpectedly");
201+
zassert_equal(atomic_get(&up_count), 0,
202+
"offload_impl_enable was called unexpectedly");
203+
zassert_false(net_if_is_admin_up(test_iface),
204+
"Iface under test should be down after net_if_down");
205+
}
206+
207+
ZTEST(net_offloaded_netdev, test_up_down_net_off_impl)
208+
{
209+
struct net_if *test_iface = NET_IF_GET(net_offload_test_impl, 0);
210+
211+
/* Verify iface under test is down before test */
212+
zassert_false(net_if_is_admin_up(test_iface),
213+
"Iface under test must be admin-down before test");
214+
215+
/* Bring iface up. */
216+
(void)net_if_up(test_iface);
217+
218+
/* Verify that a single iface went up once (according to the enable callback) */
219+
zassert_equal(atomic_get(&call_count), 1,
220+
"Bad transition-count, offload_impl_enable not called correctly");
221+
zassert_equal(atomic_get(&up_count), 1,
222+
"Bad up-count, offload_impl_enable not called correctly");
223+
zassert_true(net_if_is_admin_up(test_iface),
224+
"Iface under test should be up after net_if_up");
225+
226+
/* Bring iface down */
227+
(void)net_if_down(test_iface);
228+
229+
/* Verify that a single iface went down once (according to the enable callback)*/
230+
zassert_equal(atomic_get(&call_count), 2,
231+
"Bad transition-count, offload_impl_enable not called correctly");
232+
zassert_equal(atomic_get(&up_count), 0,
233+
"Bad up-count, offload_impl_enable not called correctly");
234+
zassert_false(net_if_is_admin_up(test_iface),
235+
"Iface under test should be down after net_if_down");
236+
}
237+
238+
ZTEST(net_offloaded_netdev, test_up_down_net_off_no_impl)
239+
{
240+
struct net_if *test_iface = NET_IF_GET(net_offload_test_no_impl, 0);
241+
242+
/* Verify iface under test is down before test */
243+
zassert_false(net_if_is_admin_up(test_iface),
244+
"Iface under test must be admin-down before test");
245+
246+
/* Bring iface up */
247+
(void)net_if_up(test_iface);
248+
249+
/* Verify that the iface went up, but callbacks were not fired*/
250+
zassert_equal(atomic_get(&call_count), 0,
251+
"offload_impl_enable was called unexpectedly");
252+
zassert_equal(atomic_get(&up_count), 0,
253+
"offload_impl_enable was called unexpectedly");
254+
zassert_true(net_if_is_admin_up(test_iface),
255+
"Iface under test should be up after net_if_up");
256+
257+
/* Bring iface down */
258+
(void)net_if_down(test_iface);
259+
260+
/* Verify that the iface went down, but callbacks were not fired*/
261+
zassert_equal(atomic_get(&call_count), 0,
262+
"offload_impl_enable was called unexpectedly");
263+
zassert_equal(atomic_get(&up_count), 0,
264+
"offload_impl_enable was called unexpectedly");
265+
zassert_false(net_if_is_admin_up(test_iface),
266+
"Iface under test should be down after net_if_down");
267+
}
268+
269+
ZTEST(net_offloaded_netdev, test_up_down_sock_off_impl_double)
270+
{
271+
struct net_if *test_iface = NET_IF_GET(sock_offload_test_impl, 0);
272+
273+
/* Verify iface under test is down before test */
274+
zassert_false(net_if_is_admin_up(test_iface),
275+
"Iface under test must be admin-down before test");
276+
277+
/* Bring iface up twice */
278+
(void)net_if_up(test_iface);
279+
(void)net_if_up(test_iface);
280+
281+
/* Verify that a single iface went up once (according to the enable callback)*/
282+
zassert_equal(atomic_get(&call_count), 1,
283+
"Bad transition-count, offload_impl_enable not called correctly");
284+
zassert_equal(atomic_get(&up_count), 1,
285+
"Bad up-count, offload_impl_enable not called correctly");
286+
zassert_true(net_if_is_admin_up(test_iface),
287+
"Iface under test should be up after net_if_up");
288+
289+
/* Verify that a single iface went down once (according to the enable callback)*/
290+
(void)net_if_down(test_iface);
291+
(void)net_if_down(test_iface);
292+
293+
/* Verify appropriate calls were made */
294+
zassert_equal(atomic_get(&call_count), 2,
295+
"Bad transition-count, offload_impl_enable not called correctly");
296+
zassert_equal(atomic_get(&up_count), 0,
297+
"Bad up-count, offload_impl_enable not called correctly");
298+
zassert_false(net_if_is_admin_up(test_iface),
299+
"Iface under test should be down after net_if_down");
300+
}
301+
302+
ZTEST(net_offloaded_netdev, test_up_down_sock_off_impl_fail_up)
303+
{
304+
struct net_if *test_iface = NET_IF_GET(sock_offload_test_impl, 0);
305+
306+
/* Verify iface under test is down before test */
307+
zassert_false(net_if_is_admin_up(test_iface),
308+
"Iface under test must be admin-down before test");
309+
310+
/* Instruct the enable callback to fail */
311+
atomic_set(&retval, -E2BIG);
312+
313+
/* Expect net_if_up to fail accordingly */
314+
zassert_equal(net_if_up(test_iface), -E2BIG,
315+
"net_if_up should forward error returned from offload_impl_enabled");
316+
317+
/* Verify that the iface failed to go up */
318+
zassert_false(net_if_is_admin_up(test_iface),
319+
"Iface under test should have failed to go up");
320+
}
321+
322+
ZTEST(net_offloaded_netdev, test_up_down_sock_off_impl_fail_down)
323+
{
324+
struct net_if *test_iface = NET_IF_GET(sock_offload_test_impl, 0);
325+
326+
/* Bring iface up before test */
327+
(void) net_if_up(test_iface);
328+
329+
/* Instruct the enable callback to fail */
330+
atomic_set(&retval, -EADDRINUSE);
331+
332+
333+
/* Expect net_if_down to fail accordingly */
334+
zassert_equal(net_if_down(test_iface), -EADDRINUSE,
335+
"net_if_down should forward error returned from offload_impl_enabled");
336+
337+
/* Verify that the iface failed to go down */
338+
zassert_true(net_if_is_admin_up(test_iface),
339+
"Iface under test should have failed to go up");
340+
}
341+
342+
343+
ZTEST_SUITE(net_offloaded_netdev, NULL, NULL, net_offloaded_netdev_before, NULL, NULL);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
common:
2+
min_ram: 16
3+
depends_on: netif
4+
tests:
5+
net.offloaded_netdev:
6+
tags: net iface userspace

0 commit comments

Comments
 (0)