1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2023 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define NET_LOG_LEVEL CONFIG_NET_L2_ETHERNET_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 #include <zephyr/linker/sections.h>
21 #include <zephyr/random/random.h>
22
23 #include <zephyr/ztest.h>
24
25 #include <zephyr/net/net_if.h>
26 #include <zephyr/net/wifi_mgmt.h>
27 #include <zephyr/net/wifi_nm.h>
28
29 #if NET_LOG_LEVEL >= LOG_LEVEL_DBG
30 #define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
31 #else
32 #define DBG(fmt, ...)
33 #endif
34
35 struct wifi_drv_context {
36 struct net_if *iface;
37 uint8_t mac_addr[6];
38 enum ethernet_if_types eth_if_type;
39 };
40
41 static struct wifi_drv_context wifi_context;
42
43 bool wifi_nm_op_called;
44 bool wifi_offload_op_called;
45
wifi_iface_init(struct net_if * iface)46 static void wifi_iface_init(struct net_if *iface)
47 {
48 const struct device *dev = net_if_get_device(iface);
49 struct wifi_drv_context *context = dev->data;
50 struct ethernet_context *eth_ctx = net_if_l2_data(iface);
51
52 net_if_set_link_addr(iface, context->mac_addr,
53 sizeof(context->mac_addr),
54 NET_LINK_ETHERNET);
55
56 eth_ctx->eth_if_type = L2_ETH_IF_TYPE_WIFI;
57
58 ethernet_init(iface);
59 }
60
wifi_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)61 static int wifi_scan(const struct device *dev, struct wifi_scan_params *params,
62 scan_result_cb_t cb)
63 {
64 ARG_UNUSED(dev);
65 ARG_UNUSED(params);
66 ARG_UNUSED(cb);
67
68 wifi_offload_op_called = true;
69
70 return 0;
71 }
72
73 static struct wifi_mgmt_ops wifi_mgmt_api = {
74 .scan = wifi_scan,
75 };
76
77 static struct net_wifi_mgmt_offload api_funcs = {
78 .wifi_iface.iface_api.init = wifi_iface_init,
79 .wifi_mgmt_api = &wifi_mgmt_api,
80 };
81
generate_mac(uint8_t * mac_addr)82 static void generate_mac(uint8_t *mac_addr)
83 {
84 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
85 mac_addr[0] = 0x00;
86 mac_addr[1] = 0x00;
87 mac_addr[2] = 0x5E;
88 mac_addr[3] = 0x00;
89 mac_addr[4] = 0x53;
90 mac_addr[5] = sys_rand8_get();
91 }
92
wifi_init(const struct device * dev)93 static int wifi_init(const struct device *dev)
94 {
95 struct wifi_drv_context *context = dev->data;
96
97 context->eth_if_type = L2_ETH_IF_TYPE_WIFI;
98
99 generate_mac(context->mac_addr);
100
101 return 0;
102 }
103
104 ETH_NET_DEVICE_INIT(wlan0, "wifi_test",
105 wifi_init, NULL,
106 &wifi_context, NULL, CONFIG_ETH_INIT_PRIORITY,
107 &api_funcs, NET_ETH_MTU);
108
wifi_nm_scan(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)109 static int wifi_nm_scan(const struct device *dev, struct wifi_scan_params *params,
110 scan_result_cb_t cb)
111 {
112 ARG_UNUSED(dev);
113 ARG_UNUSED(params);
114 ARG_UNUSED(cb);
115
116 wifi_nm_op_called = true;
117
118 return 0;
119 }
120
121 static struct wifi_mgmt_ops wifi_nm_test_ops = {
122 .scan = wifi_nm_scan,
123 };
124
125 DEFINE_WIFI_NM_INSTANCE(test, &wifi_nm_test_ops);
126
request_scan(void)127 static int request_scan(void)
128 {
129 struct net_if *iface = net_if_get_first_wifi();
130
131 if (net_mgmt(NET_REQUEST_WIFI_SCAN, iface, NULL, 0)) {
132 printk("Scan request failed\n");
133
134 return -ENOEXEC;
135 }
136
137 return 0;
138 }
139
ZTEST(net_wifi,test_wifi_offload)140 ZTEST(net_wifi, test_wifi_offload)
141 {
142
143 int ret;
144 #ifdef CONFIG_WIFI_NM
145 struct wifi_nm_instance *nm = wifi_nm_get_instance("test");
146
147 if (wifi_nm_get_instance_iface(net_if_get_first_wifi())) {
148 ret = wifi_nm_unregister_mgd_iface(nm, net_if_get_first_wifi());
149 zassert_equal(ret, 0, "Failed to unregister managed interface");
150 }
151 #endif /* CONFIG_WIFI_NM */
152
153 ret = request_scan();
154 zassert_equal(ret, 0, "Scan request failed");
155 zassert_true(wifi_offload_op_called, "Scan callback not called");
156 }
157
ZTEST(net_wifi,test_wifi_nm_managed)158 ZTEST(net_wifi, test_wifi_nm_managed)
159 {
160
161 int ret;
162 struct wifi_nm_instance *nm = wifi_nm_get_instance("test");
163
164 zassert_equal(nm->ops, &wifi_nm_test_ops,
165 "Invalid wifi nm ops");
166
167 /* Offload: in presence of registered NM but with no managed
168 * interfaces.
169 */
170 ret = request_scan();
171 zassert_equal(ret, 0, "Scan request failed");
172 zassert_true(wifi_offload_op_called, "Scan callback not called");
173
174 ret = wifi_nm_register_mgd_iface(nm, net_if_get_first_wifi());
175 zassert_equal(ret, 0, "Failed to register managed interface");
176
177 zassert_equal(nm->ops, &wifi_nm_test_ops,
178 "Invalid wifi nm ops");
179
180 ret = request_scan();
181 zassert_equal(ret, 0, "Scan request failed");
182 zassert_true(wifi_nm_op_called, "Scan callback not called");
183 }
184
185
186 ZTEST_SUITE(net_wifi, NULL, NULL, NULL, NULL, NULL);
187