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.

Merge branch 'move-can-skb-headroom-content-to-skb-extensions'

Oliver Hartkopp says:

====================
move CAN skb headroom content to skb extensions

CAN bus related skbuffs (ETH_P_CAN/ETH_P_CANFD/ETH_P_CANXL) simply contain
CAN frame structs for CAN CC/FD/XL of skb->len length at skb->data. Those
CAN skbs do not have network/mac/transport headers nor other such
references for encapsulated protocols like ethernet/IP protocols.

To store data for CAN specific use-cases all CAN bus related skbuffs are
created with a 16 byte private skb headroom (struct can_skb_priv). Using
the skb headroom and accessing skb->head for this private data led to
several problems in the past likely due to "The struct can_skb_priv
business is highly unconventional for the networking stack." [1]

This patch set aims to remove the unconventional skb headroom usage for CAN
bus related skbuffs and use the common skb extensions instead.

[1] https://lore.kernel.org/linux-can/20260104074222.29e660ac@kernel.org/

- v1: https://patch.msgid.link/20260125201601.5018-1-socketcan@hartkopp.net
- v2: https://lore.kernel.org/linux-can/20260128-can-skb-ext-v2-0-fe64aa152c8a@pengutronix.de/
- v4: https://lore.kernel.org/netdev/20260128-can_skb_ext-v1-0-330f60fd5d7e@hartkopp.net/
- v5: https://patch.msgid.link/20260129-can_skb_ext-v5-0-21252fdc8900@hartkopp.net
- v6: https://patch.msgid.link/20260130-can_skb_ext-v6-0-8fceafab7f26@hartkopp.net
- v7: https://patch.msgid.link/20260131-can_skb_ext-v7-0-dd0f8f84a83d@hartkopp.net

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
====================

Link: https://patch.msgid.link/20260201-can_skb_ext-v8-0-3635d790fe8b@hartkopp.net
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+286 -141
+1
MAINTAINERS
··· 5634 5634 F: include/linux/can/can-ml.h 5635 5635 F: include/linux/can/core.h 5636 5636 F: include/linux/can/skb.h 5637 + F: include/net/can.h 5637 5638 F: include/net/netns/can.h 5638 5639 F: include/uapi/linux/can.h 5639 5640 F: include/uapi/linux/can/bcm.h
+76 -45
drivers/net/can/dev/skb.c
··· 6 6 7 7 #include <linux/can/dev.h> 8 8 #include <linux/module.h> 9 + #include <net/can.h> 9 10 10 11 #define MOD_DESC "CAN device driver interface" 11 12 ··· 49 48 unsigned int idx, unsigned int frame_len) 50 49 { 51 50 struct can_priv *priv = netdev_priv(dev); 51 + struct can_skb_ext *csx; 52 52 53 53 if (idx >= priv->echo_skb_max) { 54 54 netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", ··· 76 74 skb->dev = dev; 77 75 78 76 /* save frame_len to reuse it when transmission is completed */ 79 - can_skb_prv(skb)->frame_len = frame_len; 77 + csx = can_skb_ext_find(skb); 78 + if (csx) 79 + csx->can_framelen = frame_len; 80 80 81 81 if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) 82 82 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ··· 115 111 * length is supported on both CAN and CANFD frames. 116 112 */ 117 113 struct sk_buff *skb = priv->echo_skb[idx]; 118 - struct can_skb_priv *can_skb_priv = can_skb_prv(skb); 114 + struct can_skb_ext *csx; 119 115 120 116 if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) 121 117 skb_tstamp_tx(skb, skb_hwtstamps(skb)); ··· 123 119 /* get the real payload length for netdev statistics */ 124 120 *len_ptr = can_skb_get_data_len(skb); 125 121 126 - if (frame_len_ptr) 127 - *frame_len_ptr = can_skb_priv->frame_len; 122 + if (frame_len_ptr) { 123 + csx = can_skb_ext_find(skb); 124 + if (csx) 125 + *frame_len_ptr = csx->can_framelen; 126 + else 127 + *frame_len_ptr = 0; 128 + } 128 129 129 130 priv->echo_skb[idx] = NULL; 130 131 ··· 189 180 190 181 if (priv->echo_skb[idx]) { 191 182 struct sk_buff *skb = priv->echo_skb[idx]; 192 - struct can_skb_priv *can_skb_priv = can_skb_prv(skb); 183 + struct can_skb_ext *csx; 193 184 194 - if (frame_len_ptr) 195 - *frame_len_ptr = can_skb_priv->frame_len; 185 + if (frame_len_ptr) { 186 + csx = can_skb_ext_find(skb); 187 + if (csx) 188 + *frame_len_ptr = csx->can_framelen; 189 + else 190 + *frame_len_ptr = 0; 191 + } 196 192 197 193 dev_kfree_skb_any(skb); 198 194 priv->echo_skb[idx] = NULL; ··· 206 192 EXPORT_SYMBOL_GPL(can_free_echo_skb); 207 193 208 194 /* fill common values for CAN sk_buffs */ 209 - static void init_can_skb_reserve(struct sk_buff *skb) 195 + static void init_can_skb(struct sk_buff *skb) 210 196 { 211 197 skb->pkt_type = PACKET_BROADCAST; 212 198 skb->ip_summed = CHECKSUM_UNNECESSARY; 213 - 214 - skb_reset_mac_header(skb); 215 - skb_reset_network_header(skb); 216 - skb_reset_transport_header(skb); 217 - 218 - can_skb_reserve(skb); 219 - can_skb_prv(skb)->skbcnt = 0; 220 199 } 221 200 222 201 struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) 223 202 { 224 203 struct sk_buff *skb; 204 + struct can_skb_ext *csx; 225 205 226 - skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) + 227 - sizeof(struct can_frame)); 228 - if (unlikely(!skb)) { 229 - *cf = NULL; 206 + skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); 207 + if (unlikely(!skb)) 208 + goto out_error_cc; 230 209 231 - return NULL; 210 + csx = can_skb_ext_add(skb); 211 + if (!csx) { 212 + kfree_skb(skb); 213 + goto out_error_cc; 232 214 } 233 215 234 216 skb->protocol = htons(ETH_P_CAN); 235 - init_can_skb_reserve(skb); 236 - can_skb_prv(skb)->ifindex = dev->ifindex; 217 + init_can_skb(skb); 218 + csx->can_iif = dev->ifindex; 237 219 238 220 *cf = skb_put_zero(skb, sizeof(struct can_frame)); 239 221 240 222 return skb; 223 + 224 + out_error_cc: 225 + *cf = NULL; 226 + 227 + return NULL; 241 228 } 242 229 EXPORT_SYMBOL_GPL(alloc_can_skb); 243 230 ··· 246 231 struct canfd_frame **cfd) 247 232 { 248 233 struct sk_buff *skb; 234 + struct can_skb_ext *csx; 249 235 250 - skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) + 251 - sizeof(struct canfd_frame)); 252 - if (unlikely(!skb)) { 253 - *cfd = NULL; 236 + skb = netdev_alloc_skb(dev, sizeof(struct canfd_frame)); 237 + if (unlikely(!skb)) 238 + goto out_error_fd; 254 239 255 - return NULL; 240 + csx = can_skb_ext_add(skb); 241 + if (!csx) { 242 + kfree_skb(skb); 243 + goto out_error_fd; 256 244 } 257 245 258 246 skb->protocol = htons(ETH_P_CANFD); 259 - init_can_skb_reserve(skb); 260 - can_skb_prv(skb)->ifindex = dev->ifindex; 247 + init_can_skb(skb); 248 + csx->can_iif = dev->ifindex; 261 249 262 250 *cfd = skb_put_zero(skb, sizeof(struct canfd_frame)); 263 251 ··· 268 250 (*cfd)->flags = CANFD_FDF; 269 251 270 252 return skb; 253 + 254 + out_error_fd: 255 + *cfd = NULL; 256 + 257 + return NULL; 271 258 } 272 259 EXPORT_SYMBOL_GPL(alloc_canfd_skb); 273 260 ··· 281 258 unsigned int data_len) 282 259 { 283 260 struct sk_buff *skb; 261 + struct can_skb_ext *csx; 284 262 285 263 if (data_len < CANXL_MIN_DLEN || data_len > CANXL_MAX_DLEN) 286 - goto out_error; 264 + goto out_error_xl; 287 265 288 - skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) + 289 - CANXL_HDR_SIZE + data_len); 266 + skb = netdev_alloc_skb(dev, CANXL_HDR_SIZE + data_len); 290 267 if (unlikely(!skb)) 291 - goto out_error; 268 + goto out_error_xl; 269 + 270 + csx = can_skb_ext_add(skb); 271 + if (!csx) { 272 + kfree_skb(skb); 273 + goto out_error_xl; 274 + } 292 275 293 276 skb->protocol = htons(ETH_P_CANXL); 294 - init_can_skb_reserve(skb); 295 - can_skb_prv(skb)->ifindex = dev->ifindex; 277 + init_can_skb(skb); 278 + csx->can_iif = dev->ifindex; 296 279 297 280 *cxl = skb_put_zero(skb, CANXL_HDR_SIZE + data_len); 298 281 ··· 308 279 309 280 return skb; 310 281 311 - out_error: 282 + out_error_xl: 312 283 *cxl = NULL; 313 284 314 285 return NULL; ··· 331 302 EXPORT_SYMBOL_GPL(alloc_can_err_skb); 332 303 333 304 /* Check for outgoing skbs that have not been created by the CAN subsystem */ 334 - static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb) 305 + static bool can_skb_init_valid(struct net_device *dev, struct sk_buff *skb) 335 306 { 336 - /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */ 337 - if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv))) 338 - return false; 307 + struct can_skb_ext *csx = can_skb_ext_find(skb); 339 308 340 309 /* af_packet does not apply CAN skb specific settings */ 341 - if (skb->ip_summed == CHECKSUM_NONE) { 342 - /* init headroom */ 343 - can_skb_prv(skb)->ifindex = dev->ifindex; 344 - can_skb_prv(skb)->skbcnt = 0; 310 + if (skb->ip_summed == CHECKSUM_NONE || !csx) { 311 + /* init CAN skb content */ 312 + if (!csx) { 313 + csx = can_skb_ext_add(skb); 314 + if (!csx) 315 + return false; 316 + } 345 317 318 + csx->can_iif = dev->ifindex; 346 319 skb->ip_summed = CHECKSUM_UNNECESSARY; 347 320 348 321 /* perform proper loopback on capable devices */ ··· 392 361 goto inval_skb; 393 362 } 394 363 395 - if (!can_skb_headroom_valid(dev, skb)) 364 + if (!can_skb_init_valid(dev, skb)) 396 365 goto inval_skb; 397 366 398 367 return false;
+14 -1
drivers/net/can/vxcan.c
··· 21 21 #include <linux/can/vxcan.h> 22 22 #include <linux/can/can-ml.h> 23 23 #include <linux/slab.h> 24 + #include <net/can.h> 24 25 #include <net/rtnetlink.h> 25 26 26 27 #define DRV_NAME "vxcan" ··· 40 39 struct vxcan_priv *priv = netdev_priv(dev); 41 40 struct net_device *peer; 42 41 struct net_device_stats *peerstats, *srcstats = &dev->stats; 42 + struct can_skb_ext *csx; 43 43 struct sk_buff *skb; 44 44 unsigned int len; 45 45 ··· 65 63 goto out_unlock; 66 64 } 67 65 66 + /* the cloned skb points to the skb extension of the already cloned 67 + * oskb with an increased refcount. skb_ext_add() creates a copy to 68 + * separate the skb extension data which is needed to start with a 69 + * fresh can_gw_hops counter in the other namespace. 70 + */ 71 + csx = skb_ext_add(skb, SKB_EXT_CAN); 72 + if (!csx) { 73 + kfree_skb(skb); 74 + goto out_unlock; 75 + } 76 + 68 77 /* reset CAN GW hop counter */ 69 - skb->csum_start = 0; 78 + csx->can_gw_hops = 0; 70 79 skb->pkt_type = PACKET_BROADCAST; 71 80 skb->dev = peer; 72 81 skb->ip_summed = CHECKSUM_UNNECESSARY;
+1
include/linux/can/core.h
··· 58 58 void *data); 59 59 60 60 extern int can_send(struct sk_buff *skb, int loop); 61 + void can_set_skb_uid(struct sk_buff *skb); 61 62 void can_sock_destruct(struct sock *sk); 62 63 63 64 #endif /* !_CAN_CORE_H */
+11 -27
include/linux/can/skb.h
··· 14 14 #include <linux/types.h> 15 15 #include <linux/skbuff.h> 16 16 #include <linux/can.h> 17 + #include <net/can.h> 17 18 #include <net/sock.h> 18 19 19 20 void can_flush_echo_skb(struct net_device *dev); ··· 38 37 struct can_frame **cf); 39 38 bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb); 40 39 41 - /* 42 - * The struct can_skb_priv is used to transport additional information along 43 - * with the stored struct can(fd)_frame that can not be contained in existing 44 - * struct sk_buff elements. 45 - * N.B. that this information must not be modified in cloned CAN sk_buffs. 46 - * To modify the CAN frame content or the struct can_skb_priv content 47 - * skb_copy() needs to be used instead of skb_clone(). 48 - */ 49 - 50 - /** 51 - * struct can_skb_priv - private additional data inside CAN sk_buffs 52 - * @ifindex: ifindex of the first interface the CAN frame appeared on 53 - * @skbcnt: atomic counter to have an unique id together with skb pointer 54 - * @frame_len: length of CAN frame in data link layer 55 - * @cf: align to the following CAN frame at skb->data 56 - */ 57 - struct can_skb_priv { 58 - int ifindex; 59 - int skbcnt; 60 - unsigned int frame_len; 61 - struct can_frame cf[]; 62 - }; 63 - 64 - static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb) 40 + static inline struct can_skb_ext *can_skb_ext_add(struct sk_buff *skb) 65 41 { 66 - return (struct can_skb_priv *)(skb->head); 42 + struct can_skb_ext *csx = skb_ext_add(skb, SKB_EXT_CAN); 43 + 44 + /* skb_ext_add() returns uninitialized space */ 45 + if (csx) 46 + csx->can_gw_hops = 0; 47 + 48 + return csx; 67 49 } 68 50 69 - static inline void can_skb_reserve(struct sk_buff *skb) 51 + static inline struct can_skb_ext *can_skb_ext_find(struct sk_buff *skb) 70 52 { 71 - skb_reserve(skb, sizeof(struct can_skb_priv)); 53 + return skb_ext_find(skb, SKB_EXT_CAN); 72 54 } 73 55 74 56 static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
+3
include/linux/skbuff.h
··· 4990 4990 #if IS_ENABLED(CONFIG_INET_PSP) 4991 4991 SKB_EXT_PSP, 4992 4992 #endif 4993 + #if IS_ENABLED(CONFIG_CAN) 4994 + SKB_EXT_CAN, 4995 + #endif 4993 4996 SKB_EXT_NUM, /* must be last */ 4994 4997 }; 4995 4998
+28
include/net/can.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ 2 + /* 3 + * net/can.h 4 + * 5 + * Definitions for the CAN network socket buffer extensions 6 + * 7 + * Copyright (C) 2026 Oliver Hartkopp <socketcan@hartkopp.net> 8 + * 9 + */ 10 + 11 + #ifndef _NET_CAN_H 12 + #define _NET_CAN_H 13 + 14 + /** 15 + * struct can_skb_ext - skb extensions for CAN specific content 16 + * @can_iif: ifindex of the first interface the CAN frame appeared on 17 + * @can_framelen: cached echo CAN frame length for bql 18 + * @can_gw_hops: can-gw CAN frame time-to-live counter 19 + * @can_ext_flags: CAN skb extensions flags 20 + */ 21 + struct can_skb_ext { 22 + int can_iif; 23 + u16 can_framelen; 24 + u8 can_gw_hops; 25 + u8 can_ext_flags; 26 + }; 27 + 28 + #endif /* _NET_CAN_H */
+1
net/can/Kconfig
··· 5 5 6 6 menuconfig CAN 7 7 tristate "CAN bus subsystem support" 8 + select SKB_EXTENSIONS 8 9 help 9 10 Controller Area Network (CAN) is a slow (up to 1Mbit/s) serial 10 11 communications protocol. Development of the CAN bus started in
+17 -6
net/can/af_can.c
··· 641 641 return matches; 642 642 } 643 643 644 + void can_set_skb_uid(struct sk_buff *skb) 645 + { 646 + /* create non-zero unique skb identifier together with *skb */ 647 + while (!(skb->hash)) 648 + skb->hash = atomic_inc_return(&skbcounter); 649 + 650 + skb->sw_hash = 1; 651 + } 652 + EXPORT_SYMBOL(can_set_skb_uid); 653 + 644 654 static void can_receive(struct sk_buff *skb, struct net_device *dev) 645 655 { 646 656 struct can_dev_rcv_lists *dev_rcv_lists; ··· 662 652 atomic_long_inc(&pkg_stats->rx_frames); 663 653 atomic_long_inc(&pkg_stats->rx_frames_delta); 664 654 665 - /* create non-zero unique skb identifier together with *skb */ 666 - while (!(can_skb_prv(skb)->skbcnt)) 667 - can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter); 655 + can_set_skb_uid(skb); 668 656 669 657 rcu_read_lock(); 670 658 ··· 687 679 static int can_rcv(struct sk_buff *skb, struct net_device *dev, 688 680 struct packet_type *pt, struct net_device *orig_dev) 689 681 { 690 - if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_can_skb(skb))) { 682 + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || 683 + !can_skb_ext_find(skb) || !can_is_can_skb(skb))) { 691 684 pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n", 692 685 dev->type, skb->len); 693 686 ··· 703 694 static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, 704 695 struct packet_type *pt, struct net_device *orig_dev) 705 696 { 706 - if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canfd_skb(skb))) { 697 + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || 698 + !can_skb_ext_find(skb) || !can_is_canfd_skb(skb))) { 707 699 pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n", 708 700 dev->type, skb->len); 709 701 ··· 719 709 static int canxl_rcv(struct sk_buff *skb, struct net_device *dev, 720 710 struct packet_type *pt, struct net_device *orig_dev) 721 711 { 722 - if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canxl_skb(skb))) { 712 + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || 713 + !can_skb_ext_find(skb) || !can_is_canxl_skb(skb))) { 723 714 pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n", 724 715 dev->type, skb->len); 725 716
+18 -8
net/can/bcm.c
··· 59 59 #include <linux/can/bcm.h> 60 60 #include <linux/slab.h> 61 61 #include <linux/spinlock.h> 62 + #include <net/can.h> 62 63 #include <net/sock.h> 63 64 #include <net/net_namespace.h> 64 65 ··· 292 291 static void bcm_can_tx(struct bcm_op *op) 293 292 { 294 293 struct sk_buff *skb; 294 + struct can_skb_ext *csx; 295 295 struct net_device *dev; 296 296 struct canfd_frame *cf; 297 297 int err; ··· 312 310 return; 313 311 } 314 312 315 - skb = alloc_skb(op->cfsiz + sizeof(struct can_skb_priv), gfp_any()); 313 + skb = alloc_skb(op->cfsiz, gfp_any()); 316 314 if (!skb) 317 315 goto out; 318 316 319 - can_skb_reserve(skb); 320 - can_skb_prv(skb)->ifindex = dev->ifindex; 321 - can_skb_prv(skb)->skbcnt = 0; 317 + csx = can_skb_ext_add(skb); 318 + if (!csx) { 319 + kfree_skb(skb); 320 + goto out; 321 + } 322 + 323 + csx->can_iif = dev->ifindex; 322 324 323 325 skb_put_data(skb, cf, op->cfsiz); 324 326 ··· 1324 1318 int cfsiz) 1325 1319 { 1326 1320 struct sk_buff *skb; 1321 + struct can_skb_ext *csx; 1327 1322 struct net_device *dev; 1328 1323 int err; 1329 1324 ··· 1332 1325 if (!ifindex) 1333 1326 return -ENODEV; 1334 1327 1335 - skb = alloc_skb(cfsiz + sizeof(struct can_skb_priv), GFP_KERNEL); 1328 + skb = alloc_skb(cfsiz, GFP_KERNEL); 1336 1329 if (!skb) 1337 1330 return -ENOMEM; 1338 1331 1339 - can_skb_reserve(skb); 1332 + csx = can_skb_ext_add(skb); 1333 + if (!csx) { 1334 + kfree_skb(skb); 1335 + return -ENOMEM; 1336 + } 1340 1337 1341 1338 err = memcpy_from_msg(skb_put(skb, cfsiz), msg, cfsiz); 1342 1339 if (err < 0) { ··· 1354 1343 return -ENODEV; 1355 1344 } 1356 1345 1357 - can_skb_prv(skb)->ifindex = dev->ifindex; 1358 - can_skb_prv(skb)->skbcnt = 0; 1346 + csx->can_iif = dev->ifindex; 1359 1347 skb->dev = dev; 1360 1348 can_skb_set_owner(skb, sk); 1361 1349 err = can_send(skb, 1); /* send with loopback */
+24 -18
net/can/gw.c
··· 55 55 #include <linux/can/core.h> 56 56 #include <linux/can/skb.h> 57 57 #include <linux/can/gw.h> 58 + #include <net/can.h> 58 59 #include <net/rtnetlink.h> 59 60 #include <net/net_namespace.h> 60 61 #include <net/sock.h> ··· 71 70 #define CGW_MAX_HOPS 6 72 71 #define CGW_DEFAULT_HOPS 1 73 72 74 - static unsigned int max_hops __read_mostly = CGW_DEFAULT_HOPS; 75 - module_param(max_hops, uint, 0444); 73 + static unsigned char max_hops __read_mostly = CGW_DEFAULT_HOPS; 74 + module_param(max_hops, byte, 0444); 76 75 MODULE_PARM_DESC(max_hops, 77 76 "maximum " CAN_GW_NAME " routing hops for CAN frames " 78 77 "(valid values: " __stringify(CGW_MIN_HOPS) "-" ··· 460 459 struct cgw_job *gwj = (struct cgw_job *)data; 461 460 struct canfd_frame *cf; 462 461 struct sk_buff *nskb; 462 + struct can_skb_ext *csx, *ncsx; 463 463 struct cf_mod *mod; 464 464 int modidx = 0; 465 465 ··· 473 471 return; 474 472 } 475 473 474 + csx = can_skb_ext_find(skb); 475 + if (!csx) 476 + return; 477 + 476 478 /* Do not handle CAN frames routed more than 'max_hops' times. 477 479 * In general we should never catch this delimiter which is intended 478 480 * to cover a misconfiguration protection (e.g. circular CAN routes). 479 - * 480 - * The Controller Area Network controllers only accept CAN frames with 481 - * correct CRCs - which are not visible in the controller registers. 482 - * According to skbuff.h documentation the csum_start element for IP 483 - * checksums is undefined/unused when ip_summed == CHECKSUM_UNNECESSARY. 484 - * Only CAN skbs can be processed here which already have this property. 485 481 */ 486 - 487 - #define cgw_hops(skb) ((skb)->csum_start) 488 - 489 - BUG_ON(skb->ip_summed != CHECKSUM_UNNECESSARY); 490 - 491 - if (cgw_hops(skb) >= max_hops) { 482 + if (csx->can_gw_hops >= max_hops) { 492 483 /* indicate deleted frames due to misconfiguration */ 493 484 gwj->deleted_frames++; 494 485 return; ··· 494 499 495 500 /* is sending the skb back to the incoming interface not allowed? */ 496 501 if (!(gwj->flags & CGW_FLAGS_CAN_IIF_TX_OK) && 497 - can_skb_prv(skb)->ifindex == gwj->dst.dev->ifindex) 502 + csx->can_iif == gwj->dst.dev->ifindex) 498 503 return; 499 504 500 505 /* clone the given skb, which has not been done in can_rcv() ··· 513 518 return; 514 519 } 515 520 521 + /* the cloned/copied nskb points to the skb extension of the original 522 + * skb with an increased refcount. skb_ext_add() creates a copy to 523 + * separate the skb extension data to modify the can_gw_hops. 524 + */ 525 + ncsx = skb_ext_add(nskb, SKB_EXT_CAN); 526 + if (!ncsx) { 527 + kfree_skb(nskb); 528 + gwj->dropped_frames++; 529 + return; 530 + } 531 + 516 532 /* put the incremented hop counter in the cloned skb */ 517 - cgw_hops(nskb) = cgw_hops(skb) + 1; 533 + ncsx->can_gw_hops = csx->can_gw_hops + 1; 518 534 519 535 /* first processing of this CAN frame -> adjust to private hop limit */ 520 - if (gwj->limit_hops && cgw_hops(nskb) == 1) 521 - cgw_hops(nskb) = max_hops - gwj->limit_hops + 1; 536 + if (gwj->limit_hops && ncsx->can_gw_hops == 1) 537 + ncsx->can_gw_hops = max_hops - gwj->limit_hops + 1; 522 538 523 539 nskb->dev = gwj->dst.dev; 524 540
+32 -14
net/can/isotp.c
··· 69 69 #include <linux/can/skb.h> 70 70 #include <linux/can/isotp.h> 71 71 #include <linux/slab.h> 72 + #include <net/can.h> 72 73 #include <net/sock.h> 73 74 #include <net/net_namespace.h> 74 75 ··· 215 214 { 216 215 struct net_device *dev; 217 216 struct sk_buff *nskb; 217 + struct can_skb_ext *csx; 218 218 struct canfd_frame *ncf; 219 219 struct isotp_sock *so = isotp_sk(sk); 220 220 int can_send_ret; 221 221 222 - nskb = alloc_skb(so->ll.mtu + sizeof(struct can_skb_priv), gfp_any()); 222 + nskb = alloc_skb(so->ll.mtu, gfp_any()); 223 223 if (!nskb) 224 224 return 1; 225 + 226 + csx = can_skb_ext_add(nskb); 227 + if (!csx) { 228 + kfree_skb(nskb); 229 + return 1; 230 + } 225 231 226 232 dev = dev_get_by_index(sock_net(sk), so->ifindex); 227 233 if (!dev) { ··· 236 228 return 1; 237 229 } 238 230 239 - can_skb_reserve(nskb); 240 - can_skb_prv(nskb)->ifindex = dev->ifindex; 241 - can_skb_prv(nskb)->skbcnt = 0; 242 - 231 + csx->can_iif = dev->ifindex; 243 232 nskb->dev = dev; 244 233 can_skb_set_owner(nskb, sk); 245 234 ncf = (struct canfd_frame *)nskb->data; ··· 768 763 { 769 764 struct sock *sk = &so->sk; 770 765 struct sk_buff *skb; 766 + struct can_skb_ext *csx; 771 767 struct net_device *dev; 772 768 struct canfd_frame *cf; 773 769 int can_send_ret; ··· 778 772 if (!dev) 779 773 return; 780 774 781 - skb = alloc_skb(so->ll.mtu + sizeof(struct can_skb_priv), GFP_ATOMIC); 775 + skb = alloc_skb(so->ll.mtu, GFP_ATOMIC); 782 776 if (!skb) { 783 777 dev_put(dev); 784 778 return; 785 779 } 786 780 787 - can_skb_reserve(skb); 788 - can_skb_prv(skb)->ifindex = dev->ifindex; 789 - can_skb_prv(skb)->skbcnt = 0; 781 + csx = can_skb_ext_add(skb); 782 + if (!csx) { 783 + kfree_skb(skb); 784 + netdev_put(dev, NULL); 785 + return; 786 + } 787 + 788 + csx->can_iif = dev->ifindex; 790 789 791 790 cf = (struct canfd_frame *)skb->data; 792 791 skb_put_zero(skb, so->ll.mtu); ··· 951 940 struct sock *sk = sock->sk; 952 941 struct isotp_sock *so = isotp_sk(sk); 953 942 struct sk_buff *skb; 943 + struct can_skb_ext *csx; 954 944 struct net_device *dev; 955 945 struct canfd_frame *cf; 956 946 int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; ··· 1012 1000 goto err_out_drop; 1013 1001 } 1014 1002 1015 - skb = sock_alloc_send_skb(sk, so->ll.mtu + sizeof(struct can_skb_priv), 1016 - msg->msg_flags & MSG_DONTWAIT, &err); 1003 + skb = sock_alloc_send_skb(sk, so->ll.mtu, msg->msg_flags & MSG_DONTWAIT, 1004 + &err); 1017 1005 if (!skb) { 1018 1006 dev_put(dev); 1019 1007 goto err_out_drop; 1020 1008 } 1021 1009 1022 - can_skb_reserve(skb); 1023 - can_skb_prv(skb)->ifindex = dev->ifindex; 1024 - can_skb_prv(skb)->skbcnt = 0; 1010 + csx = can_skb_ext_add(skb); 1011 + if (!csx) { 1012 + kfree_skb(skb); 1013 + netdev_put(dev, NULL); 1014 + err = -ENOMEM; 1015 + goto err_out_drop; 1016 + } 1017 + 1018 + csx->can_iif = dev->ifindex; 1025 1019 1026 1020 so->tx.len = size; 1027 1021 so->tx.idx = 0;
+11 -5
net/can/j1939/socket.c
··· 17 17 #include <linux/can/skb.h> 18 18 #include <linux/errqueue.h> 19 19 #include <linux/if_arp.h> 20 + #include <net/can.h> 20 21 21 22 #include "j1939-priv.h" 22 23 ··· 885 884 struct j1939_sock *jsk = j1939_sk(sk); 886 885 struct j1939_sk_buff_cb *skcb; 887 886 struct sk_buff *skb; 887 + struct can_skb_ext *csx; 888 888 int ret; 889 889 890 890 skb = sock_alloc_send_skb(sk, 891 891 size + 892 892 sizeof(struct can_frame) - 893 - sizeof(((struct can_frame *)NULL)->data) + 894 - sizeof(struct can_skb_priv), 893 + sizeof(((struct can_frame *)NULL)->data), 895 894 msg->msg_flags & MSG_DONTWAIT, &ret); 896 895 if (!skb) 897 896 goto failure; 898 897 899 - can_skb_reserve(skb); 900 - can_skb_prv(skb)->ifindex = ndev->ifindex; 901 - can_skb_prv(skb)->skbcnt = 0; 898 + csx = can_skb_ext_add(skb); 899 + if (!csx) { 900 + kfree_skb(skb); 901 + ret = -ENOMEM; 902 + goto failure; 903 + } 904 + 905 + csx->can_iif = ndev->ifindex; 902 906 skb_reserve(skb, offsetof(struct can_frame, data)); 903 907 904 908 ret = memcpy_from_msg(skb_put(skb, size), msg, size);
+30 -9
net/can/j1939/transport.c
··· 9 9 // Oleksij Rempel <kernel@pengutronix.de> 10 10 11 11 #include <linux/can/skb.h> 12 + #include <net/can.h> 12 13 13 14 #include "j1939-priv.h" 14 15 ··· 592 591 bool swap_src_dst) 593 592 { 594 593 struct sk_buff *skb; 594 + struct can_skb_ext *csx; 595 595 struct j1939_sk_buff_cb *skcb; 596 596 597 - skb = alloc_skb(sizeof(struct can_frame) + sizeof(struct can_skb_priv), 598 - GFP_ATOMIC); 597 + skb = alloc_skb(sizeof(struct can_frame), GFP_ATOMIC); 599 598 if (unlikely(!skb)) 600 599 return ERR_PTR(-ENOMEM); 601 600 601 + csx = can_skb_ext_add(skb); 602 + if (!csx) { 603 + kfree_skb(skb); 604 + return ERR_PTR(-ENOMEM); 605 + } 606 + 602 607 skb->dev = priv->ndev; 603 - can_skb_reserve(skb); 604 - can_skb_prv(skb)->ifindex = priv->ndev->ifindex; 605 - can_skb_prv(skb)->skbcnt = 0; 608 + csx->can_iif = priv->ndev->ifindex; 606 609 /* reserve CAN header */ 607 610 skb_reserve(skb, offsetof(struct can_frame, data)); 608 611 ··· 1053 1048 1054 1049 skb = skb_clone(se_skb, GFP_ATOMIC); 1055 1050 if (!skb) { 1051 + ret = -ENOMEM; 1052 + goto out_free; 1053 + } 1054 + 1055 + /* the cloned skb points to the skb extension of the original se_skb 1056 + * with an increased refcount. skb_ext_add() creates a copy to 1057 + * separate the skb extension data which is needed to modify the 1058 + * can_framelen in can_put_echo_skb(). 1059 + */ 1060 + if (!skb_ext_add(skb, SKB_EXT_CAN)) { 1061 + kfree_skb(skb); 1056 1062 ret = -ENOMEM; 1057 1063 goto out_free; 1058 1064 } ··· 1542 1526 const struct j1939_sk_buff_cb *rel_skcb) 1543 1527 { 1544 1528 struct sk_buff *skb; 1529 + struct can_skb_ext *csx; 1545 1530 struct j1939_sk_buff_cb *skcb; 1546 1531 struct j1939_session *session; 1547 1532 1548 - skb = alloc_skb(size + sizeof(struct can_skb_priv), GFP_ATOMIC); 1533 + skb = alloc_skb(size, GFP_ATOMIC); 1549 1534 if (unlikely(!skb)) 1550 1535 return NULL; 1551 1536 1537 + csx = can_skb_ext_add(skb); 1538 + if (!csx) { 1539 + kfree_skb(skb); 1540 + return NULL; 1541 + } 1542 + 1552 1543 skb->dev = priv->ndev; 1553 - can_skb_reserve(skb); 1554 - can_skb_prv(skb)->ifindex = priv->ndev->ifindex; 1555 - can_skb_prv(skb)->skbcnt = 0; 1544 + csx->can_iif = priv->ndev->ifindex; 1556 1545 skcb = j1939_skb_to_cb(skb); 1557 1546 memcpy(skcb, rel_skcb, sizeof(*skcb)); 1558 1547
+15 -8
net/can/raw.c
··· 53 53 #include <linux/can/core.h> 54 54 #include <linux/can/skb.h> 55 55 #include <linux/can/raw.h> 56 + #include <net/can.h> 56 57 #include <net/sock.h> 57 58 #include <net/net_namespace.h> 58 59 ··· 77 76 78 77 struct uniqframe { 79 78 const struct sk_buff *skb; 80 - int skbcnt; 79 + u32 hash; 81 80 unsigned int join_rx_count; 82 81 }; 83 82 ··· 165 164 166 165 /* eliminate multiple filter matches for the same skb */ 167 166 if (this_cpu_ptr(ro->uniq)->skb == oskb && 168 - this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) { 167 + this_cpu_ptr(ro->uniq)->hash == oskb->hash) { 169 168 if (!ro->join_filters) 170 169 return; 171 170 ··· 175 174 return; 176 175 } else { 177 176 this_cpu_ptr(ro->uniq)->skb = oskb; 178 - this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt; 177 + this_cpu_ptr(ro->uniq)->hash = oskb->hash; 179 178 this_cpu_ptr(ro->uniq)->join_rx_count = 1; 180 179 /* drop first frame to check all enabled filters? */ 181 180 if (ro->join_filters && ro->count > 1) ··· 919 918 struct raw_sock *ro = raw_sk(sk); 920 919 struct sockcm_cookie sockc; 921 920 struct sk_buff *skb; 921 + struct can_skb_ext *csx; 922 922 struct net_device *dev; 923 923 unsigned int txmtu; 924 924 int ifindex; ··· 953 951 goto put_dev; 954 952 } 955 953 956 - skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv), 957 - msg->msg_flags & MSG_DONTWAIT, &err); 954 + skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, 955 + &err); 958 956 if (!skb) 959 957 goto put_dev; 960 958 961 - can_skb_reserve(skb); 962 - can_skb_prv(skb)->ifindex = dev->ifindex; 963 - can_skb_prv(skb)->skbcnt = 0; 959 + csx = can_skb_ext_add(skb); 960 + if (!csx) { 961 + kfree_skb(skb); 962 + err = -ENOMEM; 963 + goto put_dev; 964 + } 965 + 966 + csx->can_iif = dev->ifindex; 964 967 965 968 /* fill the skb before testing for valid CAN frames */ 966 969 err = memcpy_from_msg(skb_put(skb, size), msg, size);
+4
net/core/skbuff.c
··· 78 78 #include <net/mpls.h> 79 79 #include <net/mptcp.h> 80 80 #include <net/mctp.h> 81 + #include <net/can.h> 81 82 #include <net/page_pool/helpers.h> 82 83 #include <net/psp/types.h> 83 84 #include <net/dropreason.h> ··· 5139 5138 #endif 5140 5139 #if IS_ENABLED(CONFIG_INET_PSP) 5141 5140 [SKB_EXT_PSP] = SKB_EXT_CHUNKSIZEOF(struct psp_skb_ext), 5141 + #endif 5142 + #if IS_ENABLED(CONFIG_CAN) 5143 + [SKB_EXT_CAN] = SKB_EXT_CHUNKSIZEOF(struct can_skb_ext), 5142 5144 #endif 5143 5145 }; 5144 5146