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: netlink: add CAN_CTRLMODE_RESTRICTED

ISO 11898-1:2024 adds a new restricted operation mode. This mode is
added as a mandatory feature for nodes which support CAN XL and is
retrofitted as optional for legacy nodes (i.e. the ones which only
support Classical CAN and CAN FD).

The restricted operation mode is nearly the same as the listen only
mode: the node can not send data frames or remote frames and can not
send dominant bits if an error occurs. The only exception is that the
node shall still send the acknowledgment bit. A second niche exception
is that the node may still send a data frame containing a time
reference message if the node is a primary time provider, but because
the time provider feature is not yet implemented in the kernel, this
second exception is not relevant to us at the moment.

Add the CAN_CTRLMODE_RESTRICTED control mode flag and update the
can_dev_dropped_skb() helper function accordingly.

Finally, bail out if both CAN_CTRLMODE_LISTENONLY and
CAN_CTRLMODE_RESTRICTED are provided.

Signed-off-by: Vincent Mailhol <mailhol@kernel.org>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20251126-canxl-v8-4-e7e3eb74f889@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Vincent Mailhol and committed by
Marc Kleine-Budde
60f511f4 d037d05c

+36 -24
+2
drivers/net/can/dev/dev.c
··· 115 115 return "TDC-AUTO"; 116 116 case CAN_CTRLMODE_TDC_MANUAL: 117 117 return "TDC-MANUAL"; 118 + case CAN_CTRLMODE_RESTRICTED: 119 + return "RESTRICTED"; 118 120 default: 119 121 return "<unknown>"; 120 122 }
+7
drivers/net/can/dev/netlink.c
··· 188 188 struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); 189 189 190 190 flags = cm->flags & cm->mask; 191 + 192 + if ((flags & CAN_CTRLMODE_LISTENONLY) && 193 + (flags & CAN_CTRLMODE_RESTRICTED)) { 194 + NL_SET_ERR_MSG(extack, 195 + "LISTEN-ONLY and RESTRICTED modes are mutually exclusive"); 196 + return -EOPNOTSUPP; 197 + } 191 198 } 192 199 193 200 err = can_validate_bittiming(data, extack, IFLA_CAN_BITTIMING);
+26 -24
include/linux/can/dev.h
··· 95 95 return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU); 96 96 } 97 97 98 - /* drop skb if it does not contain a valid CAN frame for sending */ 99 - static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb) 100 - { 101 - struct can_priv *priv = netdev_priv(dev); 102 - 103 - if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) { 104 - netdev_info_once(dev, 105 - "interface in listen only mode, dropping skb\n"); 106 - goto invalid_skb; 107 - } 108 - 109 - if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { 110 - netdev_info_once(dev, "CAN FD is disabled, dropping skb\n"); 111 - goto invalid_skb; 112 - } 113 - 114 - return can_dropped_invalid_skb(dev, skb); 115 - 116 - invalid_skb: 117 - kfree_skb(skb); 118 - dev->stats.tx_dropped++; 119 - return true; 120 - } 121 - 122 98 void can_setup(struct net_device *dev); 123 99 124 100 struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, ··· 129 153 130 154 const char *can_get_state_str(const enum can_state state); 131 155 const char *can_get_ctrlmode_str(u32 ctrlmode); 156 + 157 + /* drop skb if it does not contain a valid CAN frame for sending */ 158 + static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb) 159 + { 160 + struct can_priv *priv = netdev_priv(dev); 161 + u32 silent_mode = priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY | 162 + CAN_CTRLMODE_RESTRICTED); 163 + 164 + if (silent_mode) { 165 + netdev_info_once(dev, "interface in %s mode, dropping skb\n", 166 + can_get_ctrlmode_str(silent_mode)); 167 + goto invalid_skb; 168 + } 169 + 170 + if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) { 171 + netdev_info_once(dev, "CAN FD is disabled, dropping skb\n"); 172 + goto invalid_skb; 173 + } 174 + 175 + return can_dropped_invalid_skb(dev, skb); 176 + 177 + invalid_skb: 178 + kfree_skb(skb); 179 + dev->stats.tx_dropped++; 180 + return true; 181 + } 132 182 133 183 void can_state_get_by_berr_counter(const struct net_device *dev, 134 184 const struct can_berr_counter *bec,
+1
include/uapi/linux/can/netlink.h
··· 103 103 #define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ 104 104 #define CAN_CTRLMODE_TDC_AUTO 0x200 /* FD transceiver automatically calculates TDCV */ 105 105 #define CAN_CTRLMODE_TDC_MANUAL 0x400 /* FD TDCV is manually set up by user */ 106 + #define CAN_CTRLMODE_RESTRICTED 0x800 /* Restricted operation mode */ 106 107 107 108 /* 108 109 * CAN device statistics