* [RFC PATCH v3 0/5] can: support CAN XL
@ 2022-07-17 13:27 Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 1/5] can: canxl: introduce CAN XL data structure Oliver Hartkopp
` (5 more replies)
0 siblings, 6 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:27 UTC (permalink / raw)
To: linux-can; +Cc: Oliver Hartkopp
The CAN with eXtended data Length (CAN XL) is a new CAN protocol with a
10Mbit/s data transfer with a new physical layer transceiver (for this
data section). CAN XL allows up to 2048 byte of payload and shares the
arbitration principle (11 bit priority) known from Classical CAN and
CAN FD. RTR and 29 bit identifiers are not implemented in CAN XL.
A short introdution to CAN XL can be found here:
https://www.bosch-semiconductors.com/media/ip_modules/pdf_2/can_xl_1/canxl_intro_20210225.pdf
V2: Major rework after discussion and feedback on Linux-CAN ML
- rework of struct canxl_frame
- CANXL_XLF flag is now the switch between CAN XL and CAN/CANFD
- variable length in r/w operations for CAN XL frames
- write CAN XL frame to raw socket enforces size <-> canxl_frame.len sync
V3: Fix length for CAN XL frames inside the sk_buff
- extend the CAN_RAW sockopt to handle fixed/truncated read/write operations
Oliver Hartkopp (5):
can: canxl: introduce CAN XL data structure
can: canxl: introduce ETH_P_CANXL ethernet protocol handling
can: dev: add CAN XL support
can: vcan: add CAN XL support
can: raw: add CAN XL support
drivers/net/can/dev/rx-offload.c | 2 +-
drivers/net/can/dev/skb.c | 49 +++++++++++++----
drivers/net/can/vcan.c | 11 ++--
include/linux/can/skb.h | 44 +++++++++++++++-
include/uapi/linux/can.h | 49 +++++++++++++++++
include/uapi/linux/can/raw.h | 6 +++
include/uapi/linux/if_ether.h | 1 +
net/can/af_can.c | 32 ++++++++++--
net/can/raw.c | 90 ++++++++++++++++++++++++++++----
9 files changed, 252 insertions(+), 32 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH v3 1/5] can: canxl: introduce CAN XL data structure
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
@ 2022-07-17 13:27 ` Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 2/5] can: canxl: introduce ETH_P_CANXL ethernet protocol handling Oliver Hartkopp
` (4 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:27 UTC (permalink / raw)
To: linux-can; +Cc: Oliver Hartkopp
This patch adds defines for data structures and length information for
CAN XL (CAN with eXtended data Length) which can transfer up to 2048
byte insinde a single frame.
Notable changes from CAN FD:
- the 11 bit arbitration field is now named 'priority' instead of 'can_id'
(there are no 29 bit identifiers nor RTR frames anymore)
- the data length needs a uint16 value to cover up to 2048 byte
(the length element position is different to struct can[fd]_frame)
- new fields (SDT, AF) and a SEC bit have been introduced
- the virtual CAN interface identifier is not part if the CAN XL frame
struct as this VCID value is stored in struct skbuff (analog to vlan id)
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
include/uapi/linux/can.h | 49 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
index 90801ada2bbe..e736ed7be32d 100644
--- a/include/uapi/linux/can.h
+++ b/include/uapi/linux/can.h
@@ -46,10 +46,11 @@
#ifndef _UAPI_CAN_H
#define _UAPI_CAN_H
#include <linux/types.h>
#include <linux/socket.h>
+#include <linux/stddef.h> /* for offsetof */
/* controller area network (CAN) kernel definitions */
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
@@ -58,10 +59,11 @@
/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
+#define CANXL_PRIO_MASK CAN_SFF_MASK /* 11 bit priority mask */
/*
* Controller Area Network Identifier structure
*
* bit 0-28 : CAN identifier (11/29 bit)
@@ -71,10 +73,11 @@
*/
typedef __u32 canid_t;
#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29
+#define CANXL_PRIO_BITS CAN_SFF_ID_BITS
/*
* Controller Area Network Error Message Frame Mask structure
*
* bit 0-28 : error class mask (see include/uapi/linux/can/error.h)
@@ -89,10 +92,20 @@ typedef __u32 can_err_mask_t;
/* CAN FD payload length and DLC definitions according to ISO 11898-7 */
#define CANFD_MAX_DLC 15
#define CANFD_MAX_DLEN 64
+/*
+ * CAN XL payload length and DLC definitions according to ISO 11898-1
+ * CAN XL DLC ranges from 0 .. 2047 => data length from 1 .. 2048 byte
+ */
+#define CANXL_MIN_DLC 0
+#define CANXL_MAX_DLC 2047
+#define CANXL_MAX_DLC_MASK 0x07FF
+#define CANXL_MIN_DLEN 1
+#define CANXL_MAX_DLEN 2048
+
/**
* struct can_frame - Classical CAN frame structure (aka CAN 2.0B)
* @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition
* @len: CAN frame payload length in byte (0 .. 8)
* @can_dlc: deprecated name for CAN frame payload length in byte (0 .. 8)
@@ -164,12 +177,48 @@ struct canfd_frame {
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
};
+/*
+ * defined bits for canxl_frame.flags
+ *
+ * The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC
+ * and shares the relative position of the struct can[fd]_frame.len element.
+ * The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame.
+ * As a side effect setting this bit intentionally breaks the length checks
+ * for Classical CAN and CAN FD frames.
+ *
+ * Undefined bits in canxl_frame.flags are reserved and shall be set to zero.
+ */
+#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
+#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */
+
+/**
+ * struct canxl_frame - CAN with e'X'tended frame 'L'ength frame structure
+ * @prio: 11 bit arbitration priority with zero'ed CAN_*_FLAG flags
+ * @flags: additional flags for CAN XL
+ * @sdt: SDU (service data unit) type
+ * @len: frame payload length in byte (1 .. CANXL_MAX_DLEN)
+ * @af: acceptance field
+ * @data: CAN XL frame payload (up to CANXL_MAX_DLEN byte)
+ *
+ * @prio shares the same position as @can_id from struct can[fd]_frame.
+ */
+struct canxl_frame {
+ canid_t prio; /* 11 bit priority for arbitration (canid_t) */
+ __u8 flags; /* additional flags for CAN XL */
+ __u8 sdt; /* SDU (service data unit) type */
+ __u16 len; /* frame payload length in byte */
+ __u32 af; /* acceptance field */
+ __u8 data[CANXL_MAX_DLEN];
+};
+
#define CAN_MTU (sizeof(struct can_frame))
#define CANFD_MTU (sizeof(struct canfd_frame))
+#define CANXL_MTU (sizeof(struct canxl_frame))
+#define CANXL_HDR_SZ (offsetof(struct canxl_frame, data))
/* particular protocols of the protocol family PF_CAN */
#define CAN_RAW 1 /* RAW sockets */
#define CAN_BCM 2 /* Broadcast Manager */
#define CAN_TP16 3 /* VAG Transport Protocol v1.6 */
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v3 2/5] can: canxl: introduce ETH_P_CANXL ethernet protocol handling
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 1/5] can: canxl: introduce CAN XL data structure Oliver Hartkopp
@ 2022-07-17 13:27 ` Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 3/5] can: dev: add CAN XL support Oliver Hartkopp
` (3 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:27 UTC (permalink / raw)
To: linux-can; +Cc: Oliver Hartkopp
Enable the PF_CAN infrastructure to handle CAN XL frames. A new ethernet
protocol type ETH_P_CANXL is defined to tag skbuffs containing the CAN XL
frame data structure.
As the length information is now a uint16 value for CAN XL three new
helper functions have been introduced to retrieve the data length from
all types of CAN frames.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
include/linux/can/skb.h | 39 +++++++++++++++++++++++++++++++++++
include/uapi/linux/if_ether.h | 1 +
net/can/af_can.c | 32 +++++++++++++++++++++++-----
3 files changed, 67 insertions(+), 5 deletions(-)
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 182749e858b3..51481f5afe62 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -101,6 +101,45 @@ static inline bool can_is_canfd_skb(const struct sk_buff *skb)
{
/* the CAN specific type of skb is identified by its data length */
return skb->len == CANFD_MTU;
}
+static inline bool can_is_canxl_skb(const struct sk_buff *skb)
+{
+ const struct canxl_frame *cfx = (struct canxl_frame *)skb->data;
+
+ if (skb->len != CANXL_MTU)
+ return false;
+
+ /* check valid CAN XL data length boundaries */
+ if (cfx->len < CANXL_MIN_DLEN || cfx->len > CANXL_MAX_DLEN)
+ return false;
+
+ return cfx->flags & CANXL_XLF;
+}
+
+/* get length element value from can[|fd|xl]_frame structure */
+static inline unsigned int can_skb_get_len_val(struct sk_buff *skb)
+{
+ const struct canxl_frame *cfx = (struct canxl_frame *)skb->data;
+ const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+
+ if (can_is_canxl_skb(skb))
+ return cfx->len;
+
+ return cfd->len;
+}
+
+/* get needed data length inside of CAN frame for all frame types (RTR aware) */
+static inline unsigned int can_skb_get_data_len(struct sk_buff *skb)
+{
+ unsigned int len = can_skb_get_len_val(skb);
+ const struct can_frame *cf = (struct can_frame *)skb->data;
+
+ /* RTR frames have an actual length of zero */
+ if (skb->len == CAN_MTU && cf->can_id & CAN_RTR_FLAG)
+ return 0;
+
+ return len;
+}
+
#endif /* !_CAN_SKB_H */
diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index d370165bc621..69e0457eb200 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -136,10 +136,11 @@
#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/
#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */
#define ETH_P_CAN 0x000C /* CAN: Controller Area Network */
#define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/
+#define ETH_P_CANXL 0x000E /* CANXL: eXtended frame Length */
#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */
#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
#define ETH_P_CONTROL 0x0016 /* Card specific control frames */
#define ETH_P_IRDA 0x0017 /* Linux-IrDA */
diff --git a/net/can/af_can.c b/net/can/af_can.c
index 1fb49d51b25d..23e56e4e2457 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -209,19 +209,20 @@ int can_send(struct sk_buff *skb, int loop)
goto inval_skb;
} else if (skb->len == CANFD_MTU) {
skb->protocol = htons(ETH_P_CANFD);
if (unlikely(cfd->len > CANFD_MAX_DLEN))
goto inval_skb;
+ } else if (skb->len == CANXL_MTU) {
+ skb->protocol = htons(ETH_P_CANXL);
+ if (unlikely(!can_is_canxl_skb(skb)))
+ goto inval_skb;
} else {
goto inval_skb;
}
- /* Make sure the CAN frame can pass the selected CAN netdevice.
- * As structs can_frame and canfd_frame are similar, we can provide
- * CAN FD frames to legacy CAN drivers as long as the length is <= 8
- */
- if (unlikely(skb->len > skb->dev->mtu && cfd->len > CAN_MAX_DLEN)) {
+ /* Make sure the CAN frame can pass the selected CAN netdevice */
+ if (unlikely(skb->len > skb->dev->mtu)) {
err = -EMSGSIZE;
goto inval_skb;
}
if (unlikely(skb->dev->type != ARPHRD_CAN)) {
@@ -725,10 +726,25 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev,
free_skb:
kfree_skb(skb);
return NET_RX_DROP;
}
+static int canxl_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt, struct net_device *orig_dev)
+{
+ if (unlikely(dev->type != ARPHRD_CAN || (!can_is_canxl_skb(skb)))) {
+ pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n",
+ dev->type, skb->len);
+
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+
+ can_receive(skb, dev);
+ return NET_RX_SUCCESS;
+}
+
/* af_can protocol functions */
/**
* can_proto_register - register CAN transport protocol
* @cp: pointer to CAN protocol structure
@@ -849,10 +865,15 @@ static struct packet_type can_packet __read_mostly = {
static struct packet_type canfd_packet __read_mostly = {
.type = cpu_to_be16(ETH_P_CANFD),
.func = canfd_rcv,
};
+static struct packet_type canxl_packet __read_mostly = {
+ .type = cpu_to_be16(ETH_P_CANXL),
+ .func = canxl_rcv,
+};
+
static const struct net_proto_family can_family_ops = {
.family = PF_CAN,
.create = can_create,
.owner = THIS_MODULE,
};
@@ -888,10 +909,11 @@ static __init int can_init(void)
if (err)
goto out_sock;
dev_add_pack(&can_packet);
dev_add_pack(&canfd_packet);
+ dev_add_pack(&canxl_packet);
return 0;
out_sock:
unregister_pernet_subsys(&can_pernet_ops);
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v3 3/5] can: dev: add CAN XL support
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 1/5] can: canxl: introduce CAN XL data structure Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 2/5] can: canxl: introduce ETH_P_CANXL ethernet protocol handling Oliver Hartkopp
@ 2022-07-17 13:27 ` Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 4/5] can: vcan: " Oliver Hartkopp
` (2 subsequent siblings)
5 siblings, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:27 UTC (permalink / raw)
To: linux-can; +Cc: Oliver Hartkopp
Extend the CAN device driver infrastructure to handle CAN XL frames.
This especially addresses the increased data length which is extended
to uint16 for CAN XL.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
drivers/net/can/dev/rx-offload.c | 2 +-
drivers/net/can/dev/skb.c | 49 ++++++++++++++++++++++++++------
include/linux/can/skb.h | 5 +++-
3 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index a32a01c172d4..8505e547e922 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -245,11 +245,11 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
unsigned int *frame_len_ptr)
{
struct net_device *dev = offload->dev;
struct net_device_stats *stats = &dev->stats;
struct sk_buff *skb;
- u8 len;
+ unsigned int len;
int err;
skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
if (!skb)
return 0;
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 8bb62dd864c8..8531e0c39d1c 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -53,11 +53,12 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
BUG_ON(idx >= priv->echo_skb_max);
/* check flag whether this packet has to be looped back */
if (!(dev->flags & IFF_ECHO) ||
(skb->protocol != htons(ETH_P_CAN) &&
- skb->protocol != htons(ETH_P_CANFD))) {
+ skb->protocol != htons(ETH_P_CANFD) &&
+ skb->protocol != htons(ETH_P_CANXL))) {
kfree_skb(skb);
return 0;
}
if (!priv->echo_skb[idx]) {
@@ -86,12 +87,12 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
return 0;
}
EXPORT_SYMBOL_GPL(can_put_echo_skb);
struct sk_buff *
-__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
- unsigned int *frame_len_ptr)
+__can_get_echo_skb(struct net_device *dev, unsigned int idx,
+ unsigned int *len_ptr, unsigned int *frame_len_ptr)
{
struct can_priv *priv = netdev_priv(dev);
if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -103,17 +104,13 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
/* Using "struct canfd_frame::len" for the frame
* length is supported on both CAN and CANFD frames.
*/
struct sk_buff *skb = priv->echo_skb[idx];
struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
- struct canfd_frame *cf = (struct canfd_frame *)skb->data;
/* get the real payload length for netdev statistics */
- if (cf->can_id & CAN_RTR_FLAG)
- *len_ptr = 0;
- else
- *len_ptr = cf->len;
+ *len_ptr = can_skb_get_data_len(skb);
if (frame_len_ptr)
*frame_len_ptr = can_skb_priv->frame_len;
priv->echo_skb[idx] = NULL;
@@ -139,11 +136,11 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
*/
unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *frame_len_ptr)
{
struct sk_buff *skb;
- u8 len;
+ unsigned int len;
skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
if (!skb)
return 0;
@@ -244,10 +241,41 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
return skb;
}
EXPORT_SYMBOL_GPL(alloc_canfd_skb);
+struct sk_buff *alloc_canxl_skb(struct net_device *dev,
+ struct canxl_frame **cfx)
+{
+ struct sk_buff *skb;
+
+ skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
+ sizeof(struct canxl_frame));
+ if (unlikely(!skb)) {
+ *cfx = NULL;
+
+ return NULL;
+ }
+
+ skb->protocol = htons(ETH_P_CANXL);
+ skb->pkt_type = PACKET_BROADCAST;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+
+ can_skb_reserve(skb);
+ can_skb_prv(skb)->ifindex = dev->ifindex;
+ can_skb_prv(skb)->skbcnt = 0;
+
+ *cfx = skb_put_zero(skb, sizeof(struct canxl_frame));
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_canxl_skb);
+
struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
{
struct sk_buff *skb;
skb = alloc_can_skb(dev, cf);
@@ -302,10 +330,13 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
goto inval_skb;
} else if (skb->protocol == htons(ETH_P_CANFD)) {
if (unlikely(skb->len != CANFD_MTU ||
cfd->len > CANFD_MAX_DLEN))
goto inval_skb;
+ } else if (skb->protocol == htons(ETH_P_CANXL)) {
+ if (unlikely(!can_is_canxl_skb(skb)))
+ goto inval_skb;
} else {
goto inval_skb;
}
if (!can_skb_headroom_valid(dev, skb)) {
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 51481f5afe62..9972c9bd73bc 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -18,19 +18,22 @@
void can_flush_echo_skb(struct net_device *dev);
int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
unsigned int idx, unsigned int frame_len);
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
- u8 *len_ptr, unsigned int *frame_len_ptr);
+ unsigned int *len_ptr,
+ unsigned int *frame_len_ptr);
unsigned int __must_check can_get_echo_skb(struct net_device *dev,
unsigned int idx,
unsigned int *frame_len_ptr);
void can_free_echo_skb(struct net_device *dev, unsigned int idx,
unsigned int *frame_len_ptr);
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
struct sk_buff *alloc_canfd_skb(struct net_device *dev,
struct canfd_frame **cfd);
+struct sk_buff *alloc_canxl_skb(struct net_device *dev,
+ struct canxl_frame **cfx);
struct sk_buff *alloc_can_err_skb(struct net_device *dev,
struct can_frame **cf);
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
/*
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v3 4/5] can: vcan: add CAN XL support
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
` (2 preceding siblings ...)
2022-07-17 13:27 ` [RFC PATCH v3 3/5] can: dev: add CAN XL support Oliver Hartkopp
@ 2022-07-17 13:27 ` Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 5/5] can: raw: " Oliver Hartkopp
2022-07-18 11:03 ` [RFC PATCH v3 0/5] can: support CAN XL Pavel Pisa
5 siblings, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:27 UTC (permalink / raw)
To: linux-can; +Cc: Oliver Hartkopp
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
drivers/net/can/vcan.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index a15619d883ec..d72c0727b440 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -68,33 +68,32 @@ static bool echo; /* echo testing. Default: 0 (Off) */
module_param(echo, bool, 0444);
MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)");
static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
{
- struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct net_device_stats *stats = &dev->stats;
stats->rx_packets++;
- stats->rx_bytes += cfd->len;
+ stats->rx_bytes += can_skb_get_data_len(skb);
skb->pkt_type = PACKET_BROADCAST;
skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY;
netif_rx(skb);
}
static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
struct net_device_stats *stats = &dev->stats;
- int loop, len;
+ unsigned int len;
+ int loop;
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
- len = cfd->can_id & CAN_RTR_FLAG ? 0 : cfd->len;
+ len = can_skb_get_data_len(skb);
stats->tx_packets++;
stats->tx_bytes += len;
/* set flag whether this packet has to be looped back */
loop = skb->pkt_type == PACKET_LOOPBACK;
@@ -132,11 +131,11 @@ static int vcan_change_mtu(struct net_device *dev, int new_mtu)
{
/* Do not allow changing the MTU while running */
if (dev->flags & IFF_UP)
return -EBUSY;
- if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU)
+ if (new_mtu != CAN_MTU && new_mtu != CANFD_MTU && new_mtu != CANXL_MTU)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH v3 5/5] can: raw: add CAN XL support
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
` (3 preceding siblings ...)
2022-07-17 13:27 ` [RFC PATCH v3 4/5] can: vcan: " Oliver Hartkopp
@ 2022-07-17 13:27 ` Oliver Hartkopp
2022-07-17 13:48 ` Oliver Hartkopp
2022-07-18 11:03 ` [RFC PATCH v3 0/5] can: support CAN XL Pavel Pisa
5 siblings, 1 reply; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:27 UTC (permalink / raw)
To: linux-can; +Cc: Oliver Hartkopp
Enable CAN_RAW sockets to read and write CAN XL frames analogue to the
CAN FD extension (new CAN_RAW_XL_FRAMES sockopt).
A CAN XL network interface is capable to handle Classical CAN, CAN FD and
CAN XL frames. When CAN_RAW_XL_FRAMES is enabled, the CAN_RAW socket checks
whether the addressed CAN network interface is capable to handle the
provided CAN frame.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
include/uapi/linux/can/raw.h | 6 +++
net/can/raw.c | 90 ++++++++++++++++++++++++++++++++----
2 files changed, 86 insertions(+), 10 deletions(-)
diff --git a/include/uapi/linux/can/raw.h b/include/uapi/linux/can/raw.h
index 3386aa81fdf2..0c55d48ae867 100644
--- a/include/uapi/linux/can/raw.h
+++ b/include/uapi/linux/can/raw.h
@@ -60,8 +60,14 @@ enum {
CAN_RAW_ERR_FILTER, /* set filter for error frames */
CAN_RAW_LOOPBACK, /* local loopback (default:on) */
CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */
+ CAN_RAW_XL_FRAMES, /* allow CAN XL frames (default:off) */
};
+/* CAN XL data transfer modes for CAN_RAW_XL_FRAMES sockopt */
+#define CAN_RAW_XL_ENABLE (1 << 0) /* enable CAN XL frames on this socket */
+#define CAN_RAW_XL_RX_DYN (1 << 1) /* allow truncated data[] for read() */
+#define CAN_RAW_XL_TX_DYN (1 << 2) /* allow truncated data[] for write() */
+
#endif /* !_UAPI_CAN_RAW_H */
diff --git a/net/can/raw.c b/net/can/raw.c
index d1bd9cc51ebe..8dab87deb22e 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -85,10 +85,11 @@ struct raw_sock {
int ifindex;
struct list_head notifier;
int loopback;
int recv_own_msgs;
int fd_frames;
+ int xl_frames;
int join_filters;
int count; /* number of active filters */
struct can_filter dfilter; /* default/single filter */
struct can_filter *filter; /* pointer to filter(s) */
can_err_mask_t err_mask;
@@ -344,10 +345,11 @@ static int raw_init(struct sock *sk)
/* set default loopback behaviour */
ro->loopback = 1;
ro->recv_own_msgs = 0;
ro->fd_frames = 0;
+ ro->xl_frames = 0;
ro->join_filters = 0;
/* alloc_percpu provides zero'ed memory */
ro->uniq = alloc_percpu(struct uniqframe);
if (unlikely(!ro->uniq))
@@ -667,10 +669,23 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
if (copy_from_sockptr(&ro->fd_frames, optval, optlen))
return -EFAULT;
break;
+ case CAN_RAW_XL_FRAMES:
+ if (optlen != sizeof(ro->xl_frames))
+ return -EINVAL;
+
+ if (copy_from_sockptr(&ro->xl_frames, optval, optlen))
+ return -EFAULT;
+
+ /* sanitize flags */
+ if (ro->xl_frames & (CAN_RAW_XL_RX_DYN | CAN_RAW_XL_TX_DYN))
+ ro->xl_frames |= CAN_RAW_XL_ENABLE;
+
+ break;
+
case CAN_RAW_JOIN_FILTERS:
if (optlen != sizeof(ro->join_filters))
return -EINVAL;
if (copy_from_sockptr(&ro->join_filters, optval, optlen))
@@ -749,10 +764,16 @@ static int raw_getsockopt(struct socket *sock, int level, int optname,
if (len > sizeof(int))
len = sizeof(int);
val = &ro->fd_frames;
break;
+ case CAN_RAW_XL_FRAMES:
+ if (len > sizeof(int))
+ len = sizeof(int);
+ val = &ro->xl_frames;
+ break;
+
case CAN_RAW_JOIN_FILTERS:
if (len > sizeof(int))
len = sizeof(int);
val = &ro->join_filters;
break;
@@ -773,13 +794,18 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
struct sock *sk = sock->sk;
struct raw_sock *ro = raw_sk(sk);
struct sockcm_cookie sockc;
struct sk_buff *skb;
struct net_device *dev;
+ unsigned int skb_sz = size;
int ifindex;
int err;
+ /* valid CAN frame sizes */
+ if (size < CANXL_HDR_SZ + CANXL_MIN_DLEN || size > CANXL_MTU)
+ return -EINVAL;
+
if (msg->msg_name) {
DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name);
if (msg->msg_namelen < RAW_MIN_NAMELEN)
return -EINVAL;
@@ -795,19 +821,16 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
dev = dev_get_by_index(sock_net(sk), ifindex);
if (!dev)
return -ENXIO;
err = -EINVAL;
- if (ro->fd_frames && dev->mtu == CANFD_MTU) {
- if (unlikely(size != CANFD_MTU && size != CAN_MTU))
- goto put_dev;
- } else {
- if (unlikely(size != CAN_MTU))
- goto put_dev;
- }
- skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
+ /* alloc full CAN XL space */
+ if (ro->xl_frames && dev->mtu == CANXL_MTU)
+ skb_sz = CANXL_MTU;
+
+ skb = sock_alloc_send_skb(sk, skb_sz + sizeof(struct can_skb_priv),
msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
goto put_dev;
can_skb_reserve(skb);
@@ -816,10 +839,47 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
err = memcpy_from_msg(skb_put(skb, size), msg, size);
if (err < 0)
goto free_skb;
+ if (ro->xl_frames && dev->mtu == CANXL_MTU) {
+ struct canxl_frame *cfx = (struct canxl_frame *)skb->data;
+
+ if (cfx->flags & CANXL_XLF) {
+ /* check for valid CAN XL frame */
+ if (cfx->len < CANXL_MIN_DLEN ||
+ cfx->len > CANXL_MAX_DLEN)
+ goto free_skb;
+
+ if (ro->xl_frames & CAN_RAW_XL_TX_DYN) {
+ /* check truncated CAN XL frame structure */
+ if (size != cfx->len + CANXL_HDR_SZ)
+ goto free_skb;
+
+ /* push skb->len to CANXL_MTU */
+ if (size < CANXL_MTU)
+ skb_put_zero(skb, CANXL_MTU - size);
+ } else {
+ /* check complete CAN XL frame structure */
+ if (size != CANXL_MTU)
+ goto free_skb;
+ }
+ } else {
+ /* check for CAN FD and Classical CAN */
+ if (unlikely(size != CANFD_MTU && size != CAN_MTU))
+ goto free_skb;
+ }
+ } else if (ro->fd_frames && dev->mtu == CANFD_MTU) {
+ /* CAN FD and Classical CAN */
+ if (unlikely(size != CANFD_MTU && size != CAN_MTU))
+ goto free_skb;
+ } else {
+ /* Classical CAN */
+ if (unlikely(size != CAN_MTU))
+ goto free_skb;
+ }
+
sockcm_init(&sockc, sk);
if (msg->msg_controllen) {
err = sock_cmsg_send(sk, msg, &sockc);
if (unlikely(err))
goto free_skb;
@@ -850,25 +910,35 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
struct sock *sk = sock->sk;
+ struct raw_sock *ro = raw_sk(sk);
struct sk_buff *skb;
+ struct canxl_frame *cfx;
+ unsigned int rx_len;
int err = 0;
if (flags & MSG_ERRQUEUE)
return sock_recv_errqueue(sk, msg, size,
SOL_CAN_RAW, SCM_CAN_RAW_ERRQUEUE);
skb = skb_recv_datagram(sk, flags, &err);
if (!skb)
return err;
- if (size < skb->len)
+ rx_len = skb->len;
+ if (rx_len == CANXL_MTU && ro->xl_frames & CAN_RAW_XL_RX_DYN) {
+ cfx = (struct canxl_frame *)skb->data;
+ if (cfx->len >= CANXL_MIN_DLEN && cfx->len < CANXL_MAX_DLEN)
+ rx_len = CANXL_HDR_SZ + cfx->len;
+ }
+
+ if (size < rx_len)
msg->msg_flags |= MSG_TRUNC;
else
- size = skb->len;
+ size = rx_len;
err = memcpy_to_msg(msg, skb->data, size);
if (err < 0) {
skb_free_datagram(sk, skb);
return err;
--
2.30.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v3 5/5] can: raw: add CAN XL support
2022-07-17 13:27 ` [RFC PATCH v3 5/5] can: raw: " Oliver Hartkopp
@ 2022-07-17 13:48 ` Oliver Hartkopp
0 siblings, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-17 13:48 UTC (permalink / raw)
To: linux-can
On 17.07.22 15:27, Oliver Hartkopp wrote:
> Enable CAN_RAW sockets to read and write CAN XL frames analogue to the
> CAN FD extension (new CAN_RAW_XL_FRAMES sockopt).
>
> A CAN XL network interface is capable to handle Classical CAN, CAN FD and
> CAN XL frames. When CAN_RAW_XL_FRAMES is enabled, the CAN_RAW socket checks
> whether the addressed CAN network interface is capable to handle the
> provided CAN frame.
>
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> ---
> include/uapi/linux/can/raw.h | 6 +++
> net/can/raw.c | 90 ++++++++++++++++++++++++++++++++----
> 2 files changed, 86 insertions(+), 10 deletions(-)
>
> diff --git a/include/uapi/linux/can/raw.h b/include/uapi/linux/can/raw.h
> index 3386aa81fdf2..0c55d48ae867 100644
> --- a/include/uapi/linux/can/raw.h
> +++ b/include/uapi/linux/can/raw.h
> @@ -60,8 +60,14 @@ enum {
> CAN_RAW_ERR_FILTER, /* set filter for error frames */
> CAN_RAW_LOOPBACK, /* local loopback (default:on) */
> CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */
> CAN_RAW_FD_FRAMES, /* allow CAN FD frames (default:off) */
> CAN_RAW_JOIN_FILTERS, /* all filters must match to trigger */
> + CAN_RAW_XL_FRAMES, /* allow CAN XL frames (default:off) */
> };
>
> +/* CAN XL data transfer modes for CAN_RAW_XL_FRAMES sockopt */
> +#define CAN_RAW_XL_ENABLE (1 << 0) /* enable CAN XL frames on this socket */
> +#define CAN_RAW_XL_RX_DYN (1 << 1) /* allow truncated data[] for read() */
> +#define CAN_RAW_XL_TX_DYN (1 << 2) /* allow truncated data[] for write() */
s/allow/enable/
When CAN_RAW_XL_TX_DYN is enabled the truncated data size is enforced.
So there is no mix of truncated/fixed CAN XL frames allowed ...
Regards,
Oliver
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v3 0/5] can: support CAN XL
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
` (4 preceding siblings ...)
2022-07-17 13:27 ` [RFC PATCH v3 5/5] can: raw: " Oliver Hartkopp
@ 2022-07-18 11:03 ` Pavel Pisa
2022-07-18 12:47 ` Oliver Hartkopp
2022-07-20 6:49 ` Vincent Mailhol
5 siblings, 2 replies; 11+ messages in thread
From: Pavel Pisa @ 2022-07-18 11:03 UTC (permalink / raw)
To: Oliver Hartkopp; +Cc: linux-can
Hello Oliver,
On Sunday 17 of July 2022 15:27:25 Oliver Hartkopp wrote:
> V2: Major rework after discussion and feedback on Linux-CAN ML
>
> - rework of struct canxl_frame
> - CANXL_XLF flag is now the switch between CAN XL and CAN/CANFD
> - variable length in r/w operations for CAN XL frames
> - write CAN XL frame to raw socket enforces size <-> canxl_frame.len sync
I generally like the idea but I would like even to extend it to process
all CAN messages types through same API.
+struct canxl_frame {
+ canid_t prio; /* 11 bit priority for arbitration (canid_t) */
+ __u8 flags; /* additional flags for CAN XL */
+ __u8 sdt; /* SDU (service data unit) type */
+ __u16 len; /* frame payload length in byte */
+ __u32 af; /* acceptance field */
+ __u8 data[CANXL_MAX_DLEN];
+};
I would suggest to think about possibility to have single structure type
for processing of all CAN frames types in usersace. When you define field
prio as anonyous union of prio and can_id
union {
canid_t prio;
canid_t can_id;
}
then it is possible to define flags such way, that canxl_frame is alternative
for all other formats
+#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
So CANXL_XLF will be changed to CANXLS_SELECT frame structure selected,
then rest of bits can be used for CANXLS_XLF, CANXLS_FD, in ideal case even
RTR, BRS etc.. or RTR can be left as part of ID if that is easier.
This way only single structure can be used to receive and send all
frames over single interface when XL option is selected
by software.
Yes, there would be redundancy in the kernel handling which has to accept
two types of encoding of CAN FD and standard messages but actual complexity
in usespace when you want to support all variants and for example
forward frames between interfaces or process them inside QEMU etc.
is really quite high.
Best wishes,
Pavel
--
Pavel Pisa
phone: +420 603531357
e-mail: pisa@cmp.felk.cvut.cz
Department of Control Engineering FEE CVUT
Karlovo namesti 13, 121 35, Prague 2
university: http://control.fel.cvut.cz/
personal: http://cmp.felk.cvut.cz/~pisa
projects: https://www.openhub.net/accounts/ppisa
CAN related:http://canbus.pages.fel.cvut.cz/
RISC-V education: https://comparch.edu.cvut.cz/
Open Technologies Research Education and Exchange Services
https://gitlab.fel.cvut.cz/otrees/org/-/wikis/home
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v3 0/5] can: support CAN XL
2022-07-18 11:03 ` [RFC PATCH v3 0/5] can: support CAN XL Pavel Pisa
@ 2022-07-18 12:47 ` Oliver Hartkopp
2022-07-20 6:49 ` Vincent Mailhol
1 sibling, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-18 12:47 UTC (permalink / raw)
To: Pavel Pisa; +Cc: linux-can
Hello Pavel,
On 18.07.22 13:03, Pavel Pisa wrote:
> Hello Oliver,
>
> On Sunday 17 of July 2022 15:27:25 Oliver Hartkopp wrote:
>> V2: Major rework after discussion and feedback on Linux-CAN ML
>>
>> - rework of struct canxl_frame
>> - CANXL_XLF flag is now the switch between CAN XL and CAN/CANFD
>> - variable length in r/w operations for CAN XL frames
>> - write CAN XL frame to raw socket enforces size <-> canxl_frame.len sync
>
> I generally like the idea but I would like even to extend it to process
> all CAN messages types through same API.
>
> +struct canxl_frame {
> + canid_t prio; /* 11 bit priority for arbitration (canid_t) */
> + __u8 flags; /* additional flags for CAN XL */
> + __u8 sdt; /* SDU (service data unit) type */
> + __u16 len; /* frame payload length in byte */
> + __u32 af; /* acceptance field */
> + __u8 data[CANXL_MAX_DLEN];
> +};
>
> I would suggest to think about possibility to have single structure type
> for processing of all CAN frames types in usersace.
Yes, I would love to do this too.
But the length information in the CAN/CANFD frame is a 8 bit (u8)
element while we need 16 bit in CAN XL frames which can cover the 2048
bytes available in CAN XL.
So we can not place canxl_frame.len at the same place as can[fd]_frame.len.
And this leads to 'the trick' that canxl_frame.flags shares its position
with can[fd]_frame.len.
With CANXL_XLF = 0x80 we switch between CAN XL and CAN/CANFD which would
lead to can[fd]_frame.len = 128 which is way beyond a valid CAN/CANFD
length value.
> When you define field
> prio as anonyous union of prio and can_id
>
> union {
> canid_t prio;
> canid_t can_id;
> }
The CAN XL specification has no can_id anymore - but canxl_frame.prio
and can[fd]_frame.can_id share the same position, length and type (canid_t).
This allows us to re-use the CAN-ID filters in af_can.c for the
canxl_frame.prio.
> then it is possible to define flags such way, that canxl_frame is alternative
> for all other formats
Ah, now I got your point.
But e.g. you don't need 'sdt' and 'af' elements in CAN[FD] frames and
you would need raw-DLC fields for Classical CAN.
This will break all in-kernel users (bcm, gw, isotp, j1939).
> +#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */
> So CANXL_XLF will be changed to CANXLS_SELECT frame structure selected,
> then rest of bits can be used for CANXLS_XLF, CANXLS_FD, in ideal case even
> RTR, BRS etc.. or RTR can be left as part of ID if that is easier.
> This way only single structure can be used to receive and send all
> frames over single interface when XL option is selected
> by software.
>
> Yes, there would be redundancy in the kernel handling which has to accept
> two types of encoding of CAN FD and standard messages but actual complexity
> in usespace when you want to support all variants and for example
> forward frames between interfaces or process them inside QEMU etc.
> is really quite high.
IMHO it is very easy for CAN interfaces (as you can see in the vcan
driver (patch 4/5).
CAN XL is quite different to CAN[FD]. I would name it "Ethernet with CAN
arbitration" and for that reason I'm currently not thinking of adapting
the CAN modification features in gw.c for CAN XL.
If you go through the patches 2/5 and 3/5 you can see the current
infrastructure effort to handle CAN, CAN FD and CAN XL frames in parallel.
When working with a mix of CAN[|FD|XL] frames in user space I would
simply read into a struct canxl_frame and cast it to CAN[FD] when
CANXL_XLF is not set (and the sizeof(struct can[fd]_frame) and the len
value fits.
Don't you think, that is easy enough?
Best regards,
Oliver
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v3 0/5] can: support CAN XL
2022-07-18 11:03 ` [RFC PATCH v3 0/5] can: support CAN XL Pavel Pisa
2022-07-18 12:47 ` Oliver Hartkopp
@ 2022-07-20 6:49 ` Vincent Mailhol
2022-07-20 15:41 ` Oliver Hartkopp
1 sibling, 1 reply; 11+ messages in thread
From: Vincent Mailhol @ 2022-07-20 6:49 UTC (permalink / raw)
To: Pavel Pisa; +Cc: Oliver Hartkopp, linux-can
On Mon. 18 Jul. 2022 at 20:16, Pavel Pisa <pisa@cmp.felk.cvut.cz> wrote:
> Hello Oliver,
>
> On Sunday 17 of July 2022 15:27:25 Oliver Hartkopp wrote:
> > V2: Major rework after discussion and feedback on Linux-CAN ML
> >
> > - rework of struct canxl_frame
> > - CANXL_XLF flag is now the switch between CAN XL and CAN/CANFD
> > - variable length in r/w operations for CAN XL frames
> > - write CAN XL frame to raw socket enforces size <-> canxl_frame.len sync
>
> I generally like the idea but I would like even to extend it to process
> all CAN messages types through same API.
>
> +struct canxl_frame {
> + canid_t prio; /* 11 bit priority for arbitration (canid_t) */
> + __u8 flags; /* additional flags for CAN XL */
> + __u8 sdt; /* SDU (service data unit) type */
> + __u16 len; /* frame payload length in byte */
> + __u32 af; /* acceptance field */
> + __u8 data[CANXL_MAX_DLEN];
> +};
>
> I would suggest to think about possibility to have single structure type
> for processing of all CAN frames types in usersace.
I thought about it.
The prio is 11 bits, the XLF and SEC flags are 2 bits together, the
SDT is 8 bits, the length is 12 bits (1~2048) and finally the af is 32
bits. The total is thus 11+2+8+12+32 = 65 bits. Arg… one bit short to
fit in the struct can(fd)_frame!
However, if we use the DLC instead, the length information can fit on
11 bits (0~2047). With this, we have just enough to squeeze in the
CAN-XL flags.
And so, let me introduce you the Frankenstein monster version of the
canxl_frame:
#include <asm/byteorder.h>
struct canxl_frame {
union {
canid_t can_id; /* CAN(-FD) ID */
__u32 af; /* CAN-XL acceptance field */
};
union {
struct {
__u8 len; /* CAN(-FD) frame length */
__u8 flags; /* additional flags for CAN FD */
__u8 __res0; /* reserved / padding */
__u8 len8_dlc; /* optional Classic CAN DLC for
8 byte payload length (9 .. 15) */
};
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u32 xlf:1; /* is CAN-XL frame? */
#endif
__u32 sec:1; /* Simple Extended Content
(security/segmentation) */
__u32 xl_dlc:11; /* CAN-XL data length code (0..2047) */
__u32 prio:11; /* 11 bit priority for arbitration */
__u32 sdt:8; /* SDU (service data unit) type */
#if defined(__BIG_ENDIAN_BITFIELD)
__u32 xlf:1; /* is CAN-XL frame? */
#endif
};
};
__u8 data[] __attribute__((aligned(8)));
};
Pretty scary, isn’t it?
To be honest, I am sharing this for fun. No need to disprove this
idea, I do *not* support it myself.
Yours sincerely,
Vincent Mailhol
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH v3 0/5] can: support CAN XL
2022-07-20 6:49 ` Vincent Mailhol
@ 2022-07-20 15:41 ` Oliver Hartkopp
0 siblings, 0 replies; 11+ messages in thread
From: Oliver Hartkopp @ 2022-07-20 15:41 UTC (permalink / raw)
To: Vincent Mailhol, Pavel Pisa; +Cc: linux-can
On 20.07.22 08:49, Vincent Mailhol wrote:
> On Mon. 18 Jul. 2022 at 20:16, Pavel Pisa <pisa@cmp.felk.cvut.cz> wrote:
>> Hello Oliver,
>>
>> On Sunday 17 of July 2022 15:27:25 Oliver Hartkopp wrote:
>>> V2: Major rework after discussion and feedback on Linux-CAN ML
>>>
>>> - rework of struct canxl_frame
>>> - CANXL_XLF flag is now the switch between CAN XL and CAN/CANFD
>>> - variable length in r/w operations for CAN XL frames
>>> - write CAN XL frame to raw socket enforces size <-> canxl_frame.len sync
>>
>> I generally like the idea but I would like even to extend it to process
>> all CAN messages types through same API.
>>
>> +struct canxl_frame {
>> + canid_t prio; /* 11 bit priority for arbitration (canid_t) */
>> + __u8 flags; /* additional flags for CAN XL */
>> + __u8 sdt; /* SDU (service data unit) type */
>> + __u16 len; /* frame payload length in byte */
>> + __u32 af; /* acceptance field */
>> + __u8 data[CANXL_MAX_DLEN];
>> +};
>>
>> I would suggest to think about possibility to have single structure type
>> for processing of all CAN frames types in usersace.
>
> I thought about it.
>
> The prio is 11 bits, the XLF and SEC flags are 2 bits together, the
> SDT is 8 bits, the length is 12 bits (1~2048) and finally the af is 32
> bits. The total is thus 11+2+8+12+32 = 65 bits. Arg… one bit short to
> fit in the struct can(fd)_frame!
> However, if we use the DLC instead, the length information can fit on
> 11 bits (0~2047). With this, we have just enough to squeeze in the
> CAN-XL flags.
>
> And so, let me introduce you the Frankenstein monster version of the
> canxl_frame:
>
> #include <asm/byteorder.h>
>
> struct canxl_frame {
> union {
> canid_t can_id; /* CAN(-FD) ID */
> __u32 af; /* CAN-XL acceptance field */
> };
> union {
> struct {
> __u8 len; /* CAN(-FD) frame length */
> __u8 flags; /* additional flags for CAN FD */
> __u8 __res0; /* reserved / padding */
> __u8 len8_dlc; /* optional Classic CAN DLC for
> 8 byte payload length (9 .. 15) */
> };
> struct {
> #if defined(__LITTLE_ENDIAN_BITFIELD)
> __u32 xlf:1; /* is CAN-XL frame? */
> #endif
> __u32 sec:1; /* Simple Extended Content
> (security/segmentation) */
> __u32 xl_dlc:11; /* CAN-XL data length code (0..2047) */
> __u32 prio:11; /* 11 bit priority for arbitration */
> __u32 sdt:8; /* SDU (service data unit) type */
> #if defined(__BIG_ENDIAN_BITFIELD)
> __u32 xlf:1; /* is CAN-XL frame? */
> #endif
> };
> };
> __u8 data[] __attribute__((aligned(8)));
> };
>
> Pretty scary, isn’t it?
>
> To be honest, I am sharing this for fun. No need to disprove this
> idea, I do *not* support it myself.
But sometimes it is valuable to formulate an idea as code to see that
this is definitely NOT what you want ;-)
Best regards,
Oliver
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2022-07-20 15:41 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-17 13:27 [RFC PATCH v3 0/5] can: support CAN XL Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 1/5] can: canxl: introduce CAN XL data structure Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 2/5] can: canxl: introduce ETH_P_CANXL ethernet protocol handling Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 3/5] can: dev: add CAN XL support Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 4/5] can: vcan: " Oliver Hartkopp
2022-07-17 13:27 ` [RFC PATCH v3 5/5] can: raw: " Oliver Hartkopp
2022-07-17 13:48 ` Oliver Hartkopp
2022-07-18 11:03 ` [RFC PATCH v3 0/5] can: support CAN XL Pavel Pisa
2022-07-18 12:47 ` Oliver Hartkopp
2022-07-20 6:49 ` Vincent Mailhol
2022-07-20 15:41 ` Oliver Hartkopp
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).