: VLAN update
Subsystems (4)
cover : VLAN update
These patches include an updated set of the VLAN packet socket fixes, now also supporting VLAN TCI delivery to userspace using mmaped packet sockets, as well as a patch to add ->get_flags ethtool support and a few minor cleanup patches.
To recap the VLAN packet socket problems fixed by these patches:
- With hardware tagging, outgoing packets are visible without the VLAN header, while with software tagging the full VLAN header is visible
- With hardware stripping, incoming packets for locally configured VLANs appear on the VLAN device without being visible on the underlying device. Packets for unknown VLANs are not visible at all. Without hardware stripping, all VLAN packets are visible on the underlying device.
The patches move the VLAN TCI from skb->cb to a new skb member to avoid clashes with qdiscs and packet sockets use of skb->cb. On the TX path this is enough to make sure that packet sockets can be made aware of the VLAN TCI. On the hardware accelerated RX path, we also store the VLAN TCI in the skb and manually invoke the ptype_all handlers. The packet socket code stores the TCI in either the auxdata (for regular packet sockets) or the new tpacket2_hdr (for mmaped packet sockets) and delivers it to userspace, where it can be used to reconstruct the VLAN header.
The only remaining problem is that socket filters contructed for VLAN headers don't work properly since no header is present. Since with the approach taken by these patches, userspace has to be aware of VLAN acceleration anyway, it seems reasonable to add a new filter instruction for getting the VLAN TCI from the skb and expect it to construct its filters accordingly. This is not done so far however, other suggestions are still welcome :)
include/linux/if_packet.h | 23 ++++++ include/linux/if_vlan.h | 31 ++------ include/linux/netdevice.h | 1 + include/linux/skbuff.h | 3 + net/8021q/vlan.c | 8 +-- net/8021q/vlan_core.c | 4 + net/8021q/vlan_dev.c | 116 +++++++---------------------- net/8021q/vlanproc.c | 11 +-- net/core/dev.c | 27 +++++++ net/core/skbuff.c | 3 + net/packet/af_packet.c | 181 ++++++++++++++++++++++++++++++++++++-------- 11 files changed, 248 insertions(+), 160 deletions(-)
Patrick McHardy (8):
vlan: Don't store VLAN tag in cb
vlan: deliver packets received with VLAN acceleration to network taps
packet: support extensible, 64 bit clean mmaped ring structure
packet: deliver VLAN TCI to userspace
vlan: ethtool ->get_flags support
vlan: clean up vlan_dev_hard_header()
vlan: clean up hard_start_xmit functions
vlan: remove unnecessary include statements
PATCH 1/8 : vlan: Don't store VLAN tag in cb
vlan: Don't store VLAN tag in cb
Use a real skb member to store the skb to avoid clashes with qdiscs, which are allowed to use the cb area themselves. As currently only real devices that consume the skb set the NETIF_F_HW_VLAN_TX flag, no explicit invalidation is neccessary.
The new member fills a hole on 64 bit, the skb layout changes from:
__u32 mark; /* 172 4 */
sk_buff_data_t transport_header; /* 176 4 */
sk_buff_data_t network_header; /* 180 4 */
sk_buff_data_t mac_header; /* 184 4 */
sk_buff_data_t tail; /* 188 4 */
/* --- cacheline 3 boundary (192 bytes) --- */
sk_buff_data_t end; /* 192 4 */
/* XXX 4 bytes hole, try to pack */to
__u32 mark; /* 172 4 */
__u16 vlan_tci; /* 176 2 *//* XXX 2 bytes hole, try to pack */
sk_buff_data_t transport_header; /* 180 4 */
sk_buff_data_t network_header; /* 184 4 */
---
commit 5188944208232be946dbfa41e4e81cd13a5cc63f
tree c64a83b5852c11c1e970ca8d4955892a210138eb
parent 66f29353205907c92f202b6db8c143c7969cbedf
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 12:38:27 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 12:38:27 +0200
include/linux/if_vlan.h | 31 +++++++------------------------ include/linux/skbuff.h | 3 +++ net/core/skbuff.c | 3 +++ 3 files changed, 13 insertions(+), 24 deletions(-)
include/linux/if_vlan.h +7 -24
@@ -105,17 +105,8 @@ static inline void vlan_group_set_device(struct vlan_group *vg, array[vlan_id %VLAN_GROUP_ARRAY_PART_LEN ] = dev; } -/* VLAN tx hw acceleration helpers. */ -struct vlan_skb_tx_cookie { -u32 magic; -u32 vlan_tag; -}; - -#define VLAN_TX_COOKIE_MAGIC 0x564c414e/* "VLAN" in ascii. */ -#define VLAN_TX_SKB_CB (__skb) ((struct vlan_skb_tx_cookie *)&((__skb)->cb[0])) -#define vlan_tx_tag_present (__skb) \ - (VLAN_TX_SKB_CB(__skb)->magic == VLAN_TX_COOKIE_MAGIC) -#define vlan_tx_tag_get (__skb) (VLAN_TX_SKB_CB(__skb)->vlan_tag) +#define vlan_tx_tag_present (__skb) ((__skb)->vlan_tci) +#define vlan_tx_tag_get (__skb) ((__skb)->vlan_tci)#if defined(CONFIG_VLAN_8021Q ) || defined(CONFIG_VLAN_8021Q_MODULE )extern struct net_device *vlan_dev_real_dev (const struct net_device *dev);
@@ -210,17 +201,12 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)* @skb: skbuff to tag * @vlan_tci: VLAN TCI to insert * -* Puts the VLAN TCI in @skb->cb[] and lets the device do the rest +* Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest */ static inline struct sk_buff *__vlan_hwaccel_put_tag (struct sk_buff *skb,u16 vlan_tci) { -struct vlan_skb_tx_cookie *cookie; - - cookie =VLAN_TX_SKB_CB (skb); - cookie->magic =VLAN_TX_COOKIE_MAGIC ; - cookie->vlan_tag = vlan_tci; - + skb->vlan_tci = vlan_tci;return skb; }
@@ -267,16 +253,13 @@ static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)* @skb: skbuff to query * @vlan_tci: buffer to store vlaue * -* Returns error if @skb->cb[] is not set correctly +* Returns error if @skb->vlan_tci is not set correctly */ static inline int __vlan_hwaccel_get_tag (const struct sk_buff *skb,u16 *vlan_tci) { -struct vlan_skb_tx_cookie *cookie; - - cookie =VLAN_TX_SKB_CB (skb); -if (cookie->magic ==VLAN_TX_COOKIE_MAGIC ) { - *vlan_tci = cookie->vlan_tag; +if (vlan_tx_tag_present (skb)) { + *vlan_tci = skb->vlan_tci;return 0 ; }else { *vlan_tci =0 ;
include/linux/skbuff.h +3 -0
@@ -246,6 +246,7 @@ typedef unsigned char *sk_buff_data_t;* @dma_cookie: a cookie to one of several possible DMA operations * done by skb DMA functions * @secmark: security marking +* @vlan_tci: vlan tag control information */ struct sk_buff {
@@ -326,6 +327,8 @@ struct sk_buff {__u32 mark; +__u16 vlan_tci; +sk_buff_data_t transport_header;sk_buff_data_t network_header;sk_buff_data_t mac_header;
net/core/skbuff.c +3 -0
@@ -459,6 +459,8 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->tc_verd = old->tc_verd;#endif #endif + new->vlan_tci = old->vlan_tci; +skb_copy_secmark (new, old); }
@@ -2286,6 +2288,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)skb_copy_queue_mapping (nskb, skb); nskb->priority = skb->priority; nskb->protocol = skb->protocol; + nskb->vlan_tci = skb->vlan_tci; nskb->dst =dst_clone (skb->dst);memcpy (nskb->cb, skb->cb,sizeof (skb->cb)); nskb->pkt_type = skb->pkt_type;
PATCH 2/8 : vlan: deliver packets received with VLAN acceleration to network taps
In reply to Patrick McHardyvlan: deliver packets received with VLAN acceleration to network taps
When VLAN header stripping is used, packets currently bypass packet sockets (and other network taps) completely. For locally existing VLANs, they appear directly on the VLAN device, for unknown VLANs they are silently dropped.
Add a new function netif_nit_deliver() to deliver incoming packets to all network interface taps and use it in __vlan_hwaccel_rx() to make VLAN packets visible on the underlying device.
---
commit 2150bca3247c0b497a83937005367092bca86530
tree 1a1c894d2d360dd2b90a759485ae0e2e0a441b41
parent 5188944208232be946dbfa41e4e81cd13a5cc63f
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 12:38:27 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 12:38:27 +0200
include/linux/netdevice.h | 1 + net/8021q/vlan_core.c | 4 ++++ net/core/dev.c | 27 +++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 0 deletions(-)
include/linux/netdevice.h +1 -0
@@ -1152,6 +1152,7 @@ extern int netif_rx(struct sk_buff *skb);extern int netif_rx_ni (struct sk_buff *skb);#define HAVE_NETIF_RECEIVE_SKB 1extern int netif_receive_skb (struct sk_buff *skb); +extern void netif_nit_deliver (struct sk_buff *skb);extern int dev_valid_name (const char *name);extern int dev_ioctl (struct net *net,unsigned int cmd,void __user *);extern int dev_ethtool (struct net *net,struct ifreq *);
net/8021q/vlan_core.c +4 -0
@@ -14,6 +14,9 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,return NET_RX_DROP ; } + skb->vlan_tci = vlan_tci; +netif_nit_deliver (skb); + skb->dev =vlan_group_get_device (grp, vlan_tci &VLAN_VID_MASK );if (skb->dev ==NULL ) {dev_kfree_skb_any (skb);
@@ -22,6 +25,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,return NET_RX_SUCCESS ; } skb->dev->last_rx = jiffies; + skb->vlan_tci =0 ; stats = &skb->dev->stats; stats->rx_packets++;
net/core/dev.c +27 -0
@@ -2068,6 +2068,33 @@ out: }#endif +/* +* netif_tap_deliver - deliver received packets to network taps +* @skb: buffer +* +* This function is used to deliver incoming packets to network +* taps. It should be used when the normal netif_receive_skb path +* is bypassed, for example because of VLAN acceleration. +*/ +void netif_nit_deliver (struct sk_buff *skb) +{ +struct packet_type *ptype; + +if (list_empty (&ptype_all)) +return ; + +skb_reset_network_header (skb); +skb_reset_transport_header (skb); + skb->mac_len = skb->network_header - skb->mac_header; + +rcu_read_lock (); +list_for_each_entry_rcu (ptype, &ptype_all, list) { +if (!ptype->dev || ptype->dev == skb->dev) +deliver_skb (skb, ptype, skb->dev); + } +rcu_read_unlock (); +} +/** * netif_receive_skb - process receive buffer from network * @skb: buffer to process
Re: [PATCH 02/08]: vlan: deliver packets received with VLAN acceleration to network taps
Quoted 10 lines · Patrick McHardy
vlan: deliver packets received with VLAN acceleration to network taps
When VLAN header stripping is used, packets currently bypass packet sockets (and other network taps) completely. For locally existing VLANs, they appear directly on the VLAN device, for unknown VLANs they are silently dropped.
Add a new function
netif_nit_deliver()to deliver incoming packets to all network interface taps and use it in__vlan_hwaccel_rx()to make VLAN packets visible on the underlying device.
[...]
net/core/dev.c out: · line 2079
Quoted 9 lines
net/core/dev.c +9
-0+/* +* netif_tap_deliver - deliver received packets to network taps +* @skb: buffer +* +* This function is used to deliver incoming packets to network +* taps. It should be used when the normal netif_receive_skb path +* is bypassed, for example because of VLAN acceleration. +*/ +void netif_nit_deliver (struct sk_buff *skb)
[...]
Is it supposed to be called netif_nit_deliver() or netif_tap_deliver()?
Ben.
Signature · 2 lines
Ben Hutchings, Senior Software Engineer, Solarflare Communications Not speaking for my employer; that's the marketing department's job.
Re: [PATCH 02/08]: vlan: deliver packets received with VLAN acceleration to network taps
Quoted 23 lines · Ben Hutchings
Quoted 10 lines · Patrick McHardy
vlan: deliver packets received with VLAN acceleration to network taps
When VLAN header stripping is used, packets currently bypass packet sockets (and other network taps) completely. For locally existing VLANs, they appear directly on the VLAN device, for unknown VLANs they are silently dropped.
Add a new function
netif_nit_deliver()to deliver incoming packets to all network interface taps and use it in__vlan_hwaccel_rx()to make VLAN packets visible on the underlying device.[...]
Quoted 9 lines
(quoted diff) +9
-0+/* + * netif_tap_deliver - deliver received packets to network taps + * @skb: buffer + * + * This function is used to deliver incoming packets to network + * taps. It should be used when the normal netif_receive_skb path + * is bypassed, for example because of VLAN acceleration. + */ +void netif_nit_deliver(struct sk_buff *skb)[...]
Quoted 1 line
Is it supposed to be called
netif_nit_deliver()ornetif_tap_deliver()?
Thanks, seems I only renamed it half way :)
Fixed patch attached.
commit d5c10a9dd25c8c9333e12d92cd81191a37376097
Author: Patrick McHardy <[email protected]> Date: Wed Jul 9 14:37:44 2008 +0200
vlan: deliver packets received with VLAN acceleration to network taps
When VLAN header stripping is used, packets currently bypass packet sockets (and other network taps) completely. For locally existing VLANs, they appear directly on the VLAN device, for unknown VLANs they are silently dropped.
Add a new function netif_nit_deliver() to deliver incoming packets to all network interface taps and use it in __vlan_hwaccel_rx() to make VLAN packets visible on the underlying device.
include/linux/netdevice.h +1 -0
@@ -1152,6 +1152,7 @@ extern int netif_rx(struct sk_buff *skb);extern int netif_rx_ni (struct sk_buff *skb);#define HAVE_NETIF_RECEIVE_SKB 1extern int netif_receive_skb (struct sk_buff *skb); +extern void netif_nit_deliver (struct sk_buff *skb);extern int dev_valid_name (const char *name);extern int dev_ioctl (struct net *net,unsigned int cmd,void __user *);extern int dev_ethtool (struct net *net,struct ifreq *);
net/8021q/vlan_core.c +4 -0
@@ -14,6 +14,9 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,return NET_RX_DROP ; } + skb->vlan_tci = vlan_tci; +netif_nit_deliver (skb); + skb->dev =vlan_group_get_device (grp, vlan_tci &VLAN_VID_MASK );if (skb->dev ==NULL ) {dev_kfree_skb_any (skb);
@@ -22,6 +25,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp,return NET_RX_SUCCESS ; } skb->dev->last_rx = jiffies; + skb->vlan_tci =0 ; stats = &skb->dev->stats; stats->rx_packets++;
net/core/dev.c +27 -0
@@ -2068,6 +2068,33 @@ out: }#endif +/* +* netif_nit_deliver - deliver received packets to network taps +* @skb: buffer +* +* This function is used to deliver incoming packets to network +* taps. It should be used when the normal netif_receive_skb path +* is bypassed, for example because of VLAN acceleration. +*/ +void netif_nit_deliver (struct sk_buff *skb) +{ +struct packet_type *ptype; + +if (list_empty (&ptype_all)) +return ; + +skb_reset_network_header (skb); +skb_reset_transport_header (skb); + skb->mac_len = skb->network_header - skb->mac_header; + +rcu_read_lock (); +list_for_each_entry_rcu (ptype, &ptype_all, list) { +if (!ptype->dev || ptype->dev == skb->dev) +deliver_skb (skb, ptype, skb->dev); + } +rcu_read_unlock (); +} +/** * netif_receive_skb - process receive buffer from network * @skb: buffer to process
PATCH 3/8 : packet: support extensible, 64 bit clean mmaped ring structure
In reply to Patrick McHardypacket: support extensible, 64 bit clean mmaped ring structure
The tpacket_hdr is not 64 bit clean due to use of an unsigned long and can't be extended because the following struct sockaddr_ll needs to be at a fixed offset.
Add support for a version 2 tpacket protocol that removes these limitations.
Userspace can query the header size through a new getsockopt option and change the protocol version through a setsockopt option. The changes needed to switch to the new protocol version are:
1. replace struct tpacket_hdr by struct tpacket2_hdr
2. query header len and save
3. set protocol version to 2
- set up ring as usual
4. for getting the sockaddr_ll, use (void *)hdr + TPACKET_ALIGN(hdrlen) instead of (void *)hdr + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
Steps 2 and 4 can be omitted if the struct sockaddr_ll isn't needed.
---
commit 67facd0da49b1c2061e17a6623904f675d0b1bc9
tree 3c3f7e5bcd481da693fbdda775c618abf9f89584
parent 2150bca3247c0b497a83937005367092bca86530
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:04:26 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:04:26 +0200
include/linux/if_packet.h | 21 +++++ net/packet/af_packet.c | 179 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 167 insertions(+), 33 deletions(-)
include/linux/if_packet.h +21 -0
@@ -43,6 +43,8 @@ struct sockaddr_ll#define PACKET_COPY_THRESH 7#define PACKET_AUXDATA 8#define PACKET_ORIGDEV 9 +#define PACKET_VERSION 10 +#define PACKET_HDRLEN 11struct tpacket_stats {
@@ -79,6 +81,25 @@ struct tpacket_hdr#define TPACKET_ALIGN (x) (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))#define TPACKET_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket_hdr)) + sizeof(struct sockaddr_ll)) +struct tpacket2_hdr +{ +__u32 tp_status; +__u32 tp_len; +__u32 tp_snaplen; +__u16 tp_mac; +__u16 tp_net; +__u32 tp_sec; +__u32 tp_nsec; +}; + +#define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) + +enum tpacket_versions +{ +TPACKET_V1 , +TPACKET_V2 , +}; +/* Frame structure:
net/packet/af_packet.c +146 -33
280 lines not on this page · raw message
PATCH 4/8 : packet: deliver VLAN TCI to userspace
In reply to Patrick McHardypacket: deliver VLAN TCI to userspace
Store the VLAN tag in the auxillary data/tpacket2_hdr so userspace can properly deal with hardware VLAN tagging/stripping.
---
commit 1e655d00db6762d05f8d99912a70f58fe4c4f977
tree 605cd8de3e2752890703706e7dd9acaaadcf5324
parent 67facd0da49b1c2061e17a6623904f675d0b1bc9
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:56:52 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:56:52 +0200
include/linux/if_packet.h | 2 ++ net/packet/af_packet.c | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-)
include/linux/if_packet.h +2 -0
@@ -59,6 +59,7 @@ struct tpacket_auxdata__u32 tp_snaplen;__u16 tp_mac;__u16 tp_net; +__u16 tp_vlan_tci; };struct tpacket_hdr
@@ -90,6 +91,7 @@ struct tpacket2_hdr__u16 tp_net;__u32 tp_sec;__u32 tp_nsec; +__u16 tp_vlan_tci; };#define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
net/packet/af_packet.c +2 -0
@@ -702,6 +702,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packegetnstimeofday (&ts); h.h2->tp_sec = ts.tv_sec; h.h2->tp_nsec = ts.tv_nsec; + h.h2->tp_vlan_tci = skb->vlan_tci; hdrlen =sizeof (*h.h2);break ;default :
@@ -1172,6 +1173,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, aux.tp_snaplen = skb->len; aux.tp_mac =0 ; aux.tp_net =skb_network_offset (skb); + aux.tp_vlan_tci = skb->vlan_tci;put_cmsg (msg,SOL_PACKET ,PACKET_AUXDATA ,sizeof (aux), &aux); }
PATCH 5/8 : vlan: ethtool ->get_flags support
In reply to Patrick McHardyvlan: ethtool ->get_flags support
Allow to query LRO settings of underlying device when VLAN RX acceleration is used.
Suggested by Ben Hutchings <[email protected]>.
---
commit b7ed86e1c799275adf2d36b8801abe91ffe66aec
tree 7374b192f8b6b88df2e2a9f6d92764423a14df9f
parent 1e655d00db6762d05f8d99912a70f58fe4c4f977
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:00 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:00 +0200
net/8021q/vlan_dev.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
net/8021q/vlan_dev.c +13 -0
@@ -709,9 +709,22 @@ static u32 vlan_ethtool_get_rx_csum(struct net_device *dev)return real_dev->ethtool_ops->get_rx_csum (real_dev); } +static u32 vlan_ethtool_get_flags (struct net_device *dev) +{ +const struct vlan_dev_info *vlan =vlan_dev_info (dev); +struct net_device *real_dev = vlan->real_dev; + +if (!(real_dev->features &NETIF_F_HW_VLAN_RX ) || + real_dev->ethtool_ops ==NULL || + real_dev->ethtool_ops->get_flags ==NULL ) +return 0 ; +return real_dev->ethtool_ops->get_flags (real_dev); +} +static const struct ethtool_ops vlan_ethtool_ops = { .get_link = ethtool_op_get_link, .get_rx_csum = vlan_ethtool_get_rx_csum, + .get_flags = vlan_ethtool_get_flags, };void vlan_setup (struct net_device *dev)
PATCH 6/8 : vlan: clean up vlan_dev_hard_header()
In reply to Patrick McHardyvlan: clean up vlan_dev_hard_header()
Remove some debugging and excessive comments, merge the two dev_hard_header calls into one.
---
commit 731075279c2229b454f9441da2b6bc82a39cde67
tree 4c7354bbc74d1d75da1a8fbc79fd6d19e7ec5021
parent b7ed86e1c799275adf2d36b8801abe91ffe66aec
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:00 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:00 +0200
net/8021q/vlan_dev.c | 55 ++++++++------------------------------------------ 1 files changed, 9 insertions(+), 46 deletions(-)
net/8021q/vlan_dev.c +9 -46
@@ -256,43 +256,18 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, unsigned int len) {struct vlan_hdr *vhdr; +unsigned int vhdrlen =0 ;u16 vlan_tci =0 ; -int rc =0 ; -int build_vlan_header =0 ; - -pr_debug ("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n" , - __func__, skb, type, len,vlan_dev_info (dev)->vlan_id, - daddr); +int rc;if (WARN_ON (skb_headroom (skb) < dev->hard_header_len))return -ENOSPC ; -/* build vlan header only if re_order_header flag is NOT set. This -* fixes some programs that get confused when they see a VLAN device -* sending a frame that is VLAN encoded (the consensus is that the VLAN -* device should look completely like an Ethernet device when the -* REORDER_HEADER flag is set) The drawback to this is some extra -* header shuffling in the hard_start_xmit. Users can turn off this -* REORDER behaviour with the vconfig tool. -*/ -if (!(vlan_dev_info (dev)->flags &VLAN_FLAG_REORDER_HDR )) - build_vlan_header =1 ; - -if (build_vlan_header) { +if (!(vlan_dev_info (dev)->flags &VLAN_FLAG_REORDER_HDR )) { vhdr = (struct vlan_hdr *)skb_push (skb,VLAN_HLEN ); -/* build the four bytes that make this a VLAN header. */ - -/* Now, construct the second two bytes. This field looks -* something like: -* usr_priority: 3 bits (high bits) -* CFI 1 bit -* VLAN ID 12 bits (low bits) -* -*/ vlan_tci =vlan_dev_info (dev)->vlan_id; vlan_tci |=vlan_dev_get_egress_qos_mask (dev, skb); - vhdr->h_vlan_TCI =htons (vlan_tci);/*
@@ -300,37 +275,25 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,* put the length in here instead. It is up to the 802.2 * layer to carry protocol information. */ -if (type !=ETH_P_802_3 ) vhdr->h_vlan_encapsulated_proto =htons (type);else vhdr->h_vlan_encapsulated_proto =htons (len); skb->protocol =htons (ETH_P_8021Q ); + type =ETH_P_8021Q ; + vhdrlen =VLAN_HLEN ; }/* Before delegating work to the lower layer, enter our MAC-address */ if (saddr ==NULL ) saddr = dev->dev_addr; +/* Now make the underlying real hard header */ dev =vlan_dev_info (dev)->real_dev; - -if (build_vlan_header) { -/* Now make the underlying real hard header */ - rc =dev_hard_header (skb, dev,ETH_P_8021Q , daddr, saddr, - len +VLAN_HLEN ); -if (rc >0 ) - rc +=VLAN_HLEN ; -else if (rc <0 ) - rc -=VLAN_HLEN ; - }else -/* If here, then we'll just make a normal looking ethernet -* frame, but, the hard_start_xmit method will insert the tag -* (it has to be able to do this for bridged and other skbs -* that don't come down the protocol stack in an orderly manner. -*/ - rc =dev_hard_header (skb, dev, type, daddr, saddr, len); - + rc =dev_hard_header (skb, dev, type, daddr, saddr, len + vhdrlen); +if (rc >0 ) + rc += vhdrlen;return rc; }
PATCH 7/8 : vlan: clean up hard_start_xmit functions
In reply to Patrick McHardyvlan: clean up hard_start_xmit functions
Remove excessive comments and debugging, use NETDEV_TX codes, remove some empty lines.
---
commit a1f83d7cbe06c3c104cfa7cf298fb0ccb26cb5a8
tree e5d55d0d2cc56417cc00788215050ae4f371cfe8
parent 731075279c2229b454f9441da2b6bc82a39cde67
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:01 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:01 +0200
net/8021q/vlan_dev.c | 41 ++++++----------------------------------- 1 files changed, 6 insertions(+), 35 deletions(-)
net/8021q/vlan_dev.c +6 -35
@@ -307,53 +307,31 @@ static int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)* NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ -if (veth->h_vlan_proto !=htons (ETH_P_8021Q ) || -vlan_dev_info (dev)->flags &VLAN_FLAG_REORDER_HDR ) { -int orig_headroom =skb_headroom (skb); +vlan_dev_info (dev)->flags &VLAN_FLAG_REORDER_HDR ) { +unsigned int orig_headroom =skb_headroom (skb);u16 vlan_tci; -/* This is not a VLAN frame...but we can fix that! */ vlan_dev_info (dev)->cnt_encap_on_xmit++; -pr_debug ("%s: proto to encap: 0x%hx\n" , - __func__,ntohs (veth->h_vlan_proto)); -/* Construct the second two bytes. This field looks something -* like: -* usr_priority: 3 bits (high bits) -* CFI 1 bit -* VLAN ID 12 bits (low bits) -*/ vlan_tci =vlan_dev_info (dev)->vlan_id; vlan_tci |=vlan_dev_get_egress_qos_mask (dev, skb); - skb =__vlan_put_tag (skb, vlan_tci);if (!skb) { stats->tx_dropped++; -return 0 ; +return NETDEV_TX_OK ; }if (orig_headroom <VLAN_HLEN )vlan_dev_info (dev)->cnt_inc_headroom_on_tx++; } -pr_debug ("%s: about to send skb: %p to dev: %s\n" , - __func__, skb, skb->dev->name); -pr_debug (" " MAC_FMT " " MAC_FMT " %4hx %4hx %4hx\n" , - veth->h_dest[0 ], veth->h_dest[1 ], veth->h_dest[2 ], - veth->h_dest[3 ], veth->h_dest[4 ], veth->h_dest[5 ], - veth->h_source[0 ], veth->h_source[1 ], veth->h_source[2 ], - veth->h_source[3 ], veth->h_source[4 ], veth->h_source[5 ], - veth->h_vlan_proto, veth->h_vlan_TCI, - veth->h_vlan_encapsulated_proto); - - stats->tx_packets++;/* for statics only */ + stats->tx_packets++; stats->tx_bytes += skb->len; skb->dev =vlan_dev_info (dev)->real_dev;dev_queue_xmit (skb); - -return 0 ; +return NETDEV_TX_OK ; } static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,
@@ -362,12 +340,6 @@ static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,struct net_device_stats *stats = &dev->stats;u16 vlan_tci; -/* Construct the second two bytes. This field looks something -* like: -* usr_priority: 3 bits (high bits) -* CFI 1 bit -* VLAN ID 12 bits (low bits) -*/ vlan_tci =vlan_dev_info (dev)->vlan_id; vlan_tci |=vlan_dev_get_egress_qos_mask (dev, skb); skb =__vlan_hwaccel_put_tag (skb, vlan_tci);
@@ -377,8 +349,7 @@ static int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, skb->dev =vlan_dev_info (dev)->real_dev;dev_queue_xmit (skb); - -return 0 ; +return NETDEV_TX_OK ; }static int vlan_dev_change_mtu (struct net_device *dev,int new_mtu)
PATCH 8/8 : vlan: remove unnecessary include statements
In reply to Patrick McHardyvlan: remove unnecessary include statements
---
commit 0b1a2cdc7acdd1fed69d6eefb16744f205fcd418
tree 3267d6c92125ad3918072c1ba180ed47c36b23f0
parent a1f83d7cbe06c3c104cfa7cf298fb0ccb26cb5a8
author Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:01 +0200 committer Patrick McHardy <[email protected]> Wed, 09 Jul 2008 13:57:01 +0200
net/8021q/vlan.c | 8 ++------ net/8021q/vlan_dev.c | 7 ------- net/8021q/vlanproc.c | 11 ++--------- 3 files changed, 4 insertions(+), 22 deletions(-)
net/8021q/vlan.c +2 -6
@@ -18,21 +18,17 @@* 2 of the License, or (at your option) any later version. */ -#include <asm/uaccess.h> /* for copy_from_user */ #include <linux/capability.h> #include <linux/module.h> #include <linux/netdevice.h> #include <linux/skbuff.h> -#include <net/datalink.h> -#include <linux/mm.h> -#include <linux/in.h> #include <linux/init.h> -#include <net/p8022.h> -#include <net/arp.h> #include <linux/rtnetlink.h> #include <linux/notifier.h> +#include <net/rtnetlink.h> #include <net/net_namespace.h> #include <net/netns/generic.h> +#include <asm/uaccess.h> #include <linux/if_vlan.h> #include "vlan.h"
net/8021q/vlan_dev.c +0 -7
@@ -21,22 +21,15 @@*/ #include <linux/module.h> -#include <linux/mm.h> -#include <linux/in.h> -#include <linux/init.h> -#include <asm/uaccess.h> /* for copy_from_user */ #include <linux/skbuff.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> -#include <net/datalink.h> -#include <net/p8022.h> #include <net/arp.h> #include "vlan.h" #include "vlanproc.h" #include <linux/if_vlan.h> -#include <net/ip.h> /* * Rebuild the Ethernet MAC header. This is called after an ARP
net/8021q/vlanproc.c +2 -9
@@ -18,16 +18,9 @@*****************************************************************************/ #include <linux/module.h> -#include <linux/stddef.h> /* offsetof(), etc. */ -#include <linux/errno.h> /* return codes */ +#include <linux/errno.h> #include <linux/kernel.h> -#include <linux/slab.h> /* kmalloc(), kfree() */ -#include <linux/mm.h> -#include <linux/string.h> /* inline mem*, str* functions */ -#include <linux/init.h> /* __initfunc et al. */ -#include <asm/byteorder.h> /* htons(), etc. */ -#include <asm/uaccess.h> /* copy_to_user */ -#include <asm/io.h> +#include <linux/string.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/fs.h>
Quoted 4 lines · Patrick McHardy
These patches include an updated set of the VLAN packet socket fixes, now also supporting VLAN TCI delivery to userspace using mmaped packet sockets, as well as a patch to add ->get_flags ethtool support and a few minor cleanup patches.
And for reference, attached is a patch for libpcap to reconstruct the VLAN header from the auxdata, as well as a ugly small program for testing the new mmaped packet socket protocol version (since I couldn't find a version of libpcap that already supports this for some reason).
pcap-linux.c +60 -6
@@ -471,7 +471,13 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)socklen_t fromlen;int packet_len, caplen;struct pcap_pkthdr pcap_header; - +struct iovec iov; +struct msghdr msg; +struct cmsghdr *cmsg; +union { +struct cmsghdr cmsg; +char buf[CMSG_SPACE (sizeof (struct tpacket_auxdata ))]; + } cmsg_buf;#ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, leave extra room for a
@@ -492,6 +498,15 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)/* Receive a single packet from the kernel */ bp = handle->buffer + handle->offset; + + msg.msg_name = &from; + msg.msg_namelen =sizeof (from); + msg.msg_iov = &iov; + msg.msg_iovlen =1 ; + msg.msg_control = &cmsg_buf; + msg.msg_controllen =sizeof (cmsg_buf); + msg.msg_flags =0 ; + do { /* * Has "pcap_breakloop()" been called?
@@ -505,11 +520,11 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) handle->break_loop =0 ;return -2 ; } - fromlen =sizeof (from); - packet_len =recvfrom ( - handle->fd, bp + offset, - handle->bufsize - offset,MSG_TRUNC , - (struct sockaddr *) &from, &fromlen); + + iov.iov_len = handle->bufsize - offset; + iov.iov_base = bp + offset; + + packet_len =recvmsg (handle->fd, &msg,MSG_TRUNC ); }while (packet_len ==-1 && errno ==EINTR );/* Check if an error occured */
@@ -524,6 +539,38 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) } } +for (cmsg =CMSG_FIRSTHDR (&msg); cmsg; cmsg =CMSG_NXTHDR (&msg, cmsg)) { +struct tpacket_auxdata *aux; +unsigned int len, copy; +unsigned short *ptr; + +if (cmsg->cmsg_len <CMSG_LEN (sizeof (struct tpacket_auxdata )) || + cmsg->cmsg_level !=SOL_PACKET || + cmsg->cmsg_type !=PACKET_AUXDATA ) +continue ; + + aux = (struct tpacket_auxdata *)CMSG_DATA (cmsg); +if (aux->tp_vlan_tci ==0 ) +continue ; + + len = packet_len > iov.iov_len ? iov.iov_len : packet_len; +if (len >2 *ETH_ALEN +4 ) { + copy = len -2 *ETH_ALEN -4 ; +if (copy > iov.iov_len -2 *ETH_ALEN -4 ) + copy = iov.iov_len -2 *ETH_ALEN -4 ; + +memmove (iov.iov_base +2 *ETH_ALEN +4 , + iov.iov_base +2 *ETH_ALEN , copy); + } + + ptr = (unsigned short *)(iov.iov_base +2 *ETH_ALEN ); +if (len >=2 *ETH_ALEN +2 ) + *(ptr++) =htons (ETH_P_8021Q ); +if (len >=2 *ETH_ALEN +4 ) + *(ptr++) =htons (aux->tp_vlan_tci); + packet_len +=4 ; + } +#ifdef HAVE_PF_PACKET_SOCKETS if (!handle->md.sock_packet) {/*
@@ -1631,6 +1678,7 @@ iface_bind(int fd, int ifindex, char *ebuf)struct sockaddr_ll sll;int err;socklen_t errlen =sizeof (err); +int val;memset (&sll,0 ,sizeof (sll)); sll.sll_family =AF_PACKET ;
@@ -1657,6 +1705,12 @@ iface_bind(int fd, int ifindex, char *ebuf)return -2 ; } + val =1 ; +if (setsockopt (fd,SOL_PACKET ,PACKET_AUXDATA , &val,sizeof (val)) ==-1 ) { +snprintf (ebuf,PCAP_ERRBUF_SIZE , +"setsockopt: %s" ,pcap_strerror (errno)); +return -3 ; + }return 0 ; }
if_packet.h renamed from tmp/null/if_packet.h +144 -0
144 lines not on this page · raw message
Makefile renamed from tmp/null/Makefile +3 -0
@@ -0,0 +1,3 @@ +CFLAGS += -O2 -I. -Wall -g + +all: test
test.c renamed from tmp/null/test.c +150 -0
150 lines not on this page · raw message
David Miller
maintainerFrom: Patrick McHardy <[email protected]>
Date: Wed, 9 Jul 2008 14:09:45 +0200 (MEST)
Quoted 4 lines
These patches include an updated set of the VLAN packet socket fixes, now also supporting VLAN TCI delivery to userspace using mmaped packet sockets, as well as a patch to add ->get_flags ethtool support and a few minor cleanup patches.
Applied and pushed out to net-next-2.6, thanks Patrick.