1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <logging/log.h>
8 LOG_MODULE_REGISTER(net_ieee802154_test, LOG_LEVEL_DBG);
9
10 #include <zephyr.h>
11 #include <ztest.h>
12
13 #include <net/net_core.h>
14 #include "net_private.h"
15
16 #include <net/net_ip.h>
17 #include <net/net_pkt.h>
18
19 #include <ieee802154_frame.h>
20 #include <ipv6.h>
21
22 struct ieee802154_pkt_test {
23 char *name;
24 struct in6_addr src;
25 struct in6_addr dst;
26 uint8_t *pkt;
27 uint8_t length;
28 struct {
29 struct ieee802154_fcf_seq *fc_seq;
30 struct ieee802154_address_field *dst_addr;
31 struct ieee802154_address_field *src_addr;
32 } mhr_check;
33 };
34
35 uint8_t ns_pkt[] = {
36 0x41, 0xd8, 0x3e, 0xcd, 0xab, 0xff, 0xff, 0xc2, 0xa3, 0x9e, 0x00,
37 0x00, 0x4b, 0x12, 0x00, 0x7b, 0x09, 0x3a, 0x20, 0x01, 0x0d, 0xb8,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 0x02, 0x02, 0x01, 0xff, 0x00, 0x00, 0x01, 0x87, 0x00, 0x2e, 0xad,
40 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
42 0x00, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x3d, 0x74
44 };
45
46 struct ieee802154_pkt_test test_ns_pkt = {
47 .name = "NS frame",
48 .src = { { { 0x20, 0x01, 0xdb, 0x08, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } },
50 .dst = { { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x01 } } },
52 .pkt = ns_pkt,
53 .length = sizeof(ns_pkt),
54 .mhr_check.fc_seq = (struct ieee802154_fcf_seq *)ns_pkt,
55 .mhr_check.dst_addr = (struct ieee802154_address_field *)(ns_pkt + 3),
56 .mhr_check.src_addr = (struct ieee802154_address_field *)(ns_pkt + 7),
57 };
58
59 uint8_t ack_pkt[] = { 0x02, 0x10, 0x16 };
60
61 struct ieee802154_pkt_test test_ack_pkt = {
62 .name = "ACK frame",
63 .pkt = ack_pkt,
64 .length = sizeof(ack_pkt),
65 .mhr_check.fc_seq = (struct ieee802154_fcf_seq *)ack_pkt,
66 .mhr_check.dst_addr = NULL,
67 .mhr_check.src_addr = NULL,
68 };
69
70 uint8_t beacon_pkt[] = {
71 0x00, 0xd0, 0x11, 0xcd, 0xab, 0xc2, 0xa3, 0x9e, 0x00, 0x00, 0x4b,
72 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
73 };
74
75 struct ieee802154_pkt_test test_beacon_pkt = {
76 .name = "Empty beacon frame",
77 .pkt = beacon_pkt,
78 .length = sizeof(beacon_pkt),
79 .mhr_check.fc_seq = (struct ieee802154_fcf_seq *)beacon_pkt,
80 .mhr_check.dst_addr = NULL,
81 .mhr_check.src_addr =
82 (struct ieee802154_address_field *) (beacon_pkt + 3),
83 };
84
85 uint8_t sec_data_pkt[] = {
86 0x49, 0xd8, 0x03, 0xcd, 0xab, 0xff, 0xff, 0x02, 0x6d, 0xbb, 0xa7,
87 0x00, 0x4b, 0x12, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x8e,
88 0x49, 0xa7, 0xe2, 0x00, 0x67, 0xd4, 0x00, 0x42, 0x52, 0x6f, 0x01,
89 0x02, 0x00, 0x12, 0x4b, 0x00, 0xa7, 0xbb, 0x6d, 0x02, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x19, 0x7f, 0x91, 0xcf, 0x73, 0xf0
91 };
92
93 struct ieee802154_pkt_test test_sec_data_pkt = {
94 .name = "Secured data frame",
95 .pkt = sec_data_pkt,
96 .length = sizeof(sec_data_pkt),
97 .mhr_check.fc_seq = (struct ieee802154_fcf_seq *)sec_data_pkt,
98 .mhr_check.dst_addr =
99 (struct ieee802154_address_field *)(sec_data_pkt + 3),
100 .mhr_check.src_addr =
101 (struct ieee802154_address_field *)(sec_data_pkt + 7),
102 };
103
104 struct net_pkt *current_pkt;
105 struct net_if *iface;
106 K_SEM_DEFINE(driver_lock, 0, UINT_MAX);
107
pkt_hexdump(uint8_t * pkt,uint8_t length)108 static void pkt_hexdump(uint8_t *pkt, uint8_t length)
109 {
110 int i;
111
112 printk(" -> Packet content:\n");
113
114 for (i = 0; i < length;) {
115 int j;
116
117 printk("\t");
118
119 for (j = 0; j < 10 && i < length; j++, i++) {
120 printk("%02x ", *pkt);
121 pkt++;
122 }
123
124 printk("\n");
125 }
126 }
127
ieee_addr_hexdump(uint8_t * addr,uint8_t length)128 static void ieee_addr_hexdump(uint8_t *addr, uint8_t length)
129 {
130 int i;
131
132 printk(" -> IEEE 802.15.4 Address: ");
133
134 for (i = 0; i < length-1; i++) {
135 printk("%02x:", *addr);
136 addr++;
137 }
138
139 printk("%02x\n", *addr);
140 }
141
test_packet_parsing(struct ieee802154_pkt_test * t)142 static bool test_packet_parsing(struct ieee802154_pkt_test *t)
143 {
144 struct ieee802154_mpdu mpdu;
145
146 NET_INFO("- Parsing packet 0x%p of frame %s\n", t->pkt, t->name);
147
148 if (!ieee802154_validate_frame(t->pkt, t->length, &mpdu)) {
149 NET_ERR("*** Could not validate frame %s\n", t->name);
150 return false;
151 }
152
153 if (mpdu.mhr.fs != t->mhr_check.fc_seq ||
154 mpdu.mhr.dst_addr != t->mhr_check.dst_addr ||
155 mpdu.mhr.src_addr != t->mhr_check.src_addr) {
156 NET_INFO("d: %p vs %p -- s: %p vs %p\n",
157 mpdu.mhr.dst_addr, t->mhr_check.dst_addr,
158 mpdu.mhr.src_addr, t->mhr_check.src_addr);
159 NET_ERR("*** Wrong MPDU information on frame %s\n",
160 t->name);
161
162 return false;
163 }
164
165 return true;
166 }
167
test_ns_sending(struct ieee802154_pkt_test * t)168 static bool test_ns_sending(struct ieee802154_pkt_test *t)
169 {
170 struct ieee802154_mpdu mpdu;
171
172 NET_INFO("- Sending NS packet\n");
173
174 if (net_ipv6_send_ns(iface, NULL, &t->src, &t->dst, &t->dst, false)) {
175 NET_ERR("*** Could not create IPv6 NS packet\n");
176 return false;
177 }
178
179 k_yield();
180 k_sem_take(&driver_lock, K_SECONDS(1));
181
182 if (!current_pkt->frags) {
183 NET_ERR("*** Could not send IPv6 NS packet\n");
184 return false;
185 }
186
187 pkt_hexdump(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt));
188
189 if (!ieee802154_validate_frame(net_pkt_data(current_pkt),
190 net_pkt_get_len(current_pkt), &mpdu)) {
191 NET_ERR("*** Sent packet is not valid\n");
192 net_pkt_unref(current_pkt);
193
194 return false;
195 }
196
197 net_pkt_frag_unref(current_pkt->frags);
198 current_pkt->frags = NULL;
199
200 return true;
201 }
202
test_ack_reply(struct ieee802154_pkt_test * t)203 static bool test_ack_reply(struct ieee802154_pkt_test *t)
204 {
205 static uint8_t data_pkt[] = {
206 0x61, 0xdc, 0x16, 0xcd, 0xab, 0xc2, 0xa3, 0x9e, 0x00, 0x00, 0x4b,
207 0x12, 0x00, 0x26, 0x18, 0x32, 0x00, 0x00, 0x4b, 0x12, 0x00, 0x7b,
208 0x00, 0x3a, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x0d, 0xb8,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x02, 0x87, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01,
212 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
213 0x16, 0xf0, 0x02, 0xff, 0x16, 0xf0, 0x12, 0xff, 0x16, 0xf0, 0x32,
214 0xff, 0x16, 0xf0, 0x00, 0xff, 0x16, 0xf0, 0x00, 0xff, 0x16
215 };
216 struct ieee802154_mpdu mpdu;
217 struct net_pkt *pkt;
218 struct net_buf *frag;
219
220 NET_INFO("- Sending ACK reply to a data packet\n");
221
222 pkt = net_pkt_rx_alloc(K_FOREVER);
223 frag = net_pkt_get_frag(pkt, K_FOREVER);
224
225 memcpy(frag->data, data_pkt, sizeof(data_pkt));
226 frag->len = sizeof(data_pkt);
227
228 net_pkt_frag_add(pkt, frag);
229
230 if (net_recv_data(iface, pkt) < 0) {
231 NET_ERR("Recv data failed");
232 return false;
233 }
234
235 k_yield();
236 k_sem_take(&driver_lock, K_SECONDS(1));
237
238 /* an ACK packet should be in current_pkt */
239 if (!current_pkt->frags) {
240 NET_ERR("*** No ACK reply sent\n");
241 return false;
242 }
243
244 pkt_hexdump(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt));
245
246 if (!ieee802154_validate_frame(net_pkt_data(current_pkt),
247 net_pkt_get_len(current_pkt), &mpdu)) {
248 NET_ERR("*** ACK Reply is invalid\n");
249 return false;
250 }
251
252 if (memcmp(mpdu.mhr.fs, t->mhr_check.fc_seq,
253 sizeof(struct ieee802154_fcf_seq))) {
254 NET_ERR("*** ACK Reply does not compare\n");
255 return false;
256 }
257
258 net_pkt_frag_unref(current_pkt->frags);
259 current_pkt->frags = NULL;
260
261 return true;
262 }
263
initialize_test_environment(void)264 static bool initialize_test_environment(void)
265 {
266 const struct device *dev;
267
268 k_sem_reset(&driver_lock);
269
270 current_pkt = net_pkt_rx_alloc(K_FOREVER);
271 if (!current_pkt) {
272 NET_ERR("*** No buffer to allocate\n");
273 return false;
274 }
275
276 dev = device_get_binding("fake_ieee802154");
277 if (!dev) {
278 NET_ERR("*** Could not get fake device\n");
279 return false;
280 }
281
282 iface = net_if_lookup_by_dev(dev);
283 if (!iface) {
284 NET_ERR("*** Could not get fake iface\n");
285 return false;
286 }
287
288 NET_INFO("Fake IEEE 802.15.4 network interface ready\n");
289
290 ieee_addr_hexdump(net_if_get_link_addr(iface)->addr, 8);
291
292 return true;
293 }
294
test_init(void)295 static void test_init(void)
296 {
297 bool ret;
298
299 ret = initialize_test_environment();
300
301 zassert_true(ret, "Test initialization");
302 }
303
304
test_parsing_ns_pkt(void)305 static void test_parsing_ns_pkt(void)
306 {
307 bool ret;
308
309 ret = test_packet_parsing(&test_ns_pkt);
310
311 zassert_true(ret, "NS parsed");
312 }
313
test_sending_ns_pkt(void)314 static void test_sending_ns_pkt(void)
315 {
316 bool ret;
317
318 ret = test_ns_sending(&test_ns_pkt);
319
320 zassert_true(ret, "NS sent");
321 }
322
test_parsing_ack_pkt(void)323 static void test_parsing_ack_pkt(void)
324 {
325 bool ret;
326
327 ret = test_packet_parsing(&test_ack_pkt);
328
329 zassert_true(ret, "ACK parsed");
330 }
331
test_replying_ack_pkt(void)332 static void test_replying_ack_pkt(void)
333 {
334 bool ret;
335
336 ret = test_ack_reply(&test_ack_pkt);
337
338 zassert_true(ret, "ACK replied");
339 }
340
test_parsing_beacon_pkt(void)341 static void test_parsing_beacon_pkt(void)
342 {
343 bool ret;
344
345 ret = test_packet_parsing(&test_beacon_pkt);
346
347 zassert_true(ret, "Beacon parsed");
348 }
349
test_parsing_sec_data_pkt(void)350 static void test_parsing_sec_data_pkt(void)
351 {
352 bool ret;
353
354 ret = test_packet_parsing(&test_sec_data_pkt);
355
356 zassert_true(ret, "Secured data frame parsed");
357 }
358
test_main(void)359 void test_main(void)
360 {
361 ztest_test_suite(ieee802154_l2,
362 ztest_unit_test(test_init),
363 ztest_unit_test(test_parsing_ns_pkt),
364 ztest_unit_test(test_sending_ns_pkt),
365 ztest_unit_test(test_parsing_ack_pkt),
366 ztest_unit_test(test_replying_ack_pkt),
367 ztest_unit_test(test_parsing_beacon_pkt),
368 ztest_unit_test(test_parsing_sec_data_pkt)
369 );
370
371 ztest_run_test_suite(ieee802154_l2);
372 }
373