CAN FD support part 1 - uncommented source
Subsystems (3)
Oliver Hartkopp
maintainerRFC 1/1 CAN FD support part 1 - uncommented source
drivers/net/can/dev.c +1 -1
@@ -454,7 +454,7 @@ EXPORT_SYMBOL_GPL(can_bus_off);static void can_setup (struct net_device *dev) { dev->type =ARPHRD_CAN ; - dev->mtu =sizeof (struct can_frame ); + dev->mtu =CAN_MTU ; dev->hard_header_len =0 ; dev->addr_len =0 ; dev->tx_queue_len =10 ;
drivers/net/can/vcan.c +15 -5
@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats; stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc); - skb->protocol =htons (ETH_P_CAN ); skb->pkt_type =PACKET_BROADCAST ; skb->dev = dev; skb->ip_summed =CHECKSUM_UNNECESSARY ;
@@ -94,7 +93,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)return NETDEV_TX_OK ; stats->tx_packets++; - stats->tx_bytes += cf->can_dlc; + stats->tx_bytes +=can_dlc2len (cf->can_dlc);/* set flag whether this packet has to be looped back */ loop = skb->pkt_type ==PACKET_LOOPBACK ;
@@ -108,7 +107,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)* CAN core already did the echo for us */ stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc); }kfree_skb (skb);return NETDEV_TX_OK ;
@@ -133,14 +132,25 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)return NETDEV_TX_OK ; } +static int vcan_change_mtu (struct net_device *dev,int new_mtu) +{ +if (new_mtu ==CAN_MTU || new_mtu ==CANFD_MTU ) { + dev->mtu = new_mtu; +return 0 ; + } + +return -EINVAL ; +} +static const struct net_device_ops vcan_netdev_ops = { .ndo_start_xmit = vcan_tx, + .ndo_change_mtu = vcan_change_mtu, };static void vcan_setup (struct net_device *dev) { dev->type =ARPHRD_CAN ; - dev->mtu =sizeof (struct can_frame ); + dev->mtu =CAN_MTU ; dev->hard_header_len =0 ; dev->addr_len =0 ; dev->tx_queue_len =0 ;
include/linux/can.h +62 -0
74 lines not on this page · raw message
include/linux/can/core.h +2 -2
@@ -17,10 +17,10 @@#include <linux/skbuff.h> #include <linux/netdevice.h> -#define CAN_VERSION "20090105" +#define CAN_VERSION "20120413"/* increment this number each time you change some user-space interface */ -#define CAN_ABI_VERSION "8" +#define CAN_ABI_VERSION "9"#define CAN_VERSION_STRING "rev " CAN_VERSION " abi " CAN_ABI_VERSION
include/linux/can/dev.h +20 -6
@@ -61,7 +61,11 @@ struct can_priv {* To be used in the CAN netdriver receive path to ensure conformance with * ISO 11898-1 Chapter 8.4.2.3 (DLC field) */ -#define get_can_dlc (i) (min_t(__u8, (i), 8)) +#define get_can_dlc (i) (min_t(__u8, (i), CAN_MAX_DLC)) +#define get_canfd_dlc (i) (min_t(__u8, (i), CANFD_MAX_DLC)) + +#define CAN_MTU (sizeof(struct can_frame)) +#define CANFD_MTU (sizeof(struct canfd_frame))/* Drop a given socketbuffer if it does not contain a valid CAN frame. */ static inline int can_dropped_invalid_skb(struct net_device *dev,
@@ -69,13 +73,23 @@ static inline int can_dropped_invalid_skb(struct net_device *dev, {const struct can_frame *cf = (struct can_frame *)skb->data; -if (unlikely (skb->len !=sizeof (*cf) || cf->can_dlc >8 )) { -kfree_skb (skb); - dev->stats.tx_dropped++; -return 1 ; - } +if (skb->protocol ==htons (ETH_P_CAN )) { +if (skb->len !=sizeof (struct can_frame ) || + cf->can_dlc >CAN_MAX_DLC ) + goto inval_skb; + }else if (skb->protocol ==htons (ETH_P_CANFD )) { +if (skb->len !=sizeof (struct canfd_frame ) || + cf->can_dlc >CANFD_MAX_DLC ) + goto inval_skb; + }else + goto inval_skb;return 0 ; + +inval_skb: +kfree_skb (skb); + dev->stats.tx_dropped++; +return 1 ; }struct net_device *alloc_candev (int sizeof_priv,unsigned int echo_skb_max);
include/linux/can/raw.h +2 -1
@@ -23,7 +23,8 @@ enum {CAN_RAW_FILTER =1 ,/* set 0 .. n can_filter(s) */ 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_RECV_OWN_MSGS ,/* receive my own msgs (default:off) */ + CAN_RAW_FD_FRAMES, /* use struct canfd_frame (default:off) */ };#endif
include/linux/if_ether.h +1 -0
@@ -119,6 +119,7 @@#define ETH_P_PHONET 0x00F5/* Nokia Phonet frames */ #define ETH_P_IEEE802154 0x00F6/* IEEE802.15.4 frame */ #define ETH_P_CAIF 0x00F7/* ST-Ericsson CAIF protocol */ +#define ETH_P_CANFD 0x00FD/* Controller Area Network FD */ /* * This is an Ethernet frame header.
net/can/af_can.c +74 -19
158 lines not on this page · raw message
net/can/bcm.c +2 -0
@@ -265,6 +265,7 @@ static void bcm_can_tx(struct bcm_op *op)/* send with loopback */ skb->dev = dev; skb->sk = op->sk; + skb->protocol =htons (ETH_P_CAN );can_send (skb,1 );/* update statistics */
@@ -1215,6 +1216,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk) skb->dev = dev; skb->sk = sk; + skb->protocol =htons (ETH_P_CAN ); err =can_send (skb,1 );/* send with loopback */ dev_put (dev);
net/can/raw.c +44 -2
93 lines not on this page · raw message
Quoted 21 lines · Oliver Hartkopp
Signed-off-by Oliver Hartkopp <[email protected]>drivers/net/can/dev.c +1
-1@@ -454,7 +454,7 @@ EXPORT_SYMBOL_GPL(can_bus_off);static void can_setup (struct net_device *dev) { dev->type =ARPHRD_CAN ; - dev->mtu =sizeof (struct can_frame ); + dev->mtu =CAN_MTU ; dev->hard_header_len =0 ; dev->addr_len =0 ; dev->tx_queue_len =10 ;drivers/net/can/vcan.c +0
-0
drivers/net/can/vcan.c static void vcan_rx(struct sk_buff *skb, struct net_device *dev) · line 77
Quoted 5 lines
drivers/net/can/vcan.c +1
-1@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats; stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc);
Hm, I think "cf->can_dlc" should contain the *real* length. That would simplify things a lot. The conversion is done when the corresponding DLC registers are read or written.
Wolfgang.
Oliver Hartkopp
maintainerQuoted 7 lines · Wolfgang Grandegger
Quoted 7 lines
drivers/net/can/vcan.c +0
-0@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats;
Quoted 7 lines
drivers/net/can/vcan.c static void vcan_rx(struct sk_buff *skb, struct net_device *dev) · line 77
Quoted 3 lines
drivers/net/can/vcan.c +1
-1stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc);Hm, I think "
cf->can_dlc" should contain the *real* length. That would simplify things a lot. The conversion is done when the corresponding DLC registers are read or written.
I thought about this idea some time too.
My problem was that 'can_dlc' says
"CAN data length *code*"
And the dlc for CAN is already well defined.
From a todays view cf->len would indeed be a better expression :-/
We could generally think about a union of 'can_dlc' and 'len' though, where can_dlc would not be part of struct canfd_frame but only the len value.
As you can see here, i also had the idea of providing both values:
But is was a bad design, as you have two APIs modifying one value - you never know what to trust ... it was a sanity check hell.
Regards,
Oliver
Quoted 18 lines · Oliver Hartkopp
Quoted 7 lines · Wolfgang Grandegger
Quoted 7 lines
drivers/net/can/vcan.c +0
-0@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats;Quoted 7 lines
drivers/net/can/vcan.c static void vcan_rx(struct sk_buff *skb, struct net_device *dev) · line 77
Quoted 3 lines
drivers/net/can/vcan.c +1
-1stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc);Hm, I think "
cf->can_dlc" should contain the *real* length. That would simplify things a lot. The conversion is done when the corresponding DLC registers are read or written.
Quoted 9 lines
I thought about this idea some time too.
My problem was that '
can_dlc' says"CAN data length *code*"
And the dlc for CAN is already well defined.
Quoted 1 line
From a todays view
cf->lenwould indeed be a better expression :-/
Yes, definitely.
Quoted 3 lines
We could generally think about a union of '
can_dlc' and 'len' though, wherecan_dlcwould not be part of structcanfd_framebut only the len value.
Well, we do not need dlc in the struct, just len. The conversion len->dlc needs just to be done once when register is read/written.
Quoted 6 lines
As you can see here, i also had the idea of providing both values:
But is was a bad design, as you have two APIs modifying one value - you never know what to trust ... it was a sanity check hell.
If "cf->can_dlc", or however it is named, does not contain the real length, we will end up in a dlc2len conversion nightmare. Be aware the the struct is also used by the app.
Wolfgang.
Re: [RFC] CAN FD support
Quoted 40 lines · Wolfgang Grandegger
Quoted 18 lines · Oliver Hartkopp
Quoted 7 lines · Wolfgang Grandegger
Quoted 7 lines
drivers/net/can/vcan.c +0
-0@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats;Quoted 7 lines
drivers/net/can/vcan.c static void vcan_rx(struct sk_buff *skb, struct net_device *dev) · line 77
Quoted 3 lines
drivers/net/can/vcan.c +1
-1stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc);Hm, I think "
cf->can_dlc" should contain the *real* length. That would simplify things a lot. The conversion is done when the corresponding DLC registers are read or written.Quoted 9 lines
I thought about this idea some time too.
My problem was that '
can_dlc' says"CAN data length *code*"
And the dlc for CAN is already well defined.
Quoted 1 line
From a todays view
cf->lenwould indeed be a better expression :-/Yes, definitely.
Quoted 3 lines
We could generally think about a union of '
can_dlc' and 'len' though, wherecan_dlcwould not be part of structcanfd_framebut only the len value.Well, we do not need dlc in the struct, just len. The conversion
len->dlcneeds just to be done once when register is read/written.Quoted 2 lines
As you can see here, i also had the idea of providing both values:
Quoted 7 lines
Quoted 4 lines
But is was a bad design, as you have two APIs modifying one value - you never know what to trust ... it was a sanity check hell.
If "
cf->can_dlc", or however it is named, does not contain the real length, we will end up in a dlc2len conversion nightmare. Be aware the
I share this.
I'd even prefer u16 over u8 even.
No legacy issues exist when changing the meaning of can_dlc, since current CAN frames have equal values for DLC & length!
Quoted 7 lines
the struct is also used by the app.
Wolfgang.
--
To unsubscribe from this list: send the line "unsubscribe linux-can" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Oliver Hartkopp
maintainerRe: [RFC] CAN FD support
Quoted 46 lines · Kurt Van Dijck
Quoted 45 lines · Wolfgang Grandegger
Quoted 18 lines · Oliver Hartkopp
Quoted 7 lines · Wolfgang Grandegger
Quoted 7 lines
drivers/net/can/vcan.c +0
-0@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats;Quoted 7 lines
drivers/net/can/vcan.c static void vcan_rx(struct sk_buff *skb, struct net_device *dev) · line 77
Quoted 3 lines
drivers/net/can/vcan.c +1
-1stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc);Hm, I think "
cf->can_dlc" should contain the *real* length. That would simplify things a lot. The conversion is done when the corresponding DLC registers are read or written.Quoted 9 lines
I thought about this idea some time too.
My problem was that '
can_dlc' says"CAN data length *code*"
And the dlc for CAN is already well defined.
Quoted 1 line
From a todays view
cf->lenwould indeed be a better expression :-/Yes, definitely.
Quoted 3 lines
We could generally think about a union of '
can_dlc' and 'len' though, wherecan_dlcwould not be part of structcanfd_framebut only the len value.Well, we do not need dlc in the struct, just len. The conversion
len->dlcneeds just to be done once when register is read/written.Quoted 6 lines
As you can see here, i also had the idea of providing both values:
But is was a bad design, as you have two APIs modifying one value - you never know what to trust ... it was a sanity check hell.
Quoted 9 lines
Quoted 2 lines
If "
cf->can_dlc", or however it is named, does not contain the real length, we will end up in a dlc2len conversion nightmare. Be aware theI share this.
I'd even prefer u16 over u8 even.
No legacy issues exist when changing the meaning ofcan_dlc, since current CAN frames have equal values for DLC & length!Quoted 1 line
the struct is also used by the app.
Yes - that's the main problem IMO.
What about this binary compatible introduction of cf->len ...
drivers/net/can/vcan.c +1 -1
@@ -74,7 +74,7 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats; stats->rx_packets++; - stats->rx_bytes +=can_dlc2len (cf->can_dlc); + stats->rx_bytes += cf->len; skb->pkt_type =PACKET_BROADCAST ; skb->dev = dev;
@@ -93,7 +93,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct
net_device *dev)
return NETDEV_TX_OK;
stats->tx_packets++;
- stats->tx_bytes += can_dlc2len(cf->can_dlc);
+ stats->tx_bytes += cf->len;
/* set flag whether this packet has to be looped back */ loop = skb->pkt_type == PACKET_LOOPBACK;
@@ -107,7 +107,7 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
* CAN core already did the echo for us */
stats->rx_packets++;
- stats->rx_bytes += can_dlc2len(cf->can_dlc);
+ stats->rx_bytes += cf->len;
}
kfree_skb(skb);
return NETDEV_TX_OK;
include/linux/can.h +5 -2
@@ -57,7 +57,10 @@ typedef __u32 can_err_mask_t;*/ struct can_frame {canid_t can_id;/* 32 bit CAN_ID + EFF/RTR/ERR flags */ -__u8 can_dlc;/* data length code: 0 .. 8 */ +union { +__u8 can_dlc;/* data length code: 0 .. 8 */ +__u8 len;/* data length: 0 .. 8 */ + };__u8 data[8 ] __attribute__((aligned (8 ))); };
@@ -84,7 +87,7 @@ struct can_frame {*/ struct canfd_frame {canid_t can_id;/* 32 bit CAN_ID + EFF/RTR/ERR flags */ -__u8 can_dlc;/* CAN FD data length code: 0 .. 0xF */ +__u8 len;/* data length: 0 .. 64 */ __u8 flags;/* additional flags for CAN FD */ __u8 __res0;/* reserved / padding */ __u8 __res1;/* reserved / padding */
net/can/af_can.c +1 -1
@@ -875,7 +875,7 @@ static __init int can_init(void) {/* check for correct padding that can_dlc owns always the same position */ BUILD_BUG_ON (offsetof(struct can_frame , can_dlc) != - offsetof(struct canfd_frame , can_dlc)); + offsetof(struct canfd_frame , len));printk (banner);
Re: [RFC] CAN FD support
Quoted 56 lines · Oliver Hartkopp
Quoted 54 lines · Kurt Van Dijck
Quoted 40 lines · Wolfgang Grandegger
Quoted 18 lines · Oliver Hartkopp
Quoted 7 lines · Wolfgang Grandegger
Quoted 7 lines
drivers/net/can/vcan.c +0
-0@@ -74,9 +74,8 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)struct net_device_stats *stats = &dev->stats;Quoted 7 lines
drivers/net/can/vcan.c static void vcan_rx(struct sk_buff *skb, struct net_device *dev) · line 77
Quoted 3 lines
drivers/net/can/vcan.c +1
-1stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + stats->rx_bytes +=can_dlc2len (cf->can_dlc);Hm, I think "
cf->can_dlc" should contain the *real* length. That would simplify things a lot. The conversion is done when the corresponding DLC registers are read or written.Quoted 9 lines
I thought about this idea some time too.
My problem was that '
can_dlc' says"CAN data length *code*"
And the dlc for CAN is already well defined.
Quoted 1 line
From a todays view
cf->lenwould indeed be a better expression :-/Yes, definitely.
Quoted 3 lines
We could generally think about a union of '
can_dlc' and 'len' though, wherecan_dlcwould not be part of structcanfd_framebut only the len value.Well, we do not need dlc in the struct, just len. The conversion
len->dlcneeds just to be done once when register is read/written.Quoted 2 lines
As you can see here, i also had the idea of providing both values:
Quoted 7 lines
Quoted 4 lines
But is was a bad design, as you have two APIs modifying one value - you never know what to trust ... it was a sanity check hell.
If "
cf->can_dlc", or however it is named, does not contain the real length, we will end up in a dlc2len conversion nightmare. Be aware theI share this.
I'd even prefer u16 over u8 even.
No legacy issues exist when changing the meaning ofcan_dlc, since current CAN frames have equal values for DLC & length!
Quoted 4 lines
Quoted 1 line
Quoted 1 line
the struct is also used by the app.
Yes - that's the main problem IMO.
Furthermore, the user should be allowed to specify *any* lenght below max, als 57 bytes. It's than up to the driver to do the necessary padding.
Quoted 2 lines
What about this binary compatible introduction of
cf->len...
Looks good.
Wolfgang.
Re: [RFC] CAN FD support
Quoted 3 lines
Furthermore, the user should be allowed to specify *any* lenght below max, als 57 bytes. It's than up to the driver to do the necessary padding.
I think Oliver solved this (on af_can level?) with a table len2dlc (static in the header?)
Quoted 5 lines
Quoted 3 lines
What about this binary compatible introduction of
cf->len...Looks good.
Yep, given 2 structs, this illustrates the contents very well!
Kurt
Oliver Hartkopp
maintainerRe: [RFC] CAN FD support
Quoted 4 lines · Kurt Van Dijck
Quoted 3 lines
Furthermore, the user should be allowed to specify *any* lenght below max, als 57 bytes. It's than up to the driver to do the necessary padding.
I think Oliver solved this (on
af_canlevel?) with a table len2dlc (static in the header?)
Yes - it was the only way not to make it clash when linking proc.o and af_can.o together.
Btw. if we move this functionality to the driver, i would like to move it from can.h into dev.c :-)
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines
What about this binary compatible introduction of
cf->len...Looks good.
Yep, given 2 structs, this illustrates the contents very well!
Fine.
One question:
What about omitting the union in struct can_frame modification and leave it as it is since the first days of SocketCAN?
We can still check these offsets
BUILD_BUG_ON(offsetof(struct can_frame, can_dlc) !=
- offsetof(struct canfd_frame, can_dlc));
+ offsetof(struct canfd_frame, len));
and can (kernel) internally use struct canfd_frame as reference:
struct canfd_frame *cfd = (struct canfd_frame *)skb->data; struct net_device_stats *stats = &dev->stats; stats->rx_packets++; stats->rx_bytes += cfd->len;
which would cover cf->can_dlc in the same way.
I wonder, if people would start to use can_frame.len once it is defined as this would not be backward compatible code (but binary compatible).
Regards,
Oliver
Marc Kleine-Budde
maintainerRe: [RFC] CAN FD support
In reply to Oliver HartkoppOn 05/03/2012 02:38 PM, Oliver Hartkopp wrote:
[...]
Quoted 11 lines
Quoted 6 lines
I share this.
I'd even prefer u16 over u8 even.
No legacy issues exist when changing the meaning ofcan_dlc, since current CAN frames have equal values for DLC & length!Quoted 1 line
the struct is also used by the app.
Yes - that's the main problem IMO.
What about this binary compatible introduction of
cf->len...
...but it's not 100% source compatible, due to a compiler bug in gcc. You cannot use C99 initializers on anonymous unions in certain gcc versions.
[..]
include/linux/can.h typedef __u32 can_err_mask_t; · line 65
Quoted 13 lines
include/linux/can.h +4
-1@@ -57,7 +57,10 @@ typedef __u32 can_err_mask_t;*/ struct can_frame {canid_t can_id;/* 32 bit CAN_ID + EFF/RTR/ERR flags */ -__u8 can_dlc;/* data length code: 0 .. 8 */ +union { +__u8 can_dlc;/* data length code: 0 .. 8 */ +__u8 len;/* data length: 0 .. 8 */ + };__u8 data[8 ] __attribute__((aligned (8 ))); };
Marc
Signature · 4 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
Oliver Hartkopp
maintainerRe: [RFC] CAN FD support
Quoted 11 lines · Marc Kleine-Budde
On 05/03/2012 02:38 PM, Oliver Hartkopp wrote:
[...]Quoted 8 lines
Quoted 6 lines
I share this.
I'd even prefer u16 over u8 even.
No legacy issues exist when changing the meaning ofcan_dlc, since current CAN frames have equal values for DLC & length!Quoted 1 line
the struct is also used by the app.
Quoted 6 lines
Quoted 3 lines
Yes - that's the main problem IMO.
What about this binary compatible introduction of
cf->len......but it's not 100% source compatible, due to a compiler bug in gcc. You cannot use C99 initializers on anonymous unions in certain gcc versions.
ugh!
Quoted 17 lines
[..]
include/linux/can.h typedef __u32 can_err_mask_t; · line 65
Quoted 13 lines
include/linux/can.h +4
-1@@ -57,7 +57,10 @@ typedef __u32 can_err_mask_t;*/ struct can_frame {canid_t can_id;/* 32 bit CAN_ID + EFF/RTR/ERR flags */ -__u8 can_dlc;/* data length code: 0 .. 8 */ +union { +__u8 can_dlc;/* data length code: 0 .. 8 */ +__u8 len;/* data length: 0 .. 8 */ + };__u8 data[8 ] __attribute__((aligned (8 ))); };
Thanks for the hint.
Indeed i left the struct can_frame as is now!
There's now can_frame.can_dlc and canfd_frame.len which both contains the real length - even if can_frame.can_dlc is literally a data length *code* .
Btw. by having canfd_frame.len we indicate for CAN FD that we have a real length here.
Regards,
Oliver