]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
can: use skb hash instead of private variable in headroom
authorOliver Hartkopp <socketcan@hartkopp.net>
Sun, 1 Feb 2026 14:33:16 +0000 (15:33 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 5 Feb 2026 10:58:39 +0000 (11:58 +0100)
The can_skb_priv::skbcnt variable is used to identify CAN skbs in the RX
path analogue to the skb->hash.

As the skb hash is not filled in CAN skbs move the private skbcnt value to
skb->hash and set skb->sw_hash accordingly. The skb->hash is a value used
for RPS to identify skbs. Use it as intended.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260201-can_skb_ext-v8-1-3635d790fe8b@hartkopp.net
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/can/dev/skb.c
include/linux/can/core.h
include/linux/can/skb.h
net/can/af_can.c
net/can/bcm.c
net/can/isotp.c
net/can/j1939/socket.c
net/can/j1939/transport.c
net/can/raw.c

index 3ebd4f779b9bdf9d0ce1d1b22b3ccdea2c8e841b..0da615afa04de7c3df16c189ef8c7c1664d1a681 100644 (file)
@@ -202,7 +202,6 @@ static void init_can_skb_reserve(struct sk_buff *skb)
        skb_reset_transport_header(skb);
 
        can_skb_reserve(skb);
-       can_skb_prv(skb)->skbcnt = 0;
 }
 
 struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
@@ -312,7 +311,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
        if (skb->ip_summed == CHECKSUM_NONE) {
                /* init headroom */
                can_skb_prv(skb)->ifindex = dev->ifindex;
-               can_skb_prv(skb)->skbcnt = 0;
 
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 
index 5fb8d0e3f9c1d027a2d5cd7c4eec7f2fa0340ed4..3287232e3cad92b8514bdad996fbaa02c8fe53fe 100644 (file)
@@ -58,6 +58,7 @@ extern void can_rx_unregister(struct net *net, struct net_device *dev,
                              void *data);
 
 extern int can_send(struct sk_buff *skb, int loop);
+void can_set_skb_uid(struct sk_buff *skb);
 void can_sock_destruct(struct sock *sk);
 
 #endif /* !_CAN_CORE_H */
index 1abc25a8d144e891c9a54cb8171ec44b25b83602..869ea574a40a194b27081ae5eeed701f91ec69c4 100644 (file)
@@ -49,13 +49,11 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
 /**
  * struct can_skb_priv - private additional data inside CAN sk_buffs
  * @ifindex:   ifindex of the first interface the CAN frame appeared on
- * @skbcnt:    atomic counter to have an unique id together with skb pointer
  * @frame_len: length of CAN frame in data link layer
  * @cf:                align to the following CAN frame at skb->data
  */
 struct can_skb_priv {
        int ifindex;
-       int skbcnt;
        unsigned int frame_len;
        struct can_frame cf[];
 };
index 770173d8db42813d5c085248d1bcf5fbe717955b..70659987ef4d27fc25aaecf01302306d3f7494d0 100644 (file)
@@ -641,6 +641,16 @@ static int can_rcv_filter(struct can_dev_rcv_lists *dev_rcv_lists, struct sk_buf
        return matches;
 }
 
+void can_set_skb_uid(struct sk_buff *skb)
+{
+       /* create non-zero unique skb identifier together with *skb */
+       while (!(skb->hash))
+               skb->hash = atomic_inc_return(&skbcounter);
+
+       skb->sw_hash = 1;
+}
+EXPORT_SYMBOL(can_set_skb_uid);
+
 static void can_receive(struct sk_buff *skb, struct net_device *dev)
 {
        struct can_dev_rcv_lists *dev_rcv_lists;
@@ -652,9 +662,7 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
        atomic_long_inc(&pkg_stats->rx_frames);
        atomic_long_inc(&pkg_stats->rx_frames_delta);
 
-       /* create non-zero unique skb identifier together with *skb */
-       while (!(can_skb_prv(skb)->skbcnt))
-               can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter);
+       can_set_skb_uid(skb);
 
        rcu_read_lock();
 
index 7eba8ae01a5b1bb06fb745b6e656fa23b3935fd6..8ed60f18c2eaff7053cb2c76e5e4cf1124dd3ac5 100644 (file)
@@ -316,7 +316,6 @@ static void bcm_can_tx(struct bcm_op *op)
 
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = dev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
 
        skb_put_data(skb, cf, op->cfsiz);
 
@@ -1344,7 +1343,6 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk,
        }
 
        can_skb_prv(skb)->ifindex = dev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
        skb->dev = dev;
        can_skb_set_owner(skb, sk);
        err = can_send(skb, 1); /* send with loopback */
index ce588b85665a05a28aa499e72ce5db32ecb66126..4bb60b8f9b96188a328e77be2fdefcb879da1089 100644 (file)
@@ -230,7 +230,6 @@ static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus)
 
        can_skb_reserve(nskb);
        can_skb_prv(nskb)->ifindex = dev->ifindex;
-       can_skb_prv(nskb)->skbcnt = 0;
 
        nskb->dev = dev;
        can_skb_set_owner(nskb, sk);
@@ -780,7 +779,6 @@ static void isotp_send_cframe(struct isotp_sock *so)
 
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = dev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
 
        cf = (struct canfd_frame *)skb->data;
        skb_put_zero(skb, so->ll.mtu);
@@ -1009,7 +1007,6 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = dev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
 
        so->tx.len = size;
        so->tx.idx = 0;
index ff9c4fd7b4337a0ba8fa6846be4a9da35c232049..1589e8ca634ecc2b59eb0c2a1e48f546fafccbe0 100644 (file)
@@ -897,7 +897,6 @@ static struct sk_buff *j1939_sk_alloc_skb(struct net_device *ndev,
 
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = ndev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
        skb_reserve(skb, offsetof(struct can_frame, data));
 
        ret = memcpy_from_msg(skb_put(skb, size), msg, size);
index 8656ab388c83e68b7f779b7bc0ac97a8d0d009e5..d5d3e5320f7ac5fb247756f6413ab448c75447f6 100644 (file)
@@ -601,7 +601,6 @@ sk_buff *j1939_tp_tx_dat_new(struct j1939_priv *priv,
        skb->dev = priv->ndev;
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = priv->ndev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
        /* reserve CAN header */
        skb_reserve(skb, offsetof(struct can_frame, data));
 
@@ -1536,7 +1535,6 @@ j1939_session *j1939_session_fresh_new(struct j1939_priv *priv,
        skb->dev = priv->ndev;
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = priv->ndev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
        skcb = j1939_skb_to_cb(skb);
        memcpy(skcb, rel_skcb, sizeof(*skcb));
 
index 12293363413ce6906b068e45d000d188836f6a91..fb4f9c854df04d90ed6bd4601c616ac39bb85ad9 100644 (file)
@@ -76,7 +76,7 @@ MODULE_ALIAS("can-proto-1");
 
 struct uniqframe {
        const struct sk_buff *skb;
-       int skbcnt;
+       u32 hash;
        unsigned int join_rx_count;
 };
 
@@ -164,7 +164,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
 
        /* eliminate multiple filter matches for the same skb */
        if (this_cpu_ptr(ro->uniq)->skb == oskb &&
-           this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
+           this_cpu_ptr(ro->uniq)->hash == oskb->hash) {
                if (!ro->join_filters)
                        return;
 
@@ -174,7 +174,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
                        return;
        } else {
                this_cpu_ptr(ro->uniq)->skb = oskb;
-               this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
+               this_cpu_ptr(ro->uniq)->hash = oskb->hash;
                this_cpu_ptr(ro->uniq)->join_rx_count = 1;
                /* drop first frame to check all enabled filters? */
                if (ro->join_filters && ro->count > 1)
@@ -958,7 +958,6 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
        can_skb_reserve(skb);
        can_skb_prv(skb)->ifindex = dev->ifindex;
-       can_skb_prv(skb)->skbcnt = 0;
 
        /* fill the skb before testing for valid CAN frames */
        err = memcpy_from_msg(skb_put(skb, size), msg, size);