1 /*
2  * Copyright (c) 2019 Alexander Wachter.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <logging/log.h>
8 LOG_MODULE_REGISTER(net_l2_canbus, CONFIG_NET_L2_CANBUS_LOG_LEVEL);
9 
10 #include <net/net_core.h>
11 #include <net/net_l2.h>
12 #include <net/net_if.h>
13 #include <net/capture.h>
14 #include <net/net_pkt.h>
15 #include <net/can.h>
16 #include "canbus_internal.h"
17 #include <6lo.h>
18 #include <timeout_q.h>
19 #include <string.h>
20 #include <sys/byteorder.h>
21 #include <net/ethernet.h>
22 #include <net/net_ip.h>
23 #include <string.h>
24 #include <random/rand32.h>
25 
26 #define NET_CAN_WFTMAX 2
27 #define NET_CAN_ALLOC_TIMEOUT K_MSEC(100)
28 
29 /* Minimal separation time betwee frames */
30 #define NET_CAN_STMIN CONFIG_NET_L2_CANBUS_STMIN
31 #define NET_CAN_BS CONFIG_NET_L2_CANBUS_BS
32 
33 #define NET_CAN_DAD_SEND_RETRY 5
34 #define NET_CAN_DAD_TIMEOUT K_MSEC(100)
35 
36 extern uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto);
37 
38 static struct canbus_l2_ctx l2_ctx;
39 
40 static struct k_work_q net_canbus_workq;
41 K_KERNEL_STACK_DEFINE(net_canbus_stack, 512);
42 
43 char *net_sprint_addr(sa_family_t af, const void *addr);
44 
45 #if CONFIG_NET_L2_CANBUS_LOG_LEVEL >= LOG_LEVEL_DBG
canbus_print_ip_hdr(struct net_ipv6_hdr * ip_hdr)46 static void canbus_print_ip_hdr(struct net_ipv6_hdr *ip_hdr)
47 {
48 	uint8_t version = (ip_hdr->vtc >> 4);
49 	uint8_t tc = ((ip_hdr->vtc & 0x0F) << 4) | ((ip_hdr->tcflow & 0xF0 >> 4));
50 	uint32_t flow = ((ip_hdr->tcflow & 0x0F) << 16) | ip_hdr->flow;
51 
52 	NET_DBG("IP header: Version: 0x%x, TC: 0x%x, Flow Label: 0x%x, "
53 		"Payload Length: %u, Next Header: 0x%x, Hop Limit: %u, "
54 		"Src: %s, Dest: %s",
55 		version, tc, flow, ntohs(ip_hdr->len), ip_hdr->nexthdr,
56 		ip_hdr->hop_limit,
57 		log_strdup(net_sprint_addr(AF_INET6, &ip_hdr->src)),
58 		log_strdup(net_sprint_addr(AF_INET6, &ip_hdr->dst)));
59 }
60 #else
61 #define canbus_print_ip_hdr(...)
62 #endif
63 
canbus_free_tx_ctx(struct canbus_isotp_tx_ctx * ctx)64 static void canbus_free_tx_ctx(struct canbus_isotp_tx_ctx *ctx)
65 {
66 	k_mutex_lock(&l2_ctx.tx_ctx_mtx, K_FOREVER);
67 	ctx->state = NET_CAN_TX_STATE_UNUSED;
68 	k_mutex_unlock(&l2_ctx.tx_ctx_mtx);
69 }
70 
canbus_free_rx_ctx(struct canbus_isotp_rx_ctx * ctx)71 static void canbus_free_rx_ctx(struct canbus_isotp_rx_ctx *ctx)
72 {
73 	k_mutex_lock(&l2_ctx.rx_ctx_mtx, K_FOREVER);
74 	ctx->state = NET_CAN_RX_STATE_UNUSED;
75 	k_mutex_unlock(&l2_ctx.rx_ctx_mtx);
76 }
77 
canbus_tx_finish(struct net_pkt * pkt)78 static void canbus_tx_finish(struct net_pkt *pkt)
79 {
80 	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
81 
82 	if (ctx->state != NET_CAN_TX_STATE_RESET) {
83 		z_abort_timeout(&ctx->timeout);
84 	}
85 
86 	canbus_free_tx_ctx(ctx);
87 	net_pkt_unref(pkt);
88 	k_sem_give(&l2_ctx.tx_sem);
89 }
90 
canbus_rx_finish(struct net_pkt * pkt)91 static void canbus_rx_finish(struct net_pkt *pkt)
92 {
93 	struct canbus_isotp_rx_ctx *ctx = pkt->canbus_rx_ctx;
94 
95 	canbus_free_rx_ctx(ctx);
96 }
97 
canbus_tx_report_err(struct net_pkt * pkt)98 static void canbus_tx_report_err(struct net_pkt *pkt)
99 {
100 	canbus_tx_finish(pkt);
101 }
102 
canbus_rx_report_err(struct net_pkt * pkt)103 static void canbus_rx_report_err(struct net_pkt *pkt)
104 {
105 	canbus_rx_finish(pkt);
106 	net_pkt_unref(pkt);
107 }
108 
rx_err_work_handler(struct net_pkt * pkt)109 static void rx_err_work_handler(struct net_pkt *pkt)
110 {
111 	canbus_rx_report_err(pkt);
112 }
113 
submit_to_queue(struct k_fifo * queue,struct net_pkt * pkt)114 static void submit_to_queue(struct k_fifo *queue, struct net_pkt *pkt)
115 {
116 	k_fifo_put(queue, pkt);
117 }
118 
canbus_rx_report_err_from_isr(struct k_fifo * queue,struct net_pkt * pkt)119 static void canbus_rx_report_err_from_isr(struct k_fifo *queue,
120 					  struct net_pkt *pkt)
121 {
122 	submit_to_queue(queue, pkt);
123 }
124 
canbus_tx_timeout(struct _timeout * t)125 static void canbus_tx_timeout(struct _timeout *t)
126 {
127 	struct canbus_isotp_tx_ctx *ctx =
128 		CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout);
129 	struct net_if *iface = net_pkt_iface(ctx->pkt);
130 	struct canbus_net_ctx *net_ctx = net_if_l2_data(iface);
131 
132 	NET_ERR("TX Timeout. CTX: %p", ctx);
133 	ctx->state = NET_CAN_TX_STATE_ERR;
134 
135 	submit_to_queue(&net_ctx->tx_queue, ctx->pkt);
136 }
137 
canbus_rx_timeout(struct _timeout * t)138 static void canbus_rx_timeout(struct _timeout *t)
139 {
140 	struct canbus_isotp_rx_ctx *ctx =
141 		CONTAINER_OF(t, struct canbus_isotp_rx_ctx, timeout);
142 	struct net_if *iface = net_pkt_iface(ctx->pkt);
143 	struct canbus_net_ctx *net_ctx = net_if_l2_data(iface);
144 
145 	NET_ERR("RX Timeout. CTX: %p", ctx);
146 	ctx->state = NET_CAN_RX_STATE_TIMEOUT;
147 	canbus_rx_report_err_from_isr(&net_ctx->rx_err_queue, ctx->pkt);
148 }
149 
canbus_st_min_timeout(struct _timeout * t)150 static void canbus_st_min_timeout(struct _timeout *t)
151 {
152 	struct canbus_isotp_tx_ctx *ctx =
153 		CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout);
154 	struct net_if *iface = net_pkt_iface(ctx->pkt);
155 	struct canbus_net_ctx *net_ctx = net_if_l2_data(iface);
156 
157 	submit_to_queue(&net_ctx->tx_queue, ctx->pkt);
158 }
159 
canbus_stmin_to_ticks(uint8_t stmin)160 static k_timeout_t canbus_stmin_to_ticks(uint8_t stmin)
161 {
162 	/* According to ISO 15765-2 stmin should be 127ms if value is corrupt */
163 	if (stmin > NET_CAN_STMIN_MAX ||
164 	    (stmin > NET_CAN_STMIN_MS_MAX && stmin < NET_CAN_STMIN_US_BEGIN)) {
165 		return K_MSEC(NET_CAN_STMIN_MS_MAX);
166 	} else if (stmin >= NET_CAN_STMIN_US_BEGIN) {
167 		return K_USEC((stmin + 1 - NET_CAN_STMIN_US_BEGIN) * 100U);
168 	}
169 
170 	return K_MSEC(stmin);
171 }
172 
canbus_get_lladdr(struct net_linkaddr * net_lladdr)173 static uint16_t canbus_get_lladdr(struct net_linkaddr *net_lladdr)
174 {
175 	NET_ASSERT(net_lladdr->len == sizeof(uint16_t));
176 
177 	return sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)net_lladdr->addr));
178 }
179 
canbus_get_src_lladdr(struct net_pkt * pkt)180 static uint16_t canbus_get_src_lladdr(struct net_pkt *pkt)
181 {
182 	return net_pkt_lladdr_src(pkt)->type == NET_LINK_CANBUS ?
183 	       canbus_get_lladdr(net_pkt_lladdr_src(pkt)) :
184 	       NET_CAN_ETH_TRANSLATOR_ADDR;
185 }
186 
canbus_get_dest_lladdr(struct net_pkt * pkt)187 static uint16_t canbus_get_dest_lladdr(struct net_pkt *pkt)
188 {
189 	return net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS &&
190 	       net_pkt_lladdr_dst(pkt)->len == sizeof(struct net_canbus_lladdr) ?
191 	       canbus_get_lladdr(net_pkt_lladdr_dst(pkt)) :
192 	       NET_CAN_ETH_TRANSLATOR_ADDR;
193 }
194 
canbus_dest_is_mcast(struct net_pkt * pkt)195 static inline bool canbus_dest_is_mcast(struct net_pkt *pkt)
196 {
197 	uint16_t lladdr_be = UNALIGNED_GET((uint16_t *)net_pkt_lladdr_dst(pkt)->addr);
198 
199 	return (sys_be16_to_cpu(lladdr_be) & CAN_NET_IF_IS_MCAST_BIT);
200 }
201 
canbus_src_is_translator(struct net_pkt * pkt)202 static bool canbus_src_is_translator(struct net_pkt *pkt)
203 {
204 	return ((canbus_get_src_lladdr(pkt) & CAN_NET_IF_ADDR_MASK) ==
205 		NET_CAN_ETH_TRANSLATOR_ADDR);
206 }
207 
canbus_dest_is_translator(struct net_pkt * pkt)208 static bool canbus_dest_is_translator(struct net_pkt *pkt)
209 {
210 	return (net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET ||
211 		net_pkt_lladdr_dst(pkt)->len == sizeof(struct net_eth_addr));
212 }
213 
214 #if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
canbus_is_for_translator(struct net_pkt * pkt)215 static bool canbus_is_for_translator(struct net_pkt *pkt)
216 {
217 	return ((net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS) &&
218 		(canbus_get_lladdr(net_pkt_lladdr_dst(pkt)) ==
219 		 NET_CAN_ETH_TRANSLATOR_ADDR));
220 }
221 #else
222 #define canbus_is_for_translator(...) false
223 #endif /* CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR */
224 
canbus_total_lladdr_len(struct net_pkt * pkt)225 static size_t canbus_total_lladdr_len(struct net_pkt *pkt)
226 {
227 	/* This pkt will be farowarded to Ethernet
228 	 * Destination MAC is carried inline, source is going to be extended
229 	 */
230 	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
231 	    canbus_is_for_translator(pkt)) {
232 		return sizeof(struct net_eth_addr) +
233 		       sizeof(struct net_canbus_lladdr);
234 	}
235 
236 	return 2U * sizeof(struct net_canbus_lladdr);
237 }
238 
canbus_cpy_lladdr(struct net_pkt * dst,struct net_pkt * src)239 static inline void canbus_cpy_lladdr(struct net_pkt *dst, struct net_pkt *src)
240 {
241 	struct net_linkaddr *lladdr;
242 
243 	lladdr = net_pkt_lladdr_dst(dst);
244 	lladdr->addr = net_pkt_cursor_get_pos(dst);
245 	net_pkt_write(dst, net_pkt_lladdr_dst(src)->addr,
246 		      sizeof(struct net_canbus_lladdr));
247 	lladdr->len = sizeof(struct net_canbus_lladdr);
248 	lladdr->type = NET_LINK_CANBUS;
249 
250 	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
251 	    canbus_is_for_translator(src)) {
252 		/* Make room for address extension */
253 		net_pkt_skip(dst, sizeof(struct net_eth_addr) -
254 			     sizeof(struct net_canbus_lladdr));
255 	}
256 
257 	lladdr = net_pkt_lladdr_src(dst);
258 	lladdr->addr = net_pkt_cursor_get_pos(dst);
259 
260 	if (canbus_src_is_translator(src)) {
261 		net_pkt_copy(dst, src, sizeof(struct net_eth_addr));
262 		lladdr->len = sizeof(struct net_eth_addr);
263 		lladdr->type = NET_LINK_ETHERNET;
264 		NET_DBG("Inline MAC: %02x:%02x:%02x:%02x:%02x:%02x",
265 			lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
266 			lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
267 	} else {
268 		net_pkt_write(dst, net_pkt_lladdr_src(src)->addr,
269 			      sizeof(struct net_canbus_lladdr));
270 		lladdr->len = sizeof(struct net_canbus_lladdr);
271 		lladdr->type = NET_LINK_CANBUS;
272 	}
273 }
274 
275 
canbus_get_rx_ctx(uint8_t state,uint16_t src_addr)276 static struct canbus_isotp_rx_ctx *canbus_get_rx_ctx(uint8_t state,
277 						     uint16_t src_addr)
278 {
279 	int i;
280 	struct canbus_isotp_rx_ctx *ret = NULL;
281 
282 	k_mutex_lock(&l2_ctx.rx_ctx_mtx, K_FOREVER);
283 	for (i = 0; i < ARRAY_SIZE(l2_ctx.rx_ctx); i++) {
284 		struct canbus_isotp_rx_ctx *ctx = &l2_ctx.rx_ctx[i];
285 
286 		if (ctx->state == state) {
287 			if (state == NET_CAN_RX_STATE_UNUSED) {
288 				ctx->state = NET_CAN_RX_STATE_RESET;
289 				z_init_timeout(&ctx->timeout);
290 				ret = ctx;
291 				break;
292 			}
293 
294 			if (canbus_get_src_lladdr(ctx->pkt) == src_addr) {
295 				ret = ctx;
296 				break;
297 			}
298 		}
299 	}
300 
301 	k_mutex_unlock(&l2_ctx.rx_ctx_mtx);
302 	return ret;
303 }
304 
canbus_get_tx_ctx(uint8_t state,uint16_t dest_addr)305 static struct canbus_isotp_tx_ctx *canbus_get_tx_ctx(uint8_t state,
306 						     uint16_t dest_addr)
307 {
308 	int i;
309 	struct canbus_isotp_tx_ctx *ret = NULL;
310 
311 	k_mutex_lock(&l2_ctx.tx_ctx_mtx, K_FOREVER);
312 	for (i = 0; i < ARRAY_SIZE(l2_ctx.tx_ctx); i++) {
313 		struct canbus_isotp_tx_ctx *ctx = &l2_ctx.tx_ctx[i];
314 
315 		if (ctx->state == state) {
316 			if (state == NET_CAN_TX_STATE_UNUSED) {
317 				ctx->state = NET_CAN_TX_STATE_RESET;
318 				z_init_timeout(&ctx->timeout);
319 				ret = ctx;
320 				break;
321 			}
322 
323 			if (ctx->dest_addr.addr == dest_addr) {
324 				ret = ctx;
325 				break;
326 			}
327 		}
328 	}
329 
330 	k_mutex_unlock(&l2_ctx.tx_ctx_mtx);
331 	return ret;
332 }
333 
canbus_receive_get_ff_length(struct net_pkt * pkt)334 static inline uint16_t canbus_receive_get_ff_length(struct net_pkt *pkt)
335 {
336 	uint16_t len;
337 	int ret;
338 
339 	ret = net_pkt_read_be16(pkt, &len);
340 	if (ret < 0) {
341 		NET_ERR("Can't read length");
342 	}
343 
344 	return len & 0x0FFF;
345 }
346 
canbus_get_sf_length(struct net_pkt * pkt)347 static inline size_t canbus_get_sf_length(struct net_pkt *pkt)
348 {
349 	size_t len;
350 
351 	net_buf_pull_u8(pkt->frags);
352 	len = net_buf_pull_u8(pkt->frags);
353 
354 	return len;
355 }
356 
canbus_set_frame_datalength(struct zcan_frame * frame,uint8_t length)357 static inline void canbus_set_frame_datalength(struct zcan_frame *frame,
358 					       uint8_t length)
359 {
360 	/* TODO: Needs update when CAN FD support is added */
361 	NET_ASSERT(length <= NET_CAN_DL);
362 	frame->dlc = length;
363 }
364 
canbus_finish_pkt(struct net_pkt * pkt)365 static enum net_verdict canbus_finish_pkt(struct net_pkt *pkt)
366 {
367 	/* Pull the ll addresses to ignore them in upper layers */
368 	net_buf_pull(pkt->buffer, net_pkt_lladdr_dst(pkt)->len +
369 		     net_pkt_lladdr_src(pkt)->len);
370 
371 	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
372 	    canbus_is_for_translator(pkt)) {
373 		/* Pull room for address extension */
374 		net_buf_pull(pkt->buffer, sizeof(struct net_eth_addr) -
375 			     net_pkt_lladdr_src(pkt)->len);
376 		/* Set the destination address to the inline MAC and pull it */
377 		net_pkt_cursor_init(pkt);
378 		net_pkt_lladdr_dst(pkt)->addr = net_pkt_cursor_get_pos(pkt);
379 		net_pkt_lladdr_dst(pkt)->type = NET_LINK_ETHERNET;
380 		net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
381 		net_buf_pull(pkt->buffer, sizeof(struct net_eth_addr));
382 	}
383 
384 	net_pkt_cursor_init(pkt);
385 	if (!net_6lo_uncompress(pkt)) {
386 		NET_ERR("6lo uncompression failed");
387 		return NET_DROP;
388 	}
389 
390 	net_pkt_cursor_init(pkt);
391 
392 	return NET_CONTINUE;
393 }
394 
canbus_addr_to_id(uint16_t dest,uint16_t src)395 static inline uint32_t canbus_addr_to_id(uint16_t dest, uint16_t src)
396 {
397 	return (dest << CAN_NET_IF_ADDR_DEST_POS) |
398 	       (src << CAN_NET_IF_ADDR_SRC_POS);
399 }
400 
canbus_set_frame_addr(struct zcan_frame * frame,const struct net_canbus_lladdr * dest,const struct net_canbus_lladdr * src,bool mcast)401 static void canbus_set_frame_addr(struct zcan_frame *frame,
402 				  const struct net_canbus_lladdr *dest,
403 				  const struct net_canbus_lladdr *src,
404 				  bool mcast)
405 {
406 	frame->id_type = CAN_EXTENDED_IDENTIFIER;
407 	frame->rtr = CAN_DATAFRAME;
408 
409 	frame->id = canbus_addr_to_id(dest->addr, src->addr);
410 
411 	if (mcast) {
412 		frame->id |= CAN_NET_IF_ADDR_MCAST_MASK;
413 	}
414 }
415 
canbus_set_frame_addr_pkt(struct zcan_frame * frame,struct net_pkt * pkt,struct net_canbus_lladdr * dest_addr,bool mcast)416 static void canbus_set_frame_addr_pkt(struct zcan_frame *frame,
417 				      struct net_pkt *pkt,
418 				      struct net_canbus_lladdr *dest_addr,
419 				      bool mcast)
420 {
421 	struct net_canbus_lladdr src_addr;
422 
423 	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
424 	    net_pkt_lladdr_src(pkt)->type == NET_LINK_ETHERNET) {
425 		src_addr.addr = NET_CAN_ETH_TRANSLATOR_ADDR;
426 	} else {
427 		src_addr.addr = canbus_get_lladdr(net_if_get_link_addr(pkt->iface));
428 	}
429 
430 	canbus_set_frame_addr(frame, dest_addr, &src_addr, mcast);
431 }
432 
canbus_fc_send_cb(int error,void * arg)433 static void canbus_fc_send_cb(int error, void *arg)
434 {
435 	if (error != 0) {
436 		NET_ERR("Sending FC frame failed: %d", error);
437 	}
438 }
439 
canbus_send_fc(const struct device * net_can_dev,struct net_canbus_lladdr * dest,struct net_canbus_lladdr * src,uint8_t fs)440 static int canbus_send_fc(const struct device *net_can_dev,
441 			  struct net_canbus_lladdr *dest,
442 			  struct net_canbus_lladdr *src, uint8_t fs)
443 {
444 	const struct net_can_api *api = net_can_dev->api;
445 	struct zcan_frame frame = {
446 		.id_type = CAN_EXTENDED_IDENTIFIER,
447 		.rtr = CAN_DATAFRAME,
448 	};
449 
450 	NET_ASSERT(!(fs & NET_CAN_PCI_TYPE_MASK));
451 
452 	canbus_set_frame_addr(&frame, dest, src, false);
453 
454 	frame.data[0] = NET_CAN_PCI_TYPE_FC | fs;
455 	/* BS (Block Size) */
456 	frame.data[1] = NET_CAN_BS;
457 	/* STmin (minimum Seperation Time) */
458 	frame.data[2] = NET_CAN_STMIN;
459 	canbus_set_frame_datalength(&frame, 3);
460 
461 	NET_DBG("Sending FC to ID: 0x%08x", frame.id);
462 	return api->send(net_can_dev, &frame, canbus_fc_send_cb, NULL,
463 			 K_FOREVER);
464 }
465 
canbus_process_cf_data(struct net_pkt * frag_pkt,struct canbus_isotp_rx_ctx * ctx)466 static int canbus_process_cf_data(struct net_pkt *frag_pkt,
467 				  struct canbus_isotp_rx_ctx *ctx)
468 {
469 	struct net_pkt *pkt = ctx->pkt;
470 	size_t data_len = net_pkt_get_len(frag_pkt) - 1;
471 	uint8_t pci;
472 	int ret;
473 
474 	pci = net_buf_pull_u8(frag_pkt->frags);
475 
476 	if ((pci & NET_CAN_PCI_SN_MASK) != ctx->sn) {
477 		NET_ERR("Sequence number missmatch. Expect %u, got %u",
478 			ctx->sn, pci & NET_CAN_PCI_SN_MASK);
479 		goto err;
480 	}
481 
482 	ctx->sn++;
483 
484 	if (data_len > ctx->rem_len) {
485 		NET_DBG("Remove padding of %d bytes", data_len - ctx->rem_len);
486 		data_len = ctx->rem_len;
487 	}
488 
489 	net_pkt_cursor_init(frag_pkt);
490 	NET_DBG("Appending CF data to pkt (%d bytes)", data_len);
491 	ret = net_pkt_copy(pkt, frag_pkt, data_len);
492 	if (ret < 0) {
493 		NET_ERR("Failed to write data to pkt [%d]", ret);
494 		goto err;
495 	}
496 
497 	ctx->rem_len -= data_len;
498 
499 	NET_DBG("%u bytes remaining", ctx->rem_len);
500 
501 	return 0;
502 err:
503 	canbus_rx_report_err(pkt);
504 	return -1;
505 }
506 
canbus_process_cf(struct net_pkt * pkt)507 static enum net_verdict canbus_process_cf(struct net_pkt *pkt)
508 {
509 	struct canbus_isotp_rx_ctx *rx_ctx;
510 	enum net_verdict ret;
511 	const struct device *net_can_dev;
512 	struct net_canbus_lladdr src, dest;
513 	bool mcast;
514 
515 	mcast = canbus_dest_is_mcast(pkt);
516 
517 	rx_ctx = canbus_get_rx_ctx(NET_CAN_RX_STATE_CF,
518 				   canbus_get_src_lladdr(pkt));
519 	if (!rx_ctx) {
520 		NET_INFO("Got CF but can't find a CTX that is waiting for it. "
521 			 "Src: 0x%04x", canbus_get_src_lladdr(pkt));
522 		return NET_DROP;
523 	}
524 
525 	z_abort_timeout(&rx_ctx->timeout);
526 
527 	ret = canbus_process_cf_data(pkt, rx_ctx);
528 	if (ret < 0) {
529 		return NET_DROP;
530 	}
531 
532 	net_pkt_unref(pkt);
533 
534 	if (rx_ctx->rem_len == 0) {
535 		rx_ctx->state = NET_CAN_RX_STATE_FIN;
536 		ret = net_recv_data(pkt->iface, rx_ctx->pkt);
537 		if (ret < 0) {
538 			NET_ERR("Packet dropped by NET stack");
539 			net_pkt_unref(pkt);
540 		}
541 	} else {
542 		z_add_timeout(&rx_ctx->timeout, canbus_rx_timeout,
543 			      NET_CAN_BS_TIME);
544 
545 		if (NET_CAN_BS != 0 && !mcast) {
546 			rx_ctx->act_block_nr++;
547 			if (rx_ctx->act_block_nr >= NET_CAN_BS) {
548 				NET_DBG("BS reached. Send FC");
549 				src.addr = canbus_get_src_lladdr(pkt);
550 				dest.addr = canbus_get_dest_lladdr(pkt);
551 				net_can_dev = net_if_get_device(pkt->iface);
552 				ret = canbus_send_fc(net_can_dev, &src, &dest,
553 						     NET_CAN_PCI_FS_CTS);
554 				if (ret) {
555 					NET_ERR("Failed to send FC CTS. BS: %d",
556 						NET_CAN_BS);
557 					canbus_rx_report_err(rx_ctx->pkt);
558 					return NET_OK;
559 				}
560 
561 				rx_ctx->act_block_nr = 0;
562 			}
563 		}
564 	}
565 
566 	return NET_OK;
567 }
568 
canbus_process_ff(struct net_pkt * pkt)569 static enum net_verdict canbus_process_ff(struct net_pkt *pkt)
570 {
571 	const struct device *net_can_dev = net_if_get_device(pkt->iface);
572 	struct canbus_isotp_rx_ctx *rx_ctx = NULL;
573 	struct net_pkt *new_pkt = NULL;
574 	int ret;
575 	struct net_canbus_lladdr src, dest;
576 	uint16_t msg_len;
577 	size_t new_pkt_len;
578 	uint8_t data_len;
579 	bool mcast;
580 
581 	mcast = canbus_dest_is_mcast(pkt);
582 	src.addr = canbus_get_src_lladdr(pkt);
583 	dest.addr = canbus_get_dest_lladdr(pkt);
584 	net_pkt_cursor_init(pkt);
585 
586 	msg_len = canbus_receive_get_ff_length(pkt);
587 
588 	new_pkt_len = msg_len + canbus_total_lladdr_len(pkt);
589 
590 	new_pkt = net_pkt_rx_alloc_with_buffer(pkt->iface, new_pkt_len,
591 					       AF_INET6, 0,
592 					       NET_CAN_ALLOC_TIMEOUT);
593 	if (!new_pkt) {
594 		NET_ERR("Failed to obtain net_pkt with size of %d", new_pkt_len);
595 
596 		if (!mcast) {
597 			canbus_send_fc(net_can_dev, &src, &dest,
598 				       NET_CAN_PCI_FS_OVFLW);
599 		}
600 
601 		goto err;
602 	}
603 
604 	rx_ctx = canbus_get_rx_ctx(NET_CAN_RX_STATE_UNUSED, 0);
605 	if (!rx_ctx) {
606 		NET_ERR("No rx context left");
607 
608 		if (!mcast) {
609 			canbus_send_fc(net_can_dev, &src, &dest,
610 				       NET_CAN_PCI_FS_OVFLW);
611 		}
612 
613 		goto err;
614 	}
615 
616 	rx_ctx->act_block_nr = 0;
617 	rx_ctx->pkt = new_pkt;
618 	new_pkt->canbus_rx_ctx = rx_ctx;
619 
620 	net_pkt_cursor_init(new_pkt);
621 	data_len = net_pkt_remaining_data(pkt);
622 	canbus_cpy_lladdr(new_pkt, pkt);
623 	rx_ctx->sn = 1;
624 
625 	ret = net_pkt_copy(new_pkt, pkt, net_pkt_remaining_data(pkt));
626 	if (ret) {
627 		NET_ERR("Failed to write to pkt [%d]", ret);
628 		goto err;
629 	}
630 
631 	rx_ctx->rem_len = msg_len - data_len;
632 	net_pkt_unref(pkt);
633 
634 	if (!mcast) {
635 		/* switch src and dest because we are answering */
636 		ret = canbus_send_fc(net_can_dev, &src, &dest,
637 				     NET_CAN_PCI_FS_CTS);
638 		if (ret) {
639 			NET_ERR("Failed to send FC CTS");
640 			canbus_rx_report_err(new_pkt);
641 			return NET_OK;
642 		}
643 	}
644 
645 	/* At this point we expect to get Consecutive frames directly */
646 	z_add_timeout(&rx_ctx->timeout, canbus_rx_timeout, NET_CAN_BS_TIME);
647 
648 	rx_ctx->state = NET_CAN_RX_STATE_CF;
649 
650 	NET_DBG("Processed FF from 0x%04x (%scast)"
651 		"Msg length: %u CTX: %p",
652 		src.addr, mcast ? "m" : "uni", msg_len, rx_ctx);
653 
654 	return NET_OK;
655 
656 err:
657 	if (new_pkt) {
658 		net_pkt_unref(new_pkt);
659 	}
660 
661 	if (rx_ctx) {
662 		canbus_free_rx_ctx(rx_ctx);
663 	}
664 
665 	return NET_DROP;
666 }
667 
canbus_process_sf(struct net_pkt * pkt)668 static enum net_verdict canbus_process_sf(struct net_pkt *pkt)
669 {
670 	size_t data_len;
671 	size_t pkt_len;
672 
673 	net_pkt_set_family(pkt, AF_INET6);
674 
675 	data_len = canbus_get_sf_length(pkt);
676 	pkt_len = net_pkt_get_len(pkt);
677 
678 	if (data_len > pkt_len) {
679 		NET_ERR("SF datalen > pkt size");
680 		return NET_DROP;
681 	}
682 
683 	if (pkt_len != data_len) {
684 		NET_DBG("Remove padding (%d byte)", pkt_len - data_len);
685 		net_pkt_update_length(pkt, data_len);
686 	}
687 
688 	return canbus_finish_pkt(pkt);
689 }
690 
canbus_tx_frame_isr(int error,void * arg)691 static void canbus_tx_frame_isr(int error, void *arg)
692 {
693 	struct net_pkt *pkt = (struct net_pkt *)arg;
694 	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
695 	struct net_if *iface = net_pkt_iface(pkt);
696 	struct canbus_net_ctx *net_ctx = net_if_l2_data(iface);
697 
698 	ctx->tx_backlog--;
699 
700 	if (ctx->state == NET_CAN_TX_STATE_WAIT_TX_BACKLOG) {
701 		if (ctx->tx_backlog > 0) {
702 			return;
703 		}
704 
705 		ctx->state = NET_CAN_TX_STATE_FIN;
706 	}
707 
708 	submit_to_queue(&net_ctx->tx_queue, pkt);
709 }
710 
canbus_send_cf(struct net_pkt * pkt)711 static inline int canbus_send_cf(struct net_pkt *pkt)
712 {
713 	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
714 	const struct device *net_can_dev = net_if_get_device(pkt->iface);
715 	const struct net_can_api *api = net_can_dev->api;
716 	struct zcan_frame frame;
717 	struct net_pkt_cursor cursor_backup;
718 	int ret, len;
719 
720 	canbus_set_frame_addr_pkt(&frame, pkt, &ctx->dest_addr, ctx->is_mcast);
721 
722 	/* sn wraps around at 0xF automatically because it has a 4 bit size */
723 	frame.data[0] = NET_CAN_PCI_TYPE_CF | ctx->sn;
724 
725 	len = MIN(ctx->rem_len, NET_CAN_DL - 1);
726 
727 	canbus_set_frame_datalength(&frame, len + 1);
728 
729 	net_pkt_cursor_backup(pkt, &cursor_backup);
730 	net_pkt_read(pkt, &frame.data[1], len);
731 	ret = api->send(net_can_dev, &frame, canbus_tx_frame_isr,
732 			pkt, K_NO_WAIT);
733 	if (ret == CAN_TX_OK) {
734 		ctx->sn++;
735 		ctx->rem_len -= len;
736 		ctx->act_block_nr--;
737 		ctx->tx_backlog++;
738 	} else {
739 		net_pkt_cursor_restore(pkt, &cursor_backup);
740 	}
741 
742 	NET_DBG("CF sent. %d bytes left. CTX: %p", ctx->rem_len, ctx);
743 
744 	return ret ? ret : ctx->rem_len;
745 }
746 
canbus_tx_work(struct net_pkt * pkt)747 static void canbus_tx_work(struct net_pkt *pkt)
748 {
749 	int ret;
750 	struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx;
751 
752 	NET_ASSERT(ctx);
753 
754 	switch (ctx->state) {
755 	case NET_CAN_TX_STATE_SEND_CF:
756 		do {
757 			ret = canbus_send_cf(ctx->pkt);
758 			if (!ret) {
759 				ctx->state = NET_CAN_TX_STATE_WAIT_TX_BACKLOG;
760 				break;
761 			}
762 
763 			if (ret < 0 && ret != CAN_TIMEOUT) {
764 				NET_ERR("Failed to send CF. CTX: %p", ctx);
765 				canbus_tx_report_err(pkt);
766 				break;
767 			}
768 
769 			if (ctx->opts.bs && !ctx->is_mcast &&
770 			    !ctx->act_block_nr) {
771 				NET_DBG("BS reached. Wait for FC again. CTX: %p",
772 					ctx);
773 				ctx->state = NET_CAN_TX_STATE_WAIT_FC;
774 				z_add_timeout(&ctx->timeout, canbus_tx_timeout,
775 					      NET_CAN_BS_TIME);
776 				break;
777 			} else if (ctx->opts.stmin) {
778 				ctx->state = NET_CAN_TX_STATE_WAIT_ST;
779 				break;
780 			}
781 		} while (ret > 0);
782 
783 		break;
784 
785 	case NET_CAN_TX_STATE_WAIT_ST:
786 		NET_DBG("SM wait ST. CTX: %p", ctx);
787 		z_add_timeout(&ctx->timeout, canbus_st_min_timeout,
788 			      canbus_stmin_to_ticks(ctx->opts.stmin));
789 		ctx->state = NET_CAN_TX_STATE_SEND_CF;
790 		break;
791 
792 	case NET_CAN_TX_STATE_ERR:
793 		NET_DBG("SM handle error. CTX: %p", ctx);
794 		canbus_tx_report_err(pkt);
795 		break;
796 
797 	case NET_CAN_TX_STATE_FIN:
798 		canbus_tx_finish(ctx->pkt);
799 		NET_DBG("SM finish. CTX: %p", ctx);
800 		break;
801 
802 	default:
803 		break;
804 	}
805 }
806 
canbus_process_fc_data(struct canbus_isotp_tx_ctx * ctx,struct net_pkt * pkt)807 static enum net_verdict canbus_process_fc_data(struct canbus_isotp_tx_ctx *ctx,
808 					       struct net_pkt *pkt)
809 {
810 	struct net_buf *buf = pkt->frags;
811 	uint8_t pci;
812 
813 	pci = net_buf_pull_u8(buf);
814 
815 	switch (pci & NET_CAN_PCI_FS_MASK) {
816 	case NET_CAN_PCI_FS_CTS:
817 		if (net_buf_frags_len(buf) != 2) {
818 			NET_ERR("Frame length error for CTS");
819 			canbus_tx_report_err(pkt);
820 			return NET_DROP;
821 		}
822 
823 		ctx->state = NET_CAN_TX_STATE_SEND_CF;
824 		ctx->wft = 0;
825 		ctx->opts.bs = net_buf_pull_u8(buf);
826 		ctx->opts.stmin = net_buf_pull_u8(buf);
827 		ctx->act_block_nr = ctx->opts.bs;
828 		z_abort_timeout(&ctx->timeout);
829 		NET_DBG("Got CTS. BS: %d, STmin: %d. CTX: %p",
830 			ctx->opts.bs, ctx->opts.stmin, ctx);
831 		net_pkt_unref(pkt);
832 		return NET_OK;
833 	case NET_CAN_PCI_FS_WAIT:
834 		NET_DBG("Got WAIT frame. CTX: %p", ctx);
835 		z_abort_timeout(&ctx->timeout);
836 		z_add_timeout(&ctx->timeout, canbus_tx_timeout,
837 			      NET_CAN_BS_TIME);
838 		if (ctx->wft >= NET_CAN_WFTMAX) {
839 			NET_INFO("Got to many wait frames. CTX: %p", ctx);
840 			ctx->state = NET_CAN_TX_STATE_ERR;
841 		}
842 
843 		ctx->wft++;
844 		return NET_OK;
845 	case NET_CAN_PCI_FS_OVFLW:
846 		NET_ERR("Got overflow FC frame. CTX: %p", ctx);
847 		ctx->state = NET_CAN_TX_STATE_ERR;
848 		return NET_OK;
849 	default:
850 		NET_ERR("Invalid Frame Status. CTX: %p", ctx);
851 		ctx->state = NET_CAN_TX_STATE_ERR;
852 		break;
853 	}
854 
855 	return NET_DROP;
856 }
857 
canbus_process_fc(struct net_pkt * pkt)858 static enum net_verdict canbus_process_fc(struct net_pkt *pkt)
859 {
860 	struct canbus_isotp_tx_ctx *tx_ctx;
861 	uint16_t src_addr = canbus_get_src_lladdr(pkt);
862 	enum net_verdict ret;
863 	struct net_if *iface = net_pkt_iface(pkt);
864 	struct canbus_net_ctx *net_ctx = net_if_l2_data(iface);
865 
866 	tx_ctx = canbus_get_tx_ctx(NET_CAN_TX_STATE_WAIT_FC, src_addr);
867 	if (!tx_ctx) {
868 		NET_WARN("Got FC frame from 0x%04x but can't find any "
869 			 "CTX waiting for it", src_addr);
870 		return NET_DROP;
871 	}
872 
873 	ret = canbus_process_fc_data(tx_ctx, pkt);
874 	if (ret == NET_OK) {
875 		submit_to_queue(&net_ctx->tx_queue, tx_ctx->pkt);
876 	}
877 
878 	return ret;
879 }
880 
canbus_send_ff(struct net_pkt * pkt,size_t len,bool mcast,struct net_canbus_lladdr * dest_addr)881 static inline int canbus_send_ff(struct net_pkt *pkt, size_t len, bool mcast,
882 				 struct net_canbus_lladdr *dest_addr)
883 {
884 	const struct device *net_can_dev = net_if_get_device(pkt->iface);
885 	const struct net_can_api *api = net_can_dev->api;
886 	struct net_linkaddr *lladdr_inline;
887 	struct zcan_frame frame;
888 	int ret, index = 0;
889 
890 	canbus_set_frame_addr_pkt(&frame, pkt, dest_addr, mcast);
891 	canbus_set_frame_datalength(&frame, NET_CAN_DL);
892 
893 	if (mcast) {
894 		NET_DBG("Sending FF (multicast). ID: 0x%08x. PKT len: %zu"
895 			" CTX: %p",
896 			frame.id, len, pkt->canbus_tx_ctx);
897 	} else {
898 		NET_DBG("Sending FF (unicast). ID: 0x%08x. PKT len: %zu"
899 			" CTX: %p",
900 			frame.id, len, pkt->canbus_tx_ctx);
901 	}
902 
903 #if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
904 	NET_ASSERT(mcast || !(canbus_dest_is_translator(pkt) &&
905 			      canbus_src_is_translator(pkt)));
906 
907 	if (canbus_src_is_translator(pkt)) {
908 		len += net_pkt_lladdr_src(pkt)->len;
909 	}
910 #endif
911 	if (!mcast && canbus_dest_is_translator(pkt)) {
912 		len += net_pkt_lladdr_dst(pkt)->len;
913 	}
914 
915 	frame.data[index++] = NET_CAN_PCI_TYPE_FF | (len >> 8);
916 	frame.data[index++] = len & 0xFF;
917 
918 	/* According to ISO, FF has sn 0 and is incremented to one
919 	 * alltough it's not part of the FF frame
920 	 */
921 	pkt->canbus_tx_ctx->sn = 1;
922 
923 	if (!mcast && canbus_dest_is_translator(pkt)) {
924 		lladdr_inline = net_pkt_lladdr_dst(pkt);
925 		memcpy(&frame.data[index], lladdr_inline->addr,
926 		       lladdr_inline->len);
927 		index += lladdr_inline->len;
928 	}
929 
930 	if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
931 	    net_pkt_lladdr_src(pkt)->type == NET_LINK_ETHERNET) {
932 		lladdr_inline = net_pkt_lladdr_src(pkt);
933 		memcpy(&frame.data[index], lladdr_inline->addr,
934 		       lladdr_inline->len);
935 		index += lladdr_inline->len;
936 	}
937 
938 	net_pkt_read(pkt, &frame.data[index], NET_CAN_DL - index);
939 	pkt->canbus_tx_ctx->rem_len -= NET_CAN_DL - index;
940 
941 	ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER);
942 	if (ret != CAN_TX_OK) {
943 		NET_ERR("Sending FF failed [%d]. CTX: %p",
944 			ret, pkt->canbus_tx_ctx);
945 	}
946 
947 	return ret;
948 }
949 
canbus_send_single_frame(struct net_pkt * pkt,size_t len,bool mcast,struct net_canbus_lladdr * dest_addr)950 static inline int canbus_send_single_frame(struct net_pkt *pkt, size_t len,
951 					   bool mcast,
952 					   struct net_canbus_lladdr *dest_addr)
953 {
954 	const struct device *net_can_dev = net_if_get_device(pkt->iface);
955 	const struct net_can_api *api = net_can_dev->api;
956 	int index = 0;
957 	struct zcan_frame frame;
958 	struct net_linkaddr *lladdr_dest;
959 	int ret;
960 
961 	canbus_set_frame_addr_pkt(&frame, pkt, dest_addr, mcast);
962 
963 	frame.data[index++] = NET_CAN_PCI_TYPE_SF;
964 	frame.data[index++] = len;
965 
966 	NET_ASSERT((len + (!mcast && canbus_dest_is_translator(pkt)) ?
967 		    net_pkt_lladdr_dst(pkt)->len : 0) <= NET_CAN_DL - 1);
968 
969 	if (!mcast && canbus_dest_is_translator(pkt)) {
970 		lladdr_dest = net_pkt_lladdr_dst(pkt);
971 		memcpy(&frame.data[index], lladdr_dest->addr, lladdr_dest->len);
972 		index += lladdr_dest->len;
973 	}
974 
975 	net_pkt_read(pkt, &frame.data[index], len);
976 
977 	canbus_set_frame_datalength(&frame, len + index);
978 
979 	ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER);
980 	if (ret != CAN_TX_OK) {
981 		NET_ERR("Sending SF failed [%d]", ret);
982 		return -EIO;
983 	}
984 
985 	return 0;
986 }
987 
canbus_start_sending_cf(struct _timeout * t)988 static void canbus_start_sending_cf(struct _timeout *t)
989 {
990 	struct canbus_isotp_tx_ctx *ctx =
991 		CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout);
992 	struct net_if *iface = net_pkt_iface(ctx->pkt);
993 	struct canbus_net_ctx *net_ctx = net_if_l2_data(iface);
994 
995 	submit_to_queue(&net_ctx->tx_queue, ctx->pkt);
996 }
997 
canbus_send_multiple_frames(struct net_pkt * pkt,size_t len,bool mcast,struct net_canbus_lladdr * dest_addr)998 static int canbus_send_multiple_frames(struct net_pkt *pkt, size_t len,
999 				       bool mcast,
1000 				       struct net_canbus_lladdr *dest_addr)
1001 {
1002 	struct canbus_isotp_tx_ctx *tx_ctx = NULL;
1003 	int ret;
1004 
1005 	tx_ctx = canbus_get_tx_ctx(NET_CAN_TX_STATE_UNUSED, 0);
1006 
1007 	if (!tx_ctx) {
1008 		NET_ERR("No tx context left");
1009 		k_sem_give(&l2_ctx.tx_sem);
1010 		return -EAGAIN;
1011 	}
1012 
1013 	tx_ctx->pkt = pkt;
1014 	pkt->canbus_tx_ctx = tx_ctx;
1015 	tx_ctx->is_mcast = mcast;
1016 	tx_ctx->dest_addr = *dest_addr;
1017 	tx_ctx->rem_len = net_pkt_get_len(pkt);
1018 	tx_ctx->tx_backlog = 0;
1019 
1020 	ret = canbus_send_ff(pkt, len, mcast, dest_addr);
1021 	if (ret != CAN_TX_OK) {
1022 		NET_ERR("Failed to send FF [%d]", ret);
1023 		canbus_tx_report_err(pkt);
1024 		return -EIO;
1025 	}
1026 
1027 	if (!mcast) {
1028 		z_add_timeout(&tx_ctx->timeout, canbus_tx_timeout,
1029 			      NET_CAN_BS_TIME);
1030 		tx_ctx->state = NET_CAN_TX_STATE_WAIT_FC;
1031 	} else {
1032 		tx_ctx->state = NET_CAN_TX_STATE_SEND_CF;
1033 		z_add_timeout(&tx_ctx->timeout, canbus_start_sending_cf,
1034 			      NET_CAN_FF_CF_TIME);
1035 	}
1036 
1037 	return 0;
1038 }
1039 
canbus_ipv6_mcast_to_dest(struct net_pkt * pkt,struct net_canbus_lladdr * dest_addr)1040 static void canbus_ipv6_mcast_to_dest(struct net_pkt *pkt,
1041 				      struct net_canbus_lladdr *dest_addr)
1042 {
1043 	dest_addr->addr =
1044 		sys_be16_to_cpu(UNALIGNED_GET(&NET_IPV6_HDR(pkt)->dst.s6_addr16[7]));
1045 }
1046 
canbus_eth_to_can_addr(struct net_linkaddr * lladdr)1047 static inline uint16_t canbus_eth_to_can_addr(struct net_linkaddr *lladdr)
1048 {
1049 	return (sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)&lladdr->addr[4])) &
1050 		CAN_NET_IF_ADDR_MASK);
1051 }
1052 
canbus_send(struct net_if * iface,struct net_pkt * pkt)1053 static int canbus_send(struct net_if *iface, struct net_pkt *pkt)
1054 {
1055 	int ret = 0;
1056 	int comp_len;
1057 	size_t pkt_len, inline_lladdr_len;
1058 	struct net_canbus_lladdr dest_addr;
1059 	bool mcast;
1060 
1061 	if (net_pkt_family(pkt) != AF_INET6) {
1062 		return -EINVAL;
1063 	}
1064 
1065 	mcast = net_ipv6_is_addr_mcast(&NET_IPV6_HDR(pkt)->dst);
1066 	if (mcast || canbus_dest_is_mcast(pkt)) {
1067 		canbus_ipv6_mcast_to_dest(pkt, &dest_addr);
1068 	} else if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) &&
1069 		   net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET) {
1070 		struct net_linkaddr *lladdr = net_pkt_lladdr_dst(pkt);
1071 
1072 		lladdr->type = NET_LINK_CANBUS;
1073 		lladdr->len = sizeof(struct net_canbus_lladdr);
1074 		dest_addr.addr = canbus_eth_to_can_addr(net_pkt_lladdr_dst(pkt));
1075 		NET_DBG("Translated %02x:%02x:%02x:%02x:%02x:%02x to 0x%04x",
1076 			lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
1077 			lladdr->addr[3], lladdr->addr[4], lladdr->addr[5],
1078 			dest_addr.addr);
1079 	} else {
1080 		dest_addr.addr = canbus_get_dest_lladdr(pkt);
1081 	}
1082 
1083 	net_pkt_cursor_init(pkt);
1084 	canbus_print_ip_hdr((struct net_ipv6_hdr *)net_pkt_cursor_get_pos(pkt));
1085 	comp_len = net_6lo_compress(pkt, true);
1086 	if (comp_len < 0) {
1087 		NET_ERR("IPHC failed [%d]", comp_len);
1088 		return comp_len;
1089 	}
1090 
1091 	NET_DBG("IPv6 hdr compressed by %d bytes", comp_len);
1092 	net_pkt_cursor_init(pkt);
1093 	pkt_len = net_pkt_get_len(pkt);
1094 
1095 	net_capture_pkt(iface, pkt);
1096 
1097 	NET_DBG("Send CAN frame to 0x%04x%s", dest_addr.addr,
1098 		mcast ? " (mcast)" : "");
1099 
1100 	inline_lladdr_len = (!mcast && canbus_dest_is_translator(pkt)) ?
1101 			    net_pkt_lladdr_dst(pkt)->len : 0;
1102 
1103 	if ((pkt_len + inline_lladdr_len) > (NET_CAN_DL - 1)) {
1104 		k_sem_take(&l2_ctx.tx_sem, K_FOREVER);
1105 		ret = canbus_send_multiple_frames(pkt, pkt_len, mcast,
1106 						  &dest_addr);
1107 	} else {
1108 		ret = canbus_send_single_frame(pkt, pkt_len, mcast, &dest_addr);
1109 		canbus_tx_finish(pkt);
1110 	}
1111 
1112 	return ret;
1113 }
1114 
canbus_process_frame(struct net_pkt * pkt)1115 static enum net_verdict canbus_process_frame(struct net_pkt *pkt)
1116 {
1117 	enum net_verdict ret = NET_DROP;
1118 	uint8_t pci_type;
1119 
1120 	net_pkt_cursor_init(pkt);
1121 	ret = net_pkt_read_u8(pkt, &pci_type);
1122 	if (ret < 0) {
1123 		NET_ERR("Can't read PCI");
1124 	}
1125 	pci_type = (pci_type & NET_CAN_PCI_TYPE_MASK) >> NET_CAN_PCI_TYPE_POS;
1126 
1127 	switch (pci_type) {
1128 	case NET_CAN_PCI_SF:
1129 		ret = canbus_process_sf(pkt);
1130 		break;
1131 	case NET_CAN_PCI_FF:
1132 		ret = canbus_process_ff(pkt);
1133 		break;
1134 	case NET_CAN_PCI_CF:
1135 		ret = canbus_process_cf(pkt);
1136 		break;
1137 	case NET_CAN_PCI_FC:
1138 		ret = canbus_process_fc(pkt);
1139 		break;
1140 	default:
1141 		NET_ERR("Unknown PCI number %u", pci_type);
1142 		break;
1143 	}
1144 
1145 	return ret;
1146 }
1147 
1148 #if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)
forward_eth_frame(struct net_pkt * pkt,struct net_if * canbus_iface)1149 static void forward_eth_frame(struct net_pkt *pkt, struct net_if *canbus_iface)
1150 {
1151 	pkt->iface = canbus_iface;
1152 	net_if_queue_tx(canbus_iface, pkt);
1153 }
1154 
get_ip_hdr_from_eth_frame(struct net_pkt * pkt)1155 static struct net_ipv6_hdr *get_ip_hdr_from_eth_frame(struct net_pkt *pkt)
1156 {
1157 	return (struct net_ipv6_hdr *)((uint8_t *)net_pkt_data(pkt) +
1158 				       sizeof(struct net_eth_hdr));
1159 }
1160 
net_canbus_translate_eth_frame(struct net_if * iface,struct net_pkt * pkt)1161 enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface,
1162 						struct net_pkt *pkt)
1163 {
1164 	struct net_linkaddr *lladdr = net_pkt_lladdr_dst(pkt);
1165 	struct net_pkt *clone_pkt;
1166 	struct net_if *canbus_iface;
1167 
1168 	/* Forward only IPv6 frames */
1169 	if ((get_ip_hdr_from_eth_frame(pkt)->vtc & 0xf0) != 0x60) {
1170 		return NET_CONTINUE;
1171 	}
1172 
1173 	/* This frame is for the Ethernet interface itself */
1174 	if (net_linkaddr_cmp(net_if_get_link_addr(iface), lladdr)) {
1175 		NET_DBG("Frame is for Ethernet only %02x:%02x:%02x:%02x:%02x:%02x",
1176 			lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
1177 			lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
1178 		return NET_CONTINUE;
1179 	}
1180 
1181 	canbus_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS));
1182 
1183 	net_pkt_cursor_init(pkt);
1184 	/* Forward all broadcasts */
1185 	if (net_eth_is_addr_broadcast((struct net_eth_addr *)lladdr->addr) ||
1186 	    net_eth_is_addr_multicast((struct net_eth_addr *)lladdr->addr)) {
1187 		if (!canbus_iface || !net_if_is_up(canbus_iface)) {
1188 			NET_ERR("No canbus iface");
1189 			return NET_CONTINUE;
1190 		}
1191 
1192 		clone_pkt = net_pkt_shallow_clone(pkt, NET_CAN_ALLOC_TIMEOUT);
1193 		if (clone_pkt) {
1194 			NET_DBG("Frame is %scast %02x:%02x:%02x:%02x:%02x:%02x,",
1195 				net_eth_is_addr_broadcast(
1196 					(struct net_eth_addr *)lladdr->addr) ? "broad" :
1197 				"multi",
1198 				lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
1199 				lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
1200 			net_pkt_set_family(clone_pkt, AF_INET6);
1201 			forward_eth_frame(clone_pkt, canbus_iface);
1202 		} else {
1203 			NET_ERR("PKT forwarding: cloning failed");
1204 		}
1205 
1206 		return NET_CONTINUE;
1207 	}
1208 
1209 	if (!canbus_iface || !net_if_is_up(canbus_iface)) {
1210 		NET_ERR("No canbus iface");
1211 		return NET_DROP;
1212 	}
1213 
1214 	/* This frame is for 6LoCAN only */
1215 	net_pkt_set_family(pkt, AF_INET6);
1216 	net_buf_pull(pkt->buffer, sizeof(struct net_eth_hdr));
1217 	forward_eth_frame(pkt, canbus_iface);
1218 	NET_DBG("Frame is for CANBUS: 0x%04x", canbus_get_dest_lladdr(pkt));
1219 
1220 	return NET_OK;
1221 }
1222 
forward_can_frame(struct net_pkt * pkt,struct net_if * eth_iface)1223 static void forward_can_frame(struct net_pkt *pkt, struct net_if *eth_iface)
1224 {
1225 	net_pkt_set_iface(pkt, eth_iface);
1226 	net_if_queue_tx(eth_iface, pkt);
1227 }
1228 
rewrite_icmp_hdr(struct net_pkt * pkt,struct net_icmp_hdr * icmp_hdr)1229 static void rewrite_icmp_hdr(struct net_pkt *pkt, struct net_icmp_hdr *icmp_hdr)
1230 {
1231 	int ret;
1232 
1233 	net_pkt_cursor_init(pkt);
1234 	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
1235 	ret = net_icmpv6_create(pkt, icmp_hdr->type, icmp_hdr->code);
1236 	if (ret) {
1237 		NET_ERR("Can't create ICMP HDR");
1238 		return;
1239 	}
1240 
1241 	net_pkt_cursor_init(pkt);
1242 	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
1243 	ret = net_icmpv6_finalize(pkt);
1244 	if (ret) {
1245 		NET_ERR("Can't finalize ICMP HDR");
1246 	}
1247 }
1248 
extend_llao(struct net_pkt * pkt,struct net_linkaddr * mac_addr)1249 static void extend_llao(struct net_pkt *pkt, struct net_linkaddr *mac_addr)
1250 {
1251 	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr);
1252 	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_opt_access,
1253 					      struct net_icmpv6_nd_opt_hdr);
1254 	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(llao_access,
1255 					      struct net_eth_addr);
1256 	struct net_pkt_cursor cursor_backup;
1257 	struct net_icmp_hdr *icmp_hdr;
1258 	struct net_icmpv6_nd_opt_hdr *icmp_opt_hdr;
1259 	uint8_t *llao, llao_backup[2];
1260 	int ret;
1261 
1262 	net_pkt_cursor_backup(pkt, &cursor_backup);
1263 	net_pkt_cursor_init(pkt);
1264 	net_pkt_set_overwrite(pkt, true);
1265 	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
1266 
1267 	if (net_calc_chksum(pkt, IPPROTO_ICMPV6) != 0U) {
1268 		NET_ERR("Invalid checksum");
1269 		return;
1270 	}
1271 
1272 	icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access);
1273 	if (!icmp_hdr) {
1274 		NET_ERR("No ICMP6 HDR");
1275 		goto done;
1276 	}
1277 
1278 	switch (icmp_hdr->type) {
1279 
1280 	case NET_ICMPV6_NS:
1281 		net_pkt_skip(pkt, sizeof(struct net_icmpv6_ns_hdr));
1282 		NET_DBG("Extend NS SLLAO");
1283 		break;
1284 
1285 	case NET_ICMPV6_NA:
1286 		net_pkt_skip(pkt, sizeof(struct net_icmpv6_na_hdr));
1287 		NET_DBG("Extend NA TLLAO");
1288 		break;
1289 
1290 	case NET_ICMPV6_RS:
1291 		net_pkt_skip(pkt, sizeof(struct net_icmpv6_rs_hdr));
1292 		NET_DBG("Extend RS SLLAO");
1293 		break;
1294 
1295 	case NET_ICMPV6_RA:
1296 		net_pkt_skip(pkt, sizeof(struct net_icmpv6_ra_hdr));
1297 		NET_DBG("Extend RA SLLAO");
1298 		break;
1299 
1300 	default:
1301 		goto done;
1302 	}
1303 
1304 	net_pkt_acknowledge_data(pkt, &icmp_access);
1305 
1306 	icmp_opt_hdr = (struct net_icmpv6_nd_opt_hdr *)
1307 		       net_pkt_get_data(pkt, &icmp_opt_access);
1308 	if (!icmp_opt_hdr) {
1309 		NET_DBG("No LLAO opt to extend");
1310 		goto done;
1311 	}
1312 
1313 	net_pkt_acknowledge_data(pkt, &icmp_opt_access);
1314 
1315 	if (icmp_opt_hdr->type != NET_ICMPV6_ND_OPT_SLLAO &&
1316 	    (icmp_hdr->type == NET_ICMPV6_NA &&
1317 	     icmp_opt_hdr->type != NET_ICMPV6_ND_OPT_TLLAO)) {
1318 		NET_DBG("opt was not LLAO");
1319 		goto done;
1320 	}
1321 
1322 	if (icmp_opt_hdr->len != 1) {
1323 		NET_ERR("LLAO len is %u. This should be 1 for 6LoCAN",
1324 			icmp_opt_hdr->len);
1325 		goto done;
1326 	}
1327 
1328 	llao = (uint8_t *)net_pkt_get_data(pkt, &llao_access);
1329 	if (!llao) {
1330 		NET_ERR("Can't read LLAO");
1331 		goto done;
1332 	}
1333 
1334 	memcpy(llao_backup, llao, sizeof(struct net_canbus_lladdr));
1335 	memcpy(llao, mac_addr->addr, mac_addr->len);
1336 
1337 	llao[4] = (llao[4] & 0xC0) | llao_backup[0];
1338 	llao[5] = llao_backup[1];
1339 
1340 	ret = net_pkt_set_data(pkt, &llao_access);
1341 	if (ret < 0) {
1342 		NET_ERR("Failed to write MAC to LLAO [%d]", ret);
1343 		goto done;
1344 	}
1345 
1346 	rewrite_icmp_hdr(pkt, icmp_hdr);
1347 
1348 	NET_DBG("LLAO extended to %02x:%02x:%02x:%02x:%02x:%02x",
1349 		llao[0], llao[1], llao[2], llao[3], llao[4], llao[5]);
1350 
1351 done:
1352 	net_pkt_cursor_restore(pkt, &cursor_backup);
1353 }
1354 
pkt_is_icmp(struct net_pkt * pkt)1355 static bool pkt_is_icmp(struct net_pkt *pkt)
1356 {
1357 	NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr);
1358 	struct net_ipv6_hdr *ipv6_hdr =
1359 		(struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access);
1360 
1361 	if (!ipv6_hdr) {
1362 		NET_ERR("No IPv6 HDR");
1363 		return false;
1364 	}
1365 
1366 	return (ipv6_hdr->nexthdr == IPPROTO_ICMPV6);
1367 }
1368 
swap_scr_lladdr(struct net_pkt * pkt,struct net_pkt * pkt_clone)1369 static void swap_scr_lladdr(struct net_pkt *pkt, struct net_pkt *pkt_clone)
1370 {
1371 	struct net_linkaddr *lladdr_origin = net_pkt_lladdr_src(pkt);
1372 	struct net_linkaddr *lladdr_clone = net_pkt_lladdr_src(pkt_clone);
1373 	size_t offset;
1374 
1375 	offset = lladdr_origin->addr - pkt->buffer->data;
1376 	lladdr_clone->addr = pkt_clone->buffer->data + offset;
1377 }
1378 
can_to_eth_lladdr(struct net_pkt * pkt,struct net_if * eth_iface,bool bcast)1379 static void can_to_eth_lladdr(struct net_pkt *pkt, struct net_if *eth_iface,
1380 			      bool bcast)
1381 {
1382 	uint16_t src_can_addr = canbus_get_src_lladdr(pkt);
1383 	struct net_linkaddr *lladdr_src = net_pkt_lladdr_src(pkt);
1384 	struct net_linkaddr *lladdr_dst;
1385 
1386 	if (bcast) {
1387 		lladdr_dst = net_pkt_lladdr_dst(pkt);
1388 		lladdr_dst->len = sizeof(struct net_eth_addr);
1389 		lladdr_dst->type = NET_LINK_ETHERNET;
1390 		lladdr_dst->addr = (uint8_t *)net_eth_broadcast_addr()->addr;
1391 	}
1392 
1393 	lladdr_src->addr = net_pkt_lladdr_src(pkt)->addr -
1394 			   (sizeof(struct net_eth_addr) - lladdr_src->len);
1395 	memcpy(lladdr_src->addr, net_if_get_link_addr(eth_iface)->addr,
1396 	       sizeof(struct net_eth_addr));
1397 	lladdr_src->addr[4] = (lladdr_src->addr[4] & 0xC0) | (src_can_addr >> 8U);
1398 	lladdr_src->addr[5] = src_can_addr & 0xFF;
1399 	lladdr_src->len = sizeof(struct net_eth_addr);
1400 	lladdr_src->type = NET_LINK_ETHERNET;
1401 }
1402 
translate_to_eth_frame(struct net_pkt * pkt,bool is_bcast,struct net_if * eth_iface)1403 void translate_to_eth_frame(struct net_pkt *pkt, bool is_bcast,
1404 			    struct net_if *eth_iface)
1405 {
1406 	struct net_linkaddr *dest_addr = net_pkt_lladdr_dst(pkt);
1407 	struct net_linkaddr *src_addr = net_pkt_lladdr_src(pkt);
1408 	bool is_icmp;
1409 
1410 	is_icmp = pkt_is_icmp(pkt);
1411 
1412 	can_to_eth_lladdr(pkt, eth_iface, is_bcast);
1413 	canbus_print_ip_hdr((struct net_ipv6_hdr *)net_pkt_cursor_get_pos(pkt));
1414 	NET_DBG("Forward frame to %02x:%02x:%02x:%02x:%02x:%02x. "
1415 		"Src: %02x:%02x:%02x:%02x:%02x:%02x",
1416 		dest_addr->addr[0], dest_addr->addr[1], dest_addr->addr[2],
1417 		dest_addr->addr[3], dest_addr->addr[4], dest_addr->addr[5],
1418 		src_addr->addr[0], src_addr->addr[1], src_addr->addr[2],
1419 		src_addr->addr[3], src_addr->addr[4], src_addr->addr[5]);
1420 
1421 	if (is_icmp) {
1422 		extend_llao(pkt, net_if_get_link_addr(eth_iface));
1423 	}
1424 }
1425 
canbus_forward_to_eth(struct net_pkt * pkt)1426 static enum net_verdict canbus_forward_to_eth(struct net_pkt *pkt)
1427 {
1428 	struct net_pkt *pkt_clone;
1429 	struct net_if *eth_iface;
1430 
1431 	eth_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
1432 	if (!eth_iface || !net_if_is_up(eth_iface)) {
1433 		NET_ERR("No Ethernet iface available");
1434 		if (canbus_is_for_translator(pkt)) {
1435 			return NET_DROP;
1436 		} else {
1437 			return NET_CONTINUE;
1438 		}
1439 	}
1440 
1441 	if (canbus_dest_is_mcast(pkt)) {
1442 		/* net_pkt_clone can't be called on a pkt where
1443 		 * net_buf_pull was called on. We need to clone
1444 		 * first and then finish the pkt.
1445 		 */
1446 		pkt_clone = net_pkt_clone(pkt, NET_CAN_ALLOC_TIMEOUT);
1447 		if (pkt_clone) {
1448 			swap_scr_lladdr(pkt, pkt_clone);
1449 			canbus_finish_pkt(pkt_clone);
1450 			translate_to_eth_frame(pkt_clone, true, eth_iface);
1451 			forward_can_frame(pkt_clone, eth_iface);
1452 			NET_DBG("Len: %zu", net_pkt_get_len(pkt_clone));
1453 		} else {
1454 			NET_ERR("Failed to clone pkt");
1455 		}
1456 	}
1457 
1458 	canbus_finish_pkt(pkt);
1459 
1460 	if (net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET) {
1461 		translate_to_eth_frame(pkt, false, eth_iface);
1462 		forward_can_frame(pkt, eth_iface);
1463 		return NET_OK;
1464 	}
1465 
1466 	return NET_CONTINUE;
1467 }
1468 #else
1469 #define canbus_forward_to_eth(...) 0
1470 #endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/
1471 
canbus_recv(struct net_if * iface,struct net_pkt * pkt)1472 static enum net_verdict canbus_recv(struct net_if *iface,
1473 				    struct net_pkt *pkt)
1474 {
1475 	struct net_linkaddr *lladdr = net_pkt_lladdr_src(pkt);
1476 	enum net_verdict ret = NET_DROP;
1477 
1478 	if (pkt->canbus_rx_ctx) {
1479 		if (lladdr->len == sizeof(struct net_canbus_lladdr)) {
1480 			NET_DBG("Push reassembled packet from 0x%04x through "
1481 				"stack again", canbus_get_src_lladdr(pkt));
1482 		} else {
1483 			NET_DBG("Push reassembled packet from "
1484 				"%02x:%02x:%02x:%02x:%02x:%02x through stack again",
1485 				lladdr->addr[0], lladdr->addr[1], lladdr->addr[2],
1486 				lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]);
1487 		}
1488 
1489 		if (pkt->canbus_rx_ctx->state == NET_CAN_RX_STATE_FIN) {
1490 			canbus_rx_finish(pkt);
1491 
1492 			if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)) {
1493 				ret = canbus_forward_to_eth(pkt);
1494 			} else {
1495 				canbus_finish_pkt(pkt);
1496 				canbus_print_ip_hdr(NET_IPV6_HDR(pkt));
1497 				ret = NET_CONTINUE;
1498 			}
1499 		} else {
1500 			NET_ERR("Expected pkt in FIN state");
1501 		}
1502 	} else {
1503 		ret = canbus_process_frame(pkt);
1504 	}
1505 
1506 	return ret;
1507 }
1508 
canbus_send_dad_request(const struct device * net_can_dev,struct net_canbus_lladdr * ll_addr)1509 static inline int canbus_send_dad_request(const struct device *net_can_dev,
1510 					  struct net_canbus_lladdr *ll_addr)
1511 {
1512 	const struct net_can_api *api = net_can_dev->api;
1513 	struct zcan_frame frame;
1514 	int ret;
1515 
1516 	canbus_set_frame_datalength(&frame, 0);
1517 	frame.rtr = CAN_REMOTEREQUEST;
1518 	frame.id_type = CAN_EXTENDED_IDENTIFIER;
1519 	frame.id = canbus_addr_to_id(ll_addr->addr,
1520 					 sys_rand32_get() & CAN_NET_IF_ADDR_MASK);
1521 
1522 	ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER);
1523 	if (ret != CAN_TX_OK) {
1524 		NET_ERR("Sending DAD request failed [%d]", ret);
1525 		return -EIO;
1526 	}
1527 
1528 	return 0;
1529 }
1530 
canbus_send_dad_resp_cb(int error,void * cb_arg)1531 static void canbus_send_dad_resp_cb(int error, void *cb_arg)
1532 {
1533 	static uint8_t fail_cnt;
1534 	struct k_work *work = (struct k_work *)cb_arg;
1535 
1536 	if (error != 0) {
1537 		NET_ERR("Failed to send dad response [%u]", error);
1538 		if (error != CAN_TX_BUS_OFF &&
1539 		    fail_cnt < NET_CAN_DAD_SEND_RETRY) {
1540 			k_work_submit_to_queue(&net_canbus_workq, work);
1541 		}
1542 
1543 		fail_cnt++;
1544 	} else {
1545 		fail_cnt = 0;
1546 	}
1547 }
1548 
canbus_send_dad_response(struct k_work * item)1549 static inline void canbus_send_dad_response(struct k_work *item)
1550 {
1551 	struct canbus_net_ctx *ctx = CONTAINER_OF(item, struct canbus_net_ctx,
1552 						  dad_work);
1553 	struct net_if *iface = ctx->iface;
1554 	struct net_linkaddr *ll_addr = net_if_get_link_addr(iface);
1555 	const struct device *net_can_dev = net_if_get_device(iface);
1556 	const struct net_can_api *api = net_can_dev->api;
1557 	struct zcan_frame frame;
1558 	int ret;
1559 
1560 	canbus_set_frame_datalength(&frame, 0);
1561 	frame.rtr = CAN_DATAFRAME;
1562 	frame.id_type = CAN_EXTENDED_IDENTIFIER;
1563 	frame.id = canbus_addr_to_id(NET_CAN_DAD_ADDR,
1564 					 ntohs(UNALIGNED_GET((uint16_t *) ll_addr->addr)));
1565 
1566 	ret = api->send(net_can_dev, &frame, canbus_send_dad_resp_cb, item,
1567 			K_FOREVER);
1568 	if (ret != CAN_TX_OK) {
1569 		NET_ERR("Sending SF failed [%d]", ret);
1570 	} else {
1571 		NET_INFO("DAD response sent");
1572 	}
1573 }
1574 
canbus_detach_filter(const struct device * net_can_dev,int filter_id)1575 static inline void canbus_detach_filter(const struct device *net_can_dev,
1576 					int filter_id)
1577 {
1578 	const struct net_can_api *api = net_can_dev->api;
1579 
1580 	api->detach_filter(net_can_dev, filter_id);
1581 }
1582 
canbus_dad_resp_cb(struct zcan_frame * frame,void * arg)1583 static void canbus_dad_resp_cb(struct zcan_frame *frame, void *arg)
1584 {
1585 	struct k_sem *dad_sem = (struct k_sem *)arg;
1586 
1587 	k_sem_give(dad_sem);
1588 }
1589 
1590 static inline
canbus_attach_dad_resp_filter(const struct device * net_can_dev,struct net_canbus_lladdr * ll_addr,struct k_sem * dad_sem)1591 int canbus_attach_dad_resp_filter(const struct device *net_can_dev,
1592 				  struct net_canbus_lladdr *ll_addr,
1593 				  struct k_sem *dad_sem)
1594 {
1595 	const struct net_can_api *api = net_can_dev->api;
1596 	struct zcan_filter filter = {
1597 		.id_type = CAN_EXTENDED_IDENTIFIER,
1598 		.rtr = CAN_DATAFRAME,
1599 		.rtr_mask = 1,
1600 		.id_mask = CAN_EXT_ID_MASK
1601 	};
1602 	int filter_id;
1603 
1604 	filter.id = canbus_addr_to_id(NET_CAN_DAD_ADDR, ll_addr->addr);
1605 
1606 	filter_id = api->attach_filter(net_can_dev, canbus_dad_resp_cb,
1607 				       dad_sem, &filter);
1608 	if (filter_id == CAN_NO_FREE_FILTER) {
1609 		NET_ERR("Can't attach dad response filter");
1610 	}
1611 
1612 	return filter_id;
1613 }
1614 
canbus_dad_request_cb(struct zcan_frame * frame,void * arg)1615 static void canbus_dad_request_cb(struct zcan_frame *frame, void *arg)
1616 {
1617 	struct k_work *work = (struct k_work *)arg;
1618 
1619 	k_work_submit_to_queue(&net_canbus_workq, work);
1620 }
1621 
canbus_attach_dad_filter(const struct device * net_can_dev,struct net_canbus_lladdr * ll_addr,struct k_work * dad_work)1622 static inline int canbus_attach_dad_filter(const struct device *net_can_dev,
1623 					   struct net_canbus_lladdr *ll_addr,
1624 					   struct k_work *dad_work)
1625 {
1626 	const struct net_can_api *api = net_can_dev->api;
1627 	struct zcan_filter filter = {
1628 		.id_type = CAN_EXTENDED_IDENTIFIER,
1629 		.rtr = CAN_REMOTEREQUEST,
1630 		.rtr_mask = 1,
1631 		.id_mask = (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS)
1632 	};
1633 	int filter_id;
1634 
1635 	filter.id = canbus_addr_to_id(ll_addr->addr, 0);
1636 
1637 	filter_id = api->attach_filter(net_can_dev, canbus_dad_request_cb,
1638 				       dad_work, &filter);
1639 	if (filter_id == CAN_NO_FREE_FILTER) {
1640 		NET_ERR("Can't attach dad filter");
1641 	}
1642 
1643 	return filter_id;
1644 }
1645 
canbus_init_ll_addr(struct net_if * iface)1646 static inline int canbus_init_ll_addr(struct net_if *iface)
1647 {
1648 	struct canbus_net_ctx *ctx = net_if_l2_data(iface);
1649 	const struct device *net_can_dev = net_if_get_device(iface);
1650 	int dad_resp_filter_id = CAN_NET_FILTER_NOT_SET;
1651 	struct net_canbus_lladdr ll_addr;
1652 	int ret;
1653 	struct k_sem dad_sem;
1654 
1655 #if defined(CONFIG_NET_L2_CANBUS_USE_FIXED_ADDR)
1656 	ll_addr.addr = CONFIG_NET_L2_CANBUS_FIXED_ADDR;
1657 #else
1658 	do {
1659 		ll_addr.addr = sys_rand32_get() % (NET_CAN_MAX_ADDR + 1);
1660 	} while (ll_addr.addr < NET_CAN_MIN_ADDR);
1661 #endif
1662 
1663 	/* Add address early for DAD response */
1664 	ctx->ll_addr = sys_cpu_to_be16(ll_addr.addr);
1665 	net_if_set_link_addr(iface, (uint8_t *)&ctx->ll_addr, sizeof(ll_addr),
1666 			     NET_LINK_CANBUS);
1667 
1668 	dad_resp_filter_id = canbus_attach_dad_resp_filter(net_can_dev, &ll_addr,
1669 							   &dad_sem);
1670 	if (dad_resp_filter_id < 0) {
1671 		return -EIO;
1672 	}
1673 	/*
1674 	 * Attach this filter now to defend this address instantly.
1675 	 * This filter is not called for own DAD because loopback is not
1676 	 * enabled.
1677 	 */
1678 	ctx->dad_filter_id = canbus_attach_dad_filter(net_can_dev, &ll_addr,
1679 						      &ctx->dad_work);
1680 	if (ctx->dad_filter_id < 0) {
1681 		ret = -EIO;
1682 		goto dad_err;
1683 	}
1684 
1685 	k_sem_init(&dad_sem, 0, 1);
1686 	ret = canbus_send_dad_request(net_can_dev, &ll_addr);
1687 	if (ret) {
1688 		ret = -EIO;
1689 		goto dad_err;
1690 	}
1691 
1692 	ret = k_sem_take(&dad_sem, NET_CAN_DAD_TIMEOUT);
1693 	canbus_detach_filter(net_can_dev, dad_resp_filter_id);
1694 	dad_resp_filter_id = CAN_NET_FILTER_NOT_SET;
1695 
1696 	if (ret != -EAGAIN) {
1697 		NET_INFO("DAD failed");
1698 		ret = -EAGAIN;
1699 		goto dad_err;
1700 	}
1701 
1702 	return 0;
1703 
1704 dad_err:
1705 	net_if_set_link_addr(iface, NULL, 0, NET_LINK_CANBUS);
1706 	if (ctx->dad_filter_id != CAN_NET_FILTER_NOT_SET) {
1707 		canbus_detach_filter(net_can_dev, ctx->dad_filter_id);
1708 		ctx->dad_filter_id = CAN_NET_FILTER_NOT_SET;
1709 	}
1710 
1711 	if (dad_resp_filter_id != CAN_NET_FILTER_NOT_SET) {
1712 		canbus_detach_filter(net_can_dev, dad_resp_filter_id);
1713 	}
1714 
1715 	return ret;
1716 }
1717 
queue_handler(struct canbus_net_ctx * ctx)1718 static void queue_handler(struct canbus_net_ctx *ctx)
1719 {
1720 	struct k_poll_event events[] = {
1721 		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
1722 					 K_POLL_MODE_NOTIFY_ONLY,
1723 					 &ctx->tx_queue),
1724 		K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE,
1725 					 K_POLL_MODE_NOTIFY_ONLY,
1726 					 &ctx->rx_err_queue),
1727 	};
1728 
1729 	struct net_pkt *pkt;
1730 	int ret;
1731 
1732 	while (1) {
1733 		ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
1734 		if (ret) {
1735 			continue;
1736 		}
1737 
1738 		if (events[0].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
1739 			pkt = k_fifo_get(&ctx->tx_queue, K_NO_WAIT);
1740 			if (pkt != NULL) {
1741 				canbus_tx_work(pkt);
1742 			}
1743 
1744 			events[0].state = K_POLL_STATE_NOT_READY;
1745 		}
1746 
1747 		if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) {
1748 			pkt = k_fifo_get(&ctx->rx_err_queue, K_NO_WAIT);
1749 			if (pkt != NULL) {
1750 				rx_err_work_handler(pkt);
1751 			}
1752 
1753 			events[1].state = K_POLL_STATE_NOT_READY;
1754 		}
1755 	}
1756 }
1757 
net_6locan_init(struct net_if * iface)1758 void net_6locan_init(struct net_if *iface)
1759 {
1760 	struct canbus_net_ctx *ctx = net_if_l2_data(iface);
1761 	int thread_priority;
1762 	k_tid_t tid;
1763 	int i;
1764 
1765 	NET_DBG("Init CAN net interface");
1766 
1767 	for (i = 0; i < ARRAY_SIZE(l2_ctx.tx_ctx); i++) {
1768 		l2_ctx.tx_ctx[i].state = NET_CAN_TX_STATE_UNUSED;
1769 	}
1770 
1771 	for (i = 0; i < ARRAY_SIZE(l2_ctx.rx_ctx); i++) {
1772 		l2_ctx.rx_ctx[i].state = NET_CAN_RX_STATE_UNUSED;
1773 	}
1774 
1775 	ctx->dad_filter_id = CAN_NET_FILTER_NOT_SET;
1776 	ctx->iface = iface;
1777 	k_work_init(&ctx->dad_work, canbus_send_dad_response);
1778 
1779 	k_mutex_init(&l2_ctx.tx_ctx_mtx);
1780 	k_mutex_init(&l2_ctx.rx_ctx_mtx);
1781 	k_sem_init(&l2_ctx.tx_sem, 1, K_SEM_MAX_LIMIT);
1782 
1783 	/* This work queue should have precedence over the tx stream
1784 	 * TODO thread_priority = tx_tc2thread(NET_TC_TX_COUNT -1) - 1;
1785 	 */
1786 	if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) {
1787 		thread_priority = K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1);
1788 	} else {
1789 		thread_priority = K_PRIO_PREEMPT(6);
1790 	}
1791 
1792 	k_work_queue_start(&net_canbus_workq, net_canbus_stack,
1793 			   K_KERNEL_STACK_SIZEOF(net_canbus_stack),
1794 			   thread_priority, NULL);
1795 	k_thread_name_set(&net_canbus_workq.thread, "isotp_work");
1796 	NET_DBG("Workq started. Thread ID: %p", &net_canbus_workq.thread);
1797 
1798 	k_fifo_init(&ctx->tx_queue);
1799 	k_fifo_init(&ctx->rx_err_queue);
1800 
1801 	tid = k_thread_create(&ctx->queue_handler, ctx->queue_stack,
1802 			      K_KERNEL_STACK_SIZEOF(ctx->queue_stack),
1803 			      (k_thread_entry_t)queue_handler,
1804 			      ctx, NULL, NULL,
1805 			      thread_priority, 0, K_FOREVER);
1806 	if (!tid) {
1807 		NET_ERR("Cannot create queue handler thread for %d",
1808 			net_if_get_by_iface(iface));
1809 	} else {
1810 		if (IS_ENABLED(CONFIG_THREAD_NAME)) {
1811 #define MAX_NAME_LEN sizeof("isotp[01]")
1812 			char name[MAX_NAME_LEN];
1813 
1814 			snprintk(name, sizeof(name), "isotp[%d]",
1815 				net_if_get_by_iface(iface));
1816 			k_thread_name_set(tid, name);
1817 		}
1818 
1819 		k_thread_start(tid);
1820 	}
1821 }
1822 
canbus_enable(struct net_if * iface,bool state)1823 static int canbus_enable(struct net_if *iface, bool state)
1824 {
1825 	const struct device *net_can_dev = net_if_get_device(iface);
1826 	const struct net_can_api *api = net_can_dev->api;
1827 	struct canbus_net_ctx *ctx = net_if_l2_data(iface);
1828 	int dad_retry_cnt, ret;
1829 
1830 	NET_DBG("start to bring iface %p %s", iface, state ? "up" : "down");
1831 
1832 	if (state) {
1833 		for (dad_retry_cnt = CONFIG_NET_L2_CANBUS_DAD_RETRIES;
1834 		     dad_retry_cnt; dad_retry_cnt--) {
1835 			ret = canbus_init_ll_addr(iface);
1836 			if (ret == 0) {
1837 				break;
1838 			} else if (ret == -EIO) {
1839 				return -EIO;
1840 			}
1841 		}
1842 
1843 		if (ret != 0) {
1844 			return ret;
1845 		}
1846 
1847 	} else {
1848 		if (ctx->dad_filter_id != CAN_NET_FILTER_NOT_SET) {
1849 			canbus_detach_filter(net_can_dev, ctx->dad_filter_id);
1850 		}
1851 	}
1852 
1853 	ret = api->enable(net_can_dev, state);
1854 	if (!ret) {
1855 		NET_DBG("Iface %p is up", iface);
1856 	}
1857 
1858 	return ret;
1859 }
1860 
canbus_net_flags(struct net_if * iface)1861 static enum net_l2_flags canbus_net_flags(struct net_if *iface)
1862 {
1863 	return NET_L2_MULTICAST;
1864 }
1865 
1866 NET_L2_INIT(CANBUS_L2, canbus_recv, canbus_send, canbus_enable,
1867 	    canbus_net_flags);
1868