diff options
author | Patrick McHardy <kaber@trash.net> | 2013-04-19 02:04:31 (GMT) |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-19 18:46:06 (GMT) |
commit | 8ad227ff89a7e6f05d07cd0acfd95ed3a24450ca (patch) | |
tree | 90cb532df2523a011e47844434cc423664441d71 /net/8021q/vlan_core.c | |
parent | 86a9bad3ab6b6f858fd4443b48738cabbb6d094c (diff) | |
download | linux-fsl-qoriq-8ad227ff89a7e6f05d07cd0acfd95ed3a24450ca.tar.xz |
net: vlan: add 802.1ad support
Add support for 802.1ad VLAN devices. This mainly consists of checking for
ETH_P_8021AD in addition to ETH_P_8021Q in a couple of places and check
offloading capabilities based on the used protocol.
Configuration is done using "ip link":
# ip link add link eth0 eth0.1000 \
type vlan proto 802.1ad id 1000
# ip link add link eth0.1000 eth0.1000.1000 \
type vlan proto 802.1q id 1000
52:54:00:12:34:56 > 92:b1:54:28:e4:8c, ethertype 802.1Q (0x8100), length 106: vlan 1000, p 0, ethertype 802.1Q, vlan 1000, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84)
20.1.0.2 > 20.1.0.1: ICMP echo request, id 3003, seq 8, length 64
92:b1:54:28:e4:8c > 52:54:00:12:34:56, ethertype 802.1Q-QinQ (0x88a8), length 106: vlan 1000, p 0, ethertype 802.1Q, vlan 1000, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 47944, offset 0, flags [none], proto ICMP (1), length 84)
20.1.0.1 > 20.1.0.2: ICMP echo reply, id 3003, seq 8, length 64
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/8021q/vlan_core.c')
-rw-r--r-- | net/8021q/vlan_core.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index bdb0b9d..ebfa2fc 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -194,6 +194,18 @@ struct vlan_vid_info { int refcount; }; +static bool vlan_hw_filter_capable(const struct net_device *dev, + const struct vlan_vid_info *vid_info) +{ + if (vid_info->proto == htons(ETH_P_8021Q) && + dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) + return true; + if (vid_info->proto == htons(ETH_P_8021AD) && + dev->features & NETIF_F_HW_VLAN_STAG_FILTER) + return true; + return false; +} + static struct vlan_vid_info *vlan_vid_info_get(struct vlan_info *vlan_info, __be16 proto, u16 vid) { @@ -231,8 +243,7 @@ static int __vlan_vid_add(struct vlan_info *vlan_info, __be16 proto, u16 vid, if (!vid_info) return -ENOMEM; - if (proto == htons(ETH_P_8021Q) && - dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (vlan_hw_filter_capable(dev, vid_info)) { err = ops->ndo_vlan_rx_add_vid(dev, proto, vid); if (err) { kfree(vid_info); @@ -290,8 +301,7 @@ static void __vlan_vid_del(struct vlan_info *vlan_info, u16 vid = vid_info->vid; int err; - if (proto == htons(ETH_P_8021Q) && - dev->features & NETIF_F_HW_VLAN_CTAG_FILTER) { + if (vlan_hw_filter_capable(dev, vid_info)) { err = ops->ndo_vlan_rx_kill_vid(dev, proto, vid); if (err) { pr_warn("failed to kill vid %04x/%d for device %s\n", |