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