From: Thomas Graf Date: Wed, 7 Jan 2015 11:55:49 +0000 (+0100) Subject: datapath: Add __vlan_insert_tag() compat helper if not available X-Git-Tag: v2.4.0~728 X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=17e3889fd18078784ad8e49c12ba2806b49c5b53 datapath: Add __vlan_insert_tag() compat helper if not available Since older kernels do not have skb->vlan_proto, it is assumed that kernels which don't provide their own __vlan_insert_tag() will also not have skb->vlan_proto. The backwards compat function therefore only supports ETH_P_8021Q as the protocol type. Upstream: 15255a43 ("vlan: introduce __vlan_insert_tag helper which does not free skb") Signed-off-by: Thomas Graf Acked-by: Pravin B Shelar --- diff --git a/acinclude.m4 b/acinclude.m4 index 05dc1125b..444141d7f 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -377,6 +377,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [ADD_ALL_VLANS_CMD], [OVS_DEFINE([HAVE_VLAN_BUG_WORKAROUND])]) OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [vlan_insert_tag_set_proto]) + OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [__vlan_insert_tag]) + OVS_GREP_IFELSE([$KSRC/include/linux/u64_stats_sync.h], [u64_stats_fetch_begin_irq]) diff --git a/datapath/linux/compat/include/linux/if_vlan.h b/datapath/linux/compat/include/linux/if_vlan.h index 616b3bf8a..28c4daeba 100644 --- a/datapath/linux/compat/include/linux/if_vlan.h +++ b/datapath/linux/compat/include/linux/if_vlan.h @@ -106,4 +106,33 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vh skb->protocol = htons(ETH_P_802_2); } #endif + +#ifndef HAVE___VLAN_INSERT_TAG +/* Kernels which don't have __vlan_insert_tag() also don't have skb->vlan_proto + * so ignore the proto paramter. + */ +#define __vlan_insert_tag(skb, proto, tci) rpl_vlan_insert_tag(skb, tci) +static inline int rpl_vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci) +{ + struct vlan_ethhdr *veth; + + if (skb_cow_head(skb, VLAN_HLEN) < 0) + return -ENOMEM; + + veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); + + /* Move the mac addresses to the beginning of the new header. */ + memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); + skb->mac_header -= VLAN_HLEN; + + /* first, the ethernet type */ + veth->h_vlan_proto = htons(ETH_P_8021Q); + + /* now, the TCI */ + veth->h_vlan_TCI = htons(ETH_P_8021Q); + + return 0; +} +#endif + #endif /* linux/if_vlan.h wrapper */