Commit fe19c4f9 authored by Eric Garver's avatar Eric Garver Committed by David S. Miller

vlan: Check for vlan ethernet types for 8021.q or 802.1ad

This is to simplify using double tagged vlans. This function allows all
valid vlan ethertypes to be checked in a single function call.
Also replace some instances that check for both ETH_P_8021Q and
ETH_P_8021AD.

Patch based on one originally by Thomas F Herbert.
Signed-off-by: default avatarThomas F Herbert <thomasfherbert@gmail.com>
Signed-off-by: default avatarEric Garver <e@erig.me>
Acked-by: default avatarPravin B Shelar <pshelar@ovn.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8c146bb9
...@@ -272,6 +272,23 @@ static inline int vlan_get_encap_level(struct net_device *dev) ...@@ -272,6 +272,23 @@ static inline int vlan_get_encap_level(struct net_device *dev)
} }
#endif #endif
/**
* eth_type_vlan - check for valid vlan ether type.
* @ethertype: ether type to check
*
* Returns true if the ether type is a vlan ether type.
*/
static inline bool eth_type_vlan(__be16 ethertype)
{
switch (ethertype) {
case htons(ETH_P_8021Q):
case htons(ETH_P_8021AD):
return true;
default:
return false;
}
}
static inline bool vlan_hw_offload_capable(netdev_features_t features, static inline bool vlan_hw_offload_capable(netdev_features_t features,
__be16 proto) __be16 proto)
{ {
...@@ -425,8 +442,7 @@ static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) ...@@ -425,8 +442,7 @@ static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
{ {
struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data; struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
if (veth->h_vlan_proto != htons(ETH_P_8021Q) && if (!eth_type_vlan(veth->h_vlan_proto))
veth->h_vlan_proto != htons(ETH_P_8021AD))
return -EINVAL; return -EINVAL;
*vlan_tci = ntohs(veth->h_vlan_TCI); *vlan_tci = ntohs(veth->h_vlan_TCI);
...@@ -488,7 +504,7 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type, ...@@ -488,7 +504,7 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
* present at mac_len - VLAN_HLEN (if mac_len > 0), or at * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
* ETH_HLEN otherwise * ETH_HLEN otherwise
*/ */
if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { if (eth_type_vlan(type)) {
if (vlan_depth) { if (vlan_depth) {
if (WARN_ON(vlan_depth < VLAN_HLEN)) if (WARN_ON(vlan_depth < VLAN_HLEN))
return 0; return 0;
...@@ -506,8 +522,7 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type, ...@@ -506,8 +522,7 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type,
vh = (struct vlan_hdr *)(skb->data + vlan_depth); vh = (struct vlan_hdr *)(skb->data + vlan_depth);
type = vh->h_vlan_encapsulated_proto; type = vh->h_vlan_encapsulated_proto;
vlan_depth += VLAN_HLEN; vlan_depth += VLAN_HLEN;
} while (type == htons(ETH_P_8021Q) || } while (eth_type_vlan(type));
type == htons(ETH_P_8021AD));
} }
if (depth) if (depth)
...@@ -572,8 +587,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, ...@@ -572,8 +587,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
static inline bool skb_vlan_tagged(const struct sk_buff *skb) static inline bool skb_vlan_tagged(const struct sk_buff *skb)
{ {
if (!skb_vlan_tag_present(skb) && if (!skb_vlan_tag_present(skb) &&
likely(skb->protocol != htons(ETH_P_8021Q) && likely(!eth_type_vlan(skb->protocol)))
skb->protocol != htons(ETH_P_8021AD)))
return false; return false;
return true; return true;
...@@ -593,15 +607,14 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb) ...@@ -593,15 +607,14 @@ static inline bool skb_vlan_tagged_multi(const struct sk_buff *skb)
if (!skb_vlan_tag_present(skb)) { if (!skb_vlan_tag_present(skb)) {
struct vlan_ethhdr *veh; struct vlan_ethhdr *veh;
if (likely(protocol != htons(ETH_P_8021Q) && if (likely(!eth_type_vlan(protocol)))
protocol != htons(ETH_P_8021AD)))
return false; return false;
veh = (struct vlan_ethhdr *)skb->data; veh = (struct vlan_ethhdr *)skb->data;
protocol = veh->h_vlan_encapsulated_proto; protocol = veh->h_vlan_encapsulated_proto;
} }
if (protocol != htons(ETH_P_8021Q) && protocol != htons(ETH_P_8021AD)) if (!eth_type_vlan(protocol))
return false; return false;
return true; return true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment