diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2013-01-17 12:43:39 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2013-01-26 10:59:01 -0500 |
commit | 156c2bb9f88065c8da78814f98fde665a5cbb527 (patch) | |
tree | ecd77a89c19ed0e1d420568f85769d7289ac3a37 /drivers/net/can/dev.c | |
parent | e2d5f2c7d66224c1a401ed1f797e467c02c025b8 (diff) |
can: add private data space for CAN sk_buffs
The struct can_skb_priv is used to transport additional information along
with the stored struct can(fd)_frame that can not be contained in existing
struct sk_buff elements.
can_skb_priv is located in the skb headroom, which does not touch the existing
CAN sk_buff usage with skb->data and skb->len, so that even out-of-tree
CAN drivers can be used without changes.
Btw. out-of-tree CAN drivers without can_skb_priv in the sk_buff headroom
would not support features based on can_skb_priv.
The can_skb_priv->ifindex contains the first interface where the CAN frame
appeared on the local host. Unfortunately skb->skb_iif can not be used as this
value is overwritten in every netif_receive_skb() call.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/dev.c')
-rw-r--r-- | drivers/net/can/dev.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 6abc6e59778e..59ada082a994 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/if_arp.h> | 24 | #include <linux/if_arp.h> |
25 | #include <linux/can.h> | 25 | #include <linux/can.h> |
26 | #include <linux/can/dev.h> | 26 | #include <linux/can/dev.h> |
27 | #include <linux/can/skb.h> | ||
27 | #include <linux/can/netlink.h> | 28 | #include <linux/can/netlink.h> |
28 | #include <linux/can/led.h> | 29 | #include <linux/can/led.h> |
29 | #include <net/rtnetlink.h> | 30 | #include <net/rtnetlink.h> |
@@ -502,13 +503,18 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) | |||
502 | { | 503 | { |
503 | struct sk_buff *skb; | 504 | struct sk_buff *skb; |
504 | 505 | ||
505 | skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); | 506 | skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) + |
507 | sizeof(struct can_frame)); | ||
506 | if (unlikely(!skb)) | 508 | if (unlikely(!skb)) |
507 | return NULL; | 509 | return NULL; |
508 | 510 | ||
509 | skb->protocol = htons(ETH_P_CAN); | 511 | skb->protocol = htons(ETH_P_CAN); |
510 | skb->pkt_type = PACKET_BROADCAST; | 512 | skb->pkt_type = PACKET_BROADCAST; |
511 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 513 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
514 | |||
515 | skb_reserve(skb, sizeof(struct can_skb_priv)); | ||
516 | ((struct can_skb_priv *)(skb->head))->ifindex = dev->ifindex; | ||
517 | |||
512 | *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | 518 | *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); |
513 | memset(*cf, 0, sizeof(struct can_frame)); | 519 | memset(*cf, 0, sizeof(struct can_frame)); |
514 | 520 | ||