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:
parent
9c0c191d82
commit
1574481bb3
@ -33,28 +33,33 @@ struct vxcan_priv {
|
|||||||
struct net_device __rcu *peer;
|
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 vxcan_priv *priv = netdev_priv(dev);
|
||||||
struct net_device *peer;
|
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 net_device_stats *peerstats, *srcstats = &dev->stats;
|
||||||
|
struct sk_buff *skb;
|
||||||
u8 len;
|
u8 len;
|
||||||
|
|
||||||
if (can_dropped_invalid_skb(dev, skb))
|
if (can_dropped_invalid_skb(dev, oskb))
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
peer = rcu_dereference(priv->peer);
|
peer = rcu_dereference(priv->peer);
|
||||||
if (unlikely(!peer)) {
|
if (unlikely(!peer)) {
|
||||||
kfree_skb(skb);
|
kfree_skb(oskb);
|
||||||
dev->stats.tx_dropped++;
|
dev->stats.tx_dropped++;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb = can_create_echo_skb(skb);
|
skb = skb_clone(oskb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (skb) {
|
||||||
|
consume_skb(oskb);
|
||||||
|
} else {
|
||||||
|
kfree(oskb);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
/* reset CAN GW hop counter */
|
/* reset CAN GW hop counter */
|
||||||
skb->csum_start = 0;
|
skb->csum_start = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user