1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2018 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define NET_LOG_LEVEL CONFIG_NET_IF_LOG_LEVEL
10
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(net_test, NET_LOG_LEVEL);
13
14 #include <zephyr/types.h>
15 #include <stdbool.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <zephyr/sys/printk.h>
20
21 #include <zephyr/ztest.h>
22
23 #include <zephyr/net/ethernet.h>
24 #include <zephyr/net/net_ip.h>
25 #include <zephyr/net/net_if.h>
26 #include <zephyr/net/promiscuous.h>
27
28 #define NET_LOG_ENABLED 1
29 #include "net_private.h"
30
31 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
32 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
33 #else
34 #define DBG(fmt, ...)
35 #endif
36
37 /* Interface 1 addresses */
38 static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
40
41 /* Interface 2 addresses */
42 static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 2, 0, 0, 0,
43 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
44
45 /* Interface 3 addresses */
46 static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 3, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
48
49 /* Extra address is assigned to ll_addr */
50 static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
51 0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
52 0x04 } } };
53
54 static struct in6_addr in6addr_mcast = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0x1 } } };
56
57 static struct net_if *iface1;
58 static struct net_if *iface2;
59
60 #define WAIT_TIME 250
61
62 struct net_if_test {
63 uint8_t idx;
64 uint8_t mac_addr[sizeof(struct net_eth_addr)];
65 struct net_linkaddr ll_addr;
66 };
67
68 struct eth_fake_context {
69 struct net_if *iface;
70 uint8_t mac_address[6];
71 bool promisc_mode;
72 };
73
74 static struct eth_fake_context eth_fake_data1;
75 static struct eth_fake_context eth_fake_data2;
76
eth_fake_iface_init(struct net_if * iface)77 static void eth_fake_iface_init(struct net_if *iface)
78 {
79 const struct device *dev = net_if_get_device(iface);
80 struct eth_fake_context *ctx = dev->data;
81
82 ctx->iface = iface;
83
84 net_if_set_link_addr(iface, ctx->mac_address,
85 sizeof(ctx->mac_address),
86 NET_LINK_ETHERNET);
87
88 ethernet_init(iface);
89 }
90
eth_fake_send(const struct device * dev,struct net_pkt * pkt)91 static int eth_fake_send(const struct device *dev,
92 struct net_pkt *pkt)
93 {
94 ARG_UNUSED(dev);
95 ARG_UNUSED(pkt);
96
97 return 0;
98 }
99
eth_fake_get_capabilities(const struct device * dev)100 static enum ethernet_hw_caps eth_fake_get_capabilities(const struct device *dev)
101 {
102 return ETHERNET_PROMISC_MODE;
103 }
104
eth_fake_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)105 static int eth_fake_set_config(const struct device *dev,
106 enum ethernet_config_type type,
107 const struct ethernet_config *config)
108 {
109 struct eth_fake_context *ctx = dev->data;
110
111 switch (type) {
112 case ETHERNET_CONFIG_TYPE_PROMISC_MODE:
113 if (config->promisc_mode == ctx->promisc_mode) {
114 return -EALREADY;
115 }
116
117 ctx->promisc_mode = config->promisc_mode;
118
119 break;
120
121 default:
122 return -EINVAL;
123 }
124
125 return 0;
126 }
127
128 static struct ethernet_api eth_fake_api_funcs = {
129 .iface_api.init = eth_fake_iface_init,
130
131 .get_capabilities = eth_fake_get_capabilities,
132 .set_config = eth_fake_set_config,
133 .send = eth_fake_send,
134 };
135
eth_fake_init(const struct device * dev)136 static int eth_fake_init(const struct device *dev)
137 {
138 struct eth_fake_context *ctx = dev->data;
139
140 ctx->promisc_mode = false;
141
142 return 0;
143 }
144
145 ETH_NET_DEVICE_INIT(eth_fake1, "eth_fake1",
146 eth_fake_init, NULL,
147 ð_fake_data1, NULL, CONFIG_ETH_INIT_PRIORITY,
148 ð_fake_api_funcs, NET_ETH_MTU);
149
150 ETH_NET_DEVICE_INIT(eth_fake2, "eth_fake2",
151 eth_fake_init, NULL,
152 ð_fake_data2, NULL, CONFIG_ETH_INIT_PRIORITY,
153 ð_fake_api_funcs, NET_ETH_MTU);
154
155 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
iface2str(struct net_if * iface)156 static const char *iface2str(struct net_if *iface)
157 {
158 if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
159 return "Ethernet";
160 }
161
162 if (net_if_l2(iface) == &NET_L2_GET_NAME(DUMMY)) {
163 return "Dummy";
164 }
165
166 return "<unknown type>";
167 }
168 #endif
169
iface_cb(struct net_if * iface,void * user_data)170 static void iface_cb(struct net_if *iface, void *user_data)
171 {
172 static int if_count;
173
174 DBG("Interface %p (%s) [%d]\n", iface, iface2str(iface),
175 net_if_get_by_iface(iface));
176
177 if (net_if_l2(iface) == &NET_L2_GET_NAME(ETHERNET)) {
178 const struct ethernet_api *api =
179 net_if_get_device(iface)->api;
180
181 /* As native_sim board will introduce another ethernet
182 * interface, make sure that we only use our own in this test.
183 */
184 if (api->get_capabilities ==
185 eth_fake_api_funcs.get_capabilities) {
186 switch (if_count) {
187 case 0:
188 iface1 = iface;
189 break;
190 case 1:
191 iface2 = iface;
192 break;
193 }
194
195 if_count++;
196 }
197 }
198 }
199
test_iface_setup(void)200 static void test_iface_setup(void)
201 {
202 struct net_if_mcast_addr *maddr;
203 struct net_if_addr *ifaddr;
204 int idx;
205
206 net_if_foreach(iface_cb, NULL);
207
208 idx = net_if_get_by_iface(iface1);
209 ((struct net_if_test *)
210 net_if_get_device(iface1)->data)->idx = idx;
211
212 idx = net_if_get_by_iface(iface2);
213 ((struct net_if_test *)
214 net_if_get_device(iface2)->data)->idx = idx;
215
216 zassert_not_null(iface1, "Interface 1");
217 zassert_not_null(iface2, "Interface 2");
218
219 DBG("Interfaces: [%d] iface1 %p, [%d] iface2 %p\n",
220 net_if_get_by_iface(iface1), iface1,
221 net_if_get_by_iface(iface2), iface2);
222
223 ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
224 NET_ADDR_MANUAL, 0);
225 if (!ifaddr) {
226 DBG("Cannot add IPv6 address %s\n",
227 net_sprint_ipv6_addr(&my_addr1));
228 zassert_not_null(ifaddr, "addr1");
229 }
230
231 /* For testing purposes we need to set the addresses preferred */
232 ifaddr->addr_state = NET_ADDR_PREFERRED;
233
234 ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
235 NET_ADDR_MANUAL, 0);
236 if (!ifaddr) {
237 DBG("Cannot add IPv6 address %s\n",
238 net_sprint_ipv6_addr(&ll_addr));
239 zassert_not_null(ifaddr, "ll_addr");
240 }
241
242 ifaddr->addr_state = NET_ADDR_PREFERRED;
243
244 ifaddr = net_if_ipv6_addr_add(iface2, &my_addr2,
245 NET_ADDR_MANUAL, 0);
246 if (!ifaddr) {
247 DBG("Cannot add IPv6 address %s\n",
248 net_sprint_ipv6_addr(&my_addr2));
249 zassert_not_null(ifaddr, "addr2");
250 }
251
252 ifaddr->addr_state = NET_ADDR_PREFERRED;
253
254 ifaddr = net_if_ipv6_addr_add(iface2, &my_addr3,
255 NET_ADDR_MANUAL, 0);
256 if (!ifaddr) {
257 DBG("Cannot add IPv6 address %s\n",
258 net_sprint_ipv6_addr(&my_addr3));
259 zassert_not_null(ifaddr, "addr3");
260 }
261
262 ifaddr->addr_state = NET_ADDR_PREFERRED;
263
264 net_ipv6_addr_create(&in6addr_mcast, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
265
266 maddr = net_if_ipv6_maddr_add(iface1, &in6addr_mcast);
267 if (!maddr) {
268 DBG("Cannot add multicast IPv6 address %s\n",
269 net_sprint_ipv6_addr(&in6addr_mcast));
270 zassert_not_null(maddr, "mcast");
271 }
272
273 net_if_up(iface1);
274 net_if_up(iface2);
275 }
276
_set_promisc_mode_on_again(struct net_if * iface)277 static void _set_promisc_mode_on_again(struct net_if *iface)
278 {
279 int ret;
280
281 DBG("Make sure promiscuous mode is ON (%p)\n", iface);
282
283 ret = net_promisc_mode_on(iface);
284
285 zassert_equal(ret, -EALREADY, "iface %p promiscuous mode ON", iface);
286 }
287
_set_promisc_mode_on(struct net_if * iface)288 static void _set_promisc_mode_on(struct net_if *iface)
289 {
290 bool ret;
291
292 DBG("Setting promiscuous mode ON (%p)\n", iface);
293
294 ret = net_promisc_mode_on(iface);
295
296 zassert_equal(ret, 0, "iface %p promiscuous mode set ON failed",
297 iface);
298 }
299
_set_promisc_mode_off_again(struct net_if * iface)300 static void _set_promisc_mode_off_again(struct net_if *iface)
301 {
302 int ret;
303
304 DBG("Make sure promiscuous mode is OFF (%p)\n", iface);
305
306 ret = net_promisc_mode_off(iface);
307
308 zassert_equal(ret, -EALREADY, "iface %p promiscuous mode OFF", iface);
309 }
310
_set_promisc_mode_off(struct net_if * iface)311 static void _set_promisc_mode_off(struct net_if *iface)
312 {
313 int ret;
314
315 DBG("Setting promiscuous mode OFF (%p)\n", iface);
316
317 ret = net_promisc_mode_off(iface);
318
319 zassert_equal(ret, 0, "iface %p promiscuous mode set OFF failed",
320 iface);
321 }
322
test_set_promisc_mode_on_again(void)323 static void test_set_promisc_mode_on_again(void)
324 {
325 _set_promisc_mode_on_again(iface1);
326 _set_promisc_mode_on_again(iface2);
327 }
328
test_set_promisc_mode_on(void)329 static void test_set_promisc_mode_on(void)
330 {
331 _set_promisc_mode_on(iface1);
332 _set_promisc_mode_on(iface2);
333 }
334
test_set_promisc_mode_off_again(void)335 static void test_set_promisc_mode_off_again(void)
336 {
337 _set_promisc_mode_off_again(iface1);
338 _set_promisc_mode_off_again(iface2);
339 }
340
test_set_promisc_mode_off(void)341 static void test_set_promisc_mode_off(void)
342 {
343 _set_promisc_mode_off(iface1);
344 _set_promisc_mode_off(iface2);
345 }
346
_recv_data(struct net_if * iface,struct net_pkt ** pkt)347 static void _recv_data(struct net_if *iface, struct net_pkt **pkt)
348 {
349 static uint8_t data[] = { 't', 'e', 's', 't', '\0' };
350 int ret;
351
352 *pkt = net_pkt_rx_alloc_with_buffer(iface, sizeof(data),
353 AF_UNSPEC, 0, K_FOREVER);
354
355 net_pkt_ref(*pkt);
356
357 net_pkt_write(*pkt, data, sizeof(data));
358
359 ret = net_recv_data(iface, *pkt);
360 zassert_equal(ret, 0, "Data receive failure");
361 }
362
363 static struct net_pkt *pkt1;
364 static struct net_pkt *pkt2;
365
test_recv_data(void)366 static void test_recv_data(void)
367 {
368 _recv_data(iface1, &pkt1);
369 _recv_data(iface2, &pkt2);
370 }
371
test_verify_data(void)372 static void test_verify_data(void)
373 {
374 struct net_pkt *pkt;
375
376 pkt = net_promisc_mode_wait_data(K_SECONDS(1));
377 zassert_not_null(pkt, "pkt");
378 zassert_not_null(pkt->buffer, "pkt->buffer");
379 zassert_not_null(pkt1, "pkt1");
380 zassert_not_null(pkt1->buffer, "pkt1->buffer");
381 zassert_equal(pkt->buffer->len, pkt1->buffer->len, "packet length differs");
382 zassert_not_null(pkt->buffer->data, "pkt->buffer->data");
383 zassert_not_null(pkt1->buffer->data, "pkt1->buffer->data");
384 zassert_mem_equal(pkt->buffer->data, pkt1->buffer->data, pkt1->buffer->len);
385 net_pkt_unref(pkt);
386
387 pkt = net_promisc_mode_wait_data(K_SECONDS(1));
388 zassert_not_null(pkt, "pkt");
389 zassert_not_null(pkt->buffer, "pkt->buffer");
390 zassert_not_null(pkt2, "pkt2");
391 zassert_not_null(pkt2->buffer, "pkt2->buffer");
392 zassert_equal(pkt->buffer->len, pkt2->buffer->len, "packet length differs");
393 zassert_not_null(pkt->buffer->data, "pkt->buffer->data");
394 zassert_not_null(pkt2->buffer->data, "pkt2->buffer->data");
395 zassert_mem_equal(pkt->buffer->data, pkt2->buffer->data, pkt2->buffer->len);
396 net_pkt_unref(pkt);
397 }
398
ZTEST(net_promisc_test_suite,test_net_promisc)399 ZTEST(net_promisc_test_suite, test_net_promisc)
400 {
401 test_iface_setup();
402 test_set_promisc_mode_on();
403 test_set_promisc_mode_on_again();
404 test_recv_data();
405 test_verify_data();
406 test_set_promisc_mode_off();
407 test_set_promisc_mode_off_again();
408 }
409
410 ZTEST_SUITE(net_promisc_test_suite, NULL, NULL, NULL, NULL, NULL);
411