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