vxcan: remove sk reference in peer skb
With can_create_echo_skb() the skb which is forwarded to the peer CAN interface shares the sk pointer from the originating socket. This makes the CAN frame show up in the peer namespace as a TX packet. With the use of skb_clone() analogue to the handling in gw.c the peer skb gets a new start in the peer namespace and correctly appears as a RX packet. Link: https://lore.kernel.org/all/20220309120416.83514-4-socketcan@hartkopp.net Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Родитель
9c0c191d82
Коммит
1574481bb3
|
@ -33,28 +33,33 @@ struct vxcan_priv {
|
|||
struct net_device __rcu *peer;
|
||||
};
|
||||
|
||||
static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t vxcan_xmit(struct sk_buff *oskb, struct net_device *dev)
|
||||
{
|
||||
struct vxcan_priv *priv = netdev_priv(dev);
|
||||
struct net_device *peer;
|
||||
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
struct canfd_frame *cfd = (struct canfd_frame *)oskb->data;
|
||||
struct net_device_stats *peerstats, *srcstats = &dev->stats;
|
||||
struct sk_buff *skb;
|
||||
u8 len;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dropped_invalid_skb(dev, oskb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
rcu_read_lock();
|
||||
peer = rcu_dereference(priv->peer);
|
||||
if (unlikely(!peer)) {
|
||||
kfree_skb(skb);
|
||||
kfree_skb(oskb);
|
||||
dev->stats.tx_dropped++;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
skb = can_create_echo_skb(skb);
|
||||
if (!skb)
|
||||
skb = skb_clone(oskb, GFP_ATOMIC);
|
||||
if (skb) {
|
||||
consume_skb(oskb);
|
||||
} else {
|
||||
kfree(oskb);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* reset CAN GW hop counter */
|
||||
skb->csum_start = 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче