Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

can: bcm: add recvmsg flags for own, local and remote traffic

CAN RAW sockets allow userspace to tell if a received CAN frame comes
from the same socket, another socket on the same host, or another host.
See commit 1e55659ce6dd ("can-raw: add msg_flags to distinguish local
traffic"). However, this feature is missing in CAN BCM sockets.

Add the same feature to CAN BCM sockets. When reading a received frame
(opcode RX_CHANGED) using recvmsg, two flags in msg->msg_flags may be
set following the previous convention (from CAN RAW), to distinguish
between 'own', 'local' and 'remote' CAN traffic.

Update the documentation to reflect this change.

Signed-off-by: Nicolas Maier <nicolas.maier.dev@gmail.com>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://lore.kernel.org/all/20240120081018.2319-1-socketcan@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Nicolas Maier and committed by
Marc Kleine-Budde
fec846fa 970cb1ce

+75 -28
+18 -16
Documentation/networking/can.rst
··· 444 444 #define CANFD_MTU (sizeof(struct canfd_frame)) == 72 => CAN FD frame 445 445 446 446 447 + Returned Message Flags 448 + ---------------------- 449 + 450 + When using the system call recvmsg(2) on a RAW or a BCM socket, the 451 + msg->msg_flags field may contain the following flags: 452 + 453 + MSG_DONTROUTE: 454 + set when the received frame was created on the local host. 455 + 456 + MSG_CONFIRM: 457 + set when the frame was sent via the socket it is received on. 458 + This flag can be interpreted as a 'transmission confirmation' when the 459 + CAN driver supports the echo of frames on driver level, see 460 + :ref:`socketcan-local-loopback1` and :ref:`socketcan-local-loopback2`. 461 + (Note: In order to receive such messages on a RAW socket, 462 + CAN_RAW_RECV_OWN_MSGS must be set.) 463 + 464 + 447 465 .. _socketcan-raw-sockets: 448 466 449 467 RAW Protocol Sockets with can_filters (SOCK_RAW) ··· 709 691 This is useful especially when the filterset is a combination of filters 710 692 where the CAN_INV_FILTER flag is set in order to notch single CAN IDs or 711 693 CAN ID ranges from the incoming traffic. 712 - 713 - 714 - RAW Socket Returned Message Flags 715 - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 716 - 717 - When using recvmsg() call, the msg->msg_flags may contain following flags: 718 - 719 - MSG_DONTROUTE: 720 - set when the received frame was created on the local host. 721 - 722 - MSG_CONFIRM: 723 - set when the frame was sent via the socket it is received on. 724 - This flag can be interpreted as a 'transmission confirmation' when the 725 - CAN driver supports the echo of frames on driver level, see 726 - :ref:`socketcan-local-loopback1` and :ref:`socketcan-local-loopback2`. 727 - In order to receive such messages, CAN_RAW_RECV_OWN_MSGS must be set. 728 694 729 695 730 696 Broadcast Manager Protocol Sockets (SOCK_DGRAM)
+57 -12
net/can/bcm.c
··· 72 72 #define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60) 73 73 74 74 /* use of last_frames[index].flags */ 75 + #define RX_LOCAL 0x10 /* frame was created on the local host */ 76 + #define RX_OWN 0x20 /* frame was sent via the socket it was received on */ 75 77 #define RX_RECV 0x40 /* received data for this element */ 76 78 #define RX_THR 0x80 /* element not been sent due to throttle feature */ 77 - #define BCM_CAN_FLAGS_MASK 0x3F /* to clean private flags after usage */ 79 + #define BCM_CAN_FLAGS_MASK 0x0F /* to clean private flags after usage */ 78 80 79 81 /* get best masking value for can_rx_register() for a given single can_id */ 80 82 #define REGMASK(id) ((id & CAN_EFF_FLAG) ? \ ··· 139 137 static LIST_HEAD(bcm_notifier_list); 140 138 static DEFINE_SPINLOCK(bcm_notifier_lock); 141 139 static struct bcm_sock *bcm_busy_notifier; 140 + 141 + /* Return pointer to store the extra msg flags for bcm_recvmsg(). 142 + * We use the space of one unsigned int beyond the 'struct sockaddr_can' 143 + * in skb->cb. 144 + */ 145 + static inline unsigned int *bcm_flags(struct sk_buff *skb) 146 + { 147 + /* return pointer after struct sockaddr_can */ 148 + return (unsigned int *)(&((struct sockaddr_can *)skb->cb)[1]); 149 + } 142 150 143 151 static inline struct bcm_sock *bcm_sk(const struct sock *sk) 144 152 { ··· 337 325 struct sock *sk = op->sk; 338 326 unsigned int datalen = head->nframes * op->cfsiz; 339 327 int err; 328 + unsigned int *pflags; 340 329 341 330 skb = alloc_skb(sizeof(*head) + datalen, gfp_any()); 342 331 if (!skb) 343 332 return; 344 333 345 334 skb_put_data(skb, head, sizeof(*head)); 335 + 336 + /* ensure space for sockaddr_can and msg flags */ 337 + sock_skb_cb_check_size(sizeof(struct sockaddr_can) + 338 + sizeof(unsigned int)); 339 + 340 + /* initialize msg flags */ 341 + pflags = bcm_flags(skb); 342 + *pflags = 0; 346 343 347 344 if (head->nframes) { 348 345 /* CAN frames starting here */ ··· 365 344 * relevant for updates that are generated by the 366 345 * BCM, where nframes is 1 367 346 */ 368 - if (head->nframes == 1) 347 + if (head->nframes == 1) { 348 + if (firstframe->flags & RX_LOCAL) 349 + *pflags |= MSG_DONTROUTE; 350 + if (firstframe->flags & RX_OWN) 351 + *pflags |= MSG_CONFIRM; 352 + 369 353 firstframe->flags &= BCM_CAN_FLAGS_MASK; 354 + } 370 355 } 371 356 372 357 if (has_timestamp) { ··· 387 360 * containing the interface index. 388 361 */ 389 362 390 - sock_skb_cb_check_size(sizeof(struct sockaddr_can)); 391 363 addr = (struct sockaddr_can *)skb->cb; 392 364 memset(addr, 0, sizeof(*addr)); 393 365 addr->can_family = AF_CAN; ··· 470 444 op->frames_filtered = op->frames_abs = 0; 471 445 472 446 /* this element is not throttled anymore */ 473 - data->flags &= (BCM_CAN_FLAGS_MASK|RX_RECV); 447 + data->flags &= ~RX_THR; 474 448 475 449 memset(&head, 0, sizeof(head)); 476 450 head.opcode = RX_CHANGED; ··· 491 465 */ 492 466 static void bcm_rx_update_and_send(struct bcm_op *op, 493 467 struct canfd_frame *lastdata, 494 - const struct canfd_frame *rxdata) 468 + const struct canfd_frame *rxdata, 469 + unsigned char traffic_flags) 495 470 { 496 471 memcpy(lastdata, rxdata, op->cfsiz); 497 472 498 473 /* mark as used and throttled by default */ 499 474 lastdata->flags |= (RX_RECV|RX_THR); 475 + 476 + /* add own/local/remote traffic flags */ 477 + lastdata->flags |= traffic_flags; 500 478 501 479 /* throttling mode inactive ? */ 502 480 if (!op->kt_ival2) { ··· 538 508 * received data stored in op->last_frames[] 539 509 */ 540 510 static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index, 541 - const struct canfd_frame *rxdata) 511 + const struct canfd_frame *rxdata, 512 + unsigned char traffic_flags) 542 513 { 543 514 struct canfd_frame *cf = op->frames + op->cfsiz * index; 544 515 struct canfd_frame *lcf = op->last_frames + op->cfsiz * index; ··· 552 521 553 522 if (!(lcf->flags & RX_RECV)) { 554 523 /* received data for the first time => send update to user */ 555 - bcm_rx_update_and_send(op, lcf, rxdata); 524 + bcm_rx_update_and_send(op, lcf, rxdata, traffic_flags); 556 525 return; 557 526 } 558 527 ··· 560 529 for (i = 0; i < rxdata->len; i += 8) { 561 530 if ((get_u64(cf, i) & get_u64(rxdata, i)) != 562 531 (get_u64(cf, i) & get_u64(lcf, i))) { 563 - bcm_rx_update_and_send(op, lcf, rxdata); 532 + bcm_rx_update_and_send(op, lcf, rxdata, traffic_flags); 564 533 return; 565 534 } 566 535 } ··· 568 537 if (op->flags & RX_CHECK_DLC) { 569 538 /* do a real check in CAN frame length */ 570 539 if (rxdata->len != lcf->len) { 571 - bcm_rx_update_and_send(op, lcf, rxdata); 540 + bcm_rx_update_and_send(op, lcf, rxdata, traffic_flags); 572 541 return; 573 542 } 574 543 } ··· 675 644 struct bcm_op *op = (struct bcm_op *)data; 676 645 const struct canfd_frame *rxframe = (struct canfd_frame *)skb->data; 677 646 unsigned int i; 647 + unsigned char traffic_flags; 678 648 679 649 if (op->can_id != rxframe->can_id) 680 650 return; ··· 705 673 return; 706 674 } 707 675 676 + /* compute flags to distinguish between own/local/remote CAN traffic */ 677 + traffic_flags = 0; 678 + if (skb->sk) { 679 + traffic_flags |= RX_LOCAL; 680 + if (skb->sk == op->sk) 681 + traffic_flags |= RX_OWN; 682 + } 683 + 708 684 if (op->flags & RX_FILTER_ID) { 709 685 /* the easiest case */ 710 - bcm_rx_update_and_send(op, op->last_frames, rxframe); 686 + bcm_rx_update_and_send(op, op->last_frames, rxframe, 687 + traffic_flags); 711 688 goto rx_starttimer; 712 689 } 713 690 714 691 if (op->nframes == 1) { 715 692 /* simple compare with index 0 */ 716 - bcm_rx_cmp_to_index(op, 0, rxframe); 693 + bcm_rx_cmp_to_index(op, 0, rxframe, traffic_flags); 717 694 goto rx_starttimer; 718 695 } 719 696 ··· 739 698 if ((get_u64(op->frames, 0) & get_u64(rxframe, 0)) == 740 699 (get_u64(op->frames, 0) & 741 700 get_u64(op->frames + op->cfsiz * i, 0))) { 742 - bcm_rx_cmp_to_index(op, i, rxframe); 701 + bcm_rx_cmp_to_index(op, i, rxframe, 702 + traffic_flags); 743 703 break; 744 704 } 745 705 } ··· 1716 1674 msg->msg_namelen = BCM_MIN_NAMELEN; 1717 1675 memcpy(msg->msg_name, skb->cb, msg->msg_namelen); 1718 1676 } 1677 + 1678 + /* assign the flags that have been recorded in bcm_send_to_user() */ 1679 + msg->msg_flags |= *(bcm_flags(skb)); 1719 1680 1720 1681 skb_free_datagram(sk, skb); 1721 1682