aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2013-04-18 22:04:31 -0400
committerDavid S. Miller <davem@davemloft.net>2013-04-19 14:46:06 -0400
commit8ad227ff89a7e6f05d07cd0acfd95ed3a24450ca (patch)
tree90cb532df2523a011e47844434cc423664441d71 /net/core
parent86a9bad3ab6b6f858fd4443b48738cabbb6d094c (diff)
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/core')
-rw-r--r--net/core/dev.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 3a12ee132b59..fad4c385f7a1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2212,7 +2212,7 @@ __be16 skb_network_protocol(struct sk_buff *skb)
2212 __be16 type = skb->protocol; 2212 __be16 type = skb->protocol;
2213 int vlan_depth = ETH_HLEN; 2213 int vlan_depth = ETH_HLEN;
2214 2214
2215 while (type == htons(ETH_P_8021Q)) { 2215 while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
2216 struct vlan_hdr *vh; 2216 struct vlan_hdr *vh;
2217 2217
2218 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) 2218 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
@@ -2428,20 +2428,22 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
2428 if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) 2428 if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
2429 features &= ~NETIF_F_GSO_MASK; 2429 features &= ~NETIF_F_GSO_MASK;
2430 2430
2431 if (protocol == htons(ETH_P_8021Q)) { 2431 if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) {
2432 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 2432 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
2433 protocol = veh->h_vlan_encapsulated_proto; 2433 protocol = veh->h_vlan_encapsulated_proto;
2434 } else if (!vlan_tx_tag_present(skb)) { 2434 } else if (!vlan_tx_tag_present(skb)) {
2435 return harmonize_features(skb, protocol, features); 2435 return harmonize_features(skb, protocol, features);
2436 } 2436 }
2437 2437
2438 features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX); 2438 features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
2439 NETIF_F_HW_VLAN_STAG_TX);
2439 2440
2440 if (protocol != htons(ETH_P_8021Q)) { 2441 if (protocol != htons(ETH_P_8021Q) && protocol != htons(ETH_P_8021AD)) {
2441 return harmonize_features(skb, protocol, features); 2442 return harmonize_features(skb, protocol, features);
2442 } else { 2443 } else {
2443 features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | 2444 features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
2444 NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX; 2445 NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
2446 NETIF_F_HW_VLAN_STAG_TX;
2445 return harmonize_features(skb, protocol, features); 2447 return harmonize_features(skb, protocol, features);
2446 } 2448 }
2447} 2449}
@@ -3360,6 +3362,7 @@ static bool skb_pfmemalloc_protocol(struct sk_buff *skb)
3360 case __constant_htons(ETH_P_IP): 3362 case __constant_htons(ETH_P_IP):
3361 case __constant_htons(ETH_P_IPV6): 3363 case __constant_htons(ETH_P_IPV6):
3362 case __constant_htons(ETH_P_8021Q): 3364 case __constant_htons(ETH_P_8021Q):
3365 case __constant_htons(ETH_P_8021AD):
3363 return true; 3366 return true;
3364 default: 3367 default:
3365 return false; 3368 return false;
@@ -3400,7 +3403,8 @@ another_round:
3400 3403
3401 __this_cpu_inc(softnet_data.processed); 3404 __this_cpu_inc(softnet_data.processed);
3402 3405
3403 if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { 3406 if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
3407 skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
3404 skb = vlan_untag(skb); 3408 skb = vlan_untag(skb);
3405 if (unlikely(!skb)) 3409 if (unlikely(!skb))
3406 goto unlock; 3410 goto unlock;