]> git.baikalelectronics.ru Git - kernel.git/commitdiff
can: length: can_skb_get_frame_len(): introduce function to get data length of frame...
authorVincent Mailhol <mailhol.vincent@wanadoo.fr>
Mon, 11 Jan 2021 14:19:25 +0000 (15:19 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Thu, 14 Jan 2021 07:43:42 +0000 (08:43 +0100)
This patch adds the function can_skb_get_frame_len() which returns the length
of a CAN frame on the data link layer, including Start-of-frame, Identifier,
various other bits, the actual data, the CRC, the End-of-frame, the Inter frame
spacing.

Co-developed-by: Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>
Signed-off-by: Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>
Co-developed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Acked-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Reviewed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Co-developed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Link: https://lore.kernel.org/r/20210111141930.693847-11-mkl@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/dev/length.c
include/linux/can/length.h

index 64673a8d1234e03af4a13fb72f8e9284c4eda6a9..d35c4e82314d1481bd050b141eb3b417ca139b9c 100644 (file)
@@ -38,3 +38,53 @@ u8 can_fd_len2dlc(u8 len)
        return len2dlc[len];
 }
 EXPORT_SYMBOL_GPL(can_fd_len2dlc);
+
+/**
+ * can_skb_get_frame_len() - Calculate the CAN Frame length in bytes
+ *     of a given skb.
+ * @skb: socket buffer of a CAN message.
+ *
+ * Do a rough calculation: bit stuffing is ignored and length in bits
+ * is rounded up to a length in bytes.
+ *
+ * Rationale: this function is to be used for the BQL functions
+ * (netdev_sent_queue() and netdev_completed_queue()) which expect a
+ * value in bytes. Just using skb->len is insufficient because it will
+ * return the constant value of CAN(FD)_MTU. Doing the bit stuffing
+ * calculation would be too expensive in term of computing resources
+ * for no noticeable gain.
+ *
+ * Remarks: The payload of CAN FD frames with BRS flag are sent at a
+ * different bitrate. Currently, the can-utils canbusload tool does
+ * not support CAN-FD yet and so we could not run any benchmark to
+ * measure the impact. There might be possible improvement here.
+ *
+ * Return: length in bytes.
+ */
+unsigned int can_skb_get_frame_len(const struct sk_buff *skb)
+{
+       const struct canfd_frame *cf = (const struct canfd_frame *)skb->data;
+       u8 len;
+
+       if (can_is_canfd_skb(skb))
+               len = canfd_sanitize_len(cf->len);
+       else if (cf->can_id & CAN_RTR_FLAG)
+               len = 0;
+       else
+               len = cf->len;
+
+       if (can_is_canfd_skb(skb)) {
+               if (cf->can_id & CAN_EFF_FLAG)
+                       len += CANFD_FRAME_OVERHEAD_EFF;
+               else
+                       len += CANFD_FRAME_OVERHEAD_SFF;
+       } else {
+               if (cf->can_id & CAN_EFF_FLAG)
+                       len += CAN_FRAME_OVERHEAD_EFF;
+               else
+                       len += CAN_FRAME_OVERHEAD_SFF;
+       }
+
+       return len;
+}
+EXPORT_SYMBOL_GPL(can_skb_get_frame_len);
index b2313b2a0b02430813713f885bb48338aff9fdb9..6995092b774ec6f67e07b2f5cc7ea26d8bd20ab6 100644 (file)
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Copyright (C) 2020 Oliver Hartkopp <socketcan@hartkopp.net>
+ * Copyright (C) 2020 Marc Kleine-Budde <kernel@pengutronix.de>
  */
 
 #ifndef _CAN_LENGTH_H
 #define _CAN_LENGTH_H
 
+/*
+ * Size of a Classical CAN Standard Frame
+ *
+ * Name of Field                       Bits
+ * ---------------------------------------------------------
+ * Start-of-frame                      1
+ * Identifier                          11
+ * Remote transmission request (RTR)   1
+ * Identifier extension bit (IDE)      1
+ * Reserved bit (r0)                   1
+ * Data length code (DLC)              4
+ * Data field                          0...64
+ * CRC                                 15
+ * CRC delimiter                       1
+ * ACK slot                            1
+ * ACK delimiter                       1
+ * End-of-frame (EOF)                  7
+ * Inter frame spacing                 3
+ *
+ * rounded up and ignoring bitstuffing
+ */
+#define CAN_FRAME_OVERHEAD_SFF DIV_ROUND_UP(47, 8)
+
+/*
+ * Size of a Classical CAN Extended Frame
+ *
+ * Name of Field                       Bits
+ * ---------------------------------------------------------
+ * Start-of-frame                      1
+ * Identifier A                                11
+ * Substitute remote request (SRR)     1
+ * Identifier extension bit (IDE)      1
+ * Identifier B                                18
+ * Remote transmission request (RTR)   1
+ * Reserved bits (r1, r0)              2
+ * Data length code (DLC)              4
+ * Data field                          0...64
+ * CRC                                 15
+ * CRC delimiter                       1
+ * ACK slot                            1
+ * ACK delimiter                       1
+ * End-of-frame (EOF)                  7
+ * Inter frame spacing                 3
+ *
+ * rounded up and ignoring bitstuffing
+ */
+#define CAN_FRAME_OVERHEAD_EFF DIV_ROUND_UP(67, 8)
+
+/*
+ * Size of a CAN-FD Standard Frame
+ *
+ * Name of Field                       Bits
+ * ---------------------------------------------------------
+ * Start-of-frame                      1
+ * Identifier                          11
+ * Reserved bit (r1)                   1
+ * Identifier extension bit (IDE)      1
+ * Flexible data rate format (FDF)     1
+ * Reserved bit (r0)                   1
+ * Bit Rate Switch (BRS)               1
+ * Error Status Indicator (ESI)                1
+ * Data length code (DLC)              4
+ * Data field                          0...512
+ * Stuff Bit Count (SBC)               0...16: 4 20...64:5
+ * CRC                                 0...16: 17 20...64:21
+ * CRC delimiter (CD)                  1
+ * ACK slot (AS)                       1
+ * ACK delimiter (AD)                  1
+ * End-of-frame (EOF)                  7
+ * Inter frame spacing                 3
+ *
+ * assuming CRC21, rounded up and ignoring bitstuffing
+ */
+#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(61, 8)
+
+/*
+ * Size of a CAN-FD Extended Frame
+ *
+ * Name of Field                       Bits
+ * ---------------------------------------------------------
+ * Start-of-frame                      1
+ * Identifier A                                11
+ * Substitute remote request (SRR)     1
+ * Identifier extension bit (IDE)      1
+ * Identifier B                                18
+ * Reserved bit (r1)                   1
+ * Flexible data rate format (FDF)     1
+ * Reserved bit (r0)                   1
+ * Bit Rate Switch (BRS)               1
+ * Error Status Indicator (ESI)                1
+ * Data length code (DLC)              4
+ * Data field                          0...512
+ * Stuff Bit Count (SBC)               0...16: 4 20...64:5
+ * CRC                                 0...16: 17 20...64:21
+ * CRC delimiter (CD)                  1
+ * ACK slot (AS)                       1
+ * ACK delimiter (AD)                  1
+ * End-of-frame (EOF)                  7
+ * Inter frame spacing                 3
+ *
+ * assuming CRC21, rounded up and ignoring bitstuffing
+ */
+#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(80, 8)
+
+/*
+ * Maximum size of a Classical CAN frame
+ * (rounded up and ignoring bitstuffing)
+ */
+#define CAN_FRAME_LEN_MAX (CAN_FRAME_OVERHEAD_EFF + CAN_MAX_DLEN)
+
+/*
+ * Maximum size of a CAN-FD frame
+ * (rounded up and ignoring bitstuffing)
+ */
+#define CANFD_FRAME_LEN_MAX (CANFD_FRAME_OVERHEAD_EFF + CANFD_MAX_DLEN)
+
 /*
  * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
  * Classical CAN frame into a valid data length of max. 8 bytes.
@@ -45,6 +162,9 @@ u8 can_fd_dlc2len(u8 dlc);
 /* map the sanitized data length to an appropriate data length code */
 u8 can_fd_len2dlc(u8 len);
 
+/* calculate the CAN Frame length in bytes of a given skb */
+unsigned int can_skb_get_frame_len(const struct sk_buff *skb);
+
 /* map the data length to an appropriate data link layer length */
 static inline u8 canfd_sanitize_len(u8 len)
 {