Skip to content

Commit 05423b2

Browse files
Eric Dumazetdavem330
authored andcommitted
vlan: allow null VLAN ID to be used
We currently use a 16 bit field (vlan_tci) to store VLAN ID/PRIO on a skb. Null value is used as a special value, meaning vlan tagging not enabled. This forbids use of null vlan ID. As pointed by David, some drivers use the 3 high order bits (PRIO) As VLAN ID is 12 bits, we can use the remaining bit (CFI) as a flag, and allow null VLAN ID. In case future code really wants to use VLAN_CFI_MASK, we'll have to use a bit outside of vlan_tci. #define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */ #define VLAN_PRIO_SHIFT 13 #define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */ #define VLAN_TAG_PRESENT VLAN_CFI_MASK #define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ Reported-by: Gertjan Hofman <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9dbb58d commit 05423b2

File tree

5 files changed

+15
-10
lines changed

5 files changed

+15
-10
lines changed

include/linux/if_vlan.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
6363
return (struct vlan_ethhdr *)skb_mac_header(skb);
6464
}
6565

66-
#define VLAN_VID_MASK 0xfff
66+
#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
67+
#define VLAN_PRIO_SHIFT 13
68+
#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */
69+
#define VLAN_TAG_PRESENT VLAN_CFI_MASK
70+
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
6771

6872
/* found in socket.c */
6973
extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
@@ -105,8 +109,8 @@ static inline void vlan_group_set_device(struct vlan_group *vg,
105109
array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev;
106110
}
107111

108-
#define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci)
109-
#define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci)
112+
#define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT)
113+
#define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT)
110114

111115
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
112116
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
@@ -231,7 +235,7 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci)
231235
static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb,
232236
u16 vlan_tci)
233237
{
234-
skb->vlan_tci = vlan_tci;
238+
skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
235239
return skb;
236240
}
237241

@@ -284,7 +288,7 @@ static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
284288
u16 *vlan_tci)
285289
{
286290
if (vlan_tx_tag_present(skb)) {
287-
*vlan_tci = skb->vlan_tci;
291+
*vlan_tci = vlan_tx_tag_get(skb);
288292
return 0;
289293
} else {
290294
*vlan_tci = 0;

net/8021q/vlan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static inline u32 vlan_get_ingress_priority(struct net_device *dev,
8989
{
9090
struct vlan_dev_info *vip = vlan_dev_info(dev);
9191

92-
return vip->ingress_priority_map[(vlan_tci >> 13) & 0x7];
92+
return vip->ingress_priority_map[(vlan_tci >> VLAN_PRIO_SHIFT) & 0x7];
9393
}
9494

9595
#ifdef CONFIG_VLAN_8021Q_GVRP

net/8021q/vlan_dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ int vlan_dev_set_egress_priority(const struct net_device *dev,
393393
struct vlan_dev_info *vlan = vlan_dev_info(dev);
394394
struct vlan_priority_tci_mapping *mp = NULL;
395395
struct vlan_priority_tci_mapping *np;
396-
u32 vlan_qos = (vlan_prio << 13) & 0xE000;
396+
u32 vlan_qos = (vlan_prio << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK;
397397

398398
/* See if a priority mapping exists.. */
399399
mp = vlan->egress_priority_map[skb_prio & 0xF];

net/core/dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2300,7 +2300,7 @@ int netif_receive_skb(struct sk_buff *skb)
23002300
if (!skb->tstamp.tv64)
23012301
net_timestamp(skb);
23022302

2303-
if (skb->vlan_tci && vlan_hwaccel_do_receive(skb))
2303+
if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
23042304
return NET_RX_SUCCESS;
23052305

23062306
/* if we've gotten here through NAPI, check netpoll */

net/packet/af_packet.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include <linux/module.h>
8080
#include <linux/init.h>
8181
#include <linux/mutex.h>
82+
#include <linux/if_vlan.h>
8283

8384
#ifdef CONFIG_INET
8485
#include <net/inet_common.h>
@@ -766,7 +767,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
766767
getnstimeofday(&ts);
767768
h.h2->tp_sec = ts.tv_sec;
768769
h.h2->tp_nsec = ts.tv_nsec;
769-
h.h2->tp_vlan_tci = skb->vlan_tci;
770+
h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
770771
hdrlen = sizeof(*h.h2);
771772
break;
772773
default:
@@ -1493,7 +1494,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
14931494
aux.tp_snaplen = skb->len;
14941495
aux.tp_mac = 0;
14951496
aux.tp_net = skb_network_offset(skb);
1496-
aux.tp_vlan_tci = skb->vlan_tci;
1497+
aux.tp_vlan_tci = vlan_tx_tag_get(skb);
14971498

14981499
put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
14991500
}

0 commit comments

Comments
 (0)