OVS correctly define skb_gso_segment() to handle MPLS and VLAN segmentation correctly. But OVS also uses __skb_gso_segment() in some cases. Following patch defines compat __skb_gso_segment() to handle all segmentation cases.
Signed-off-by: Pravin B Shelar <pshe...@nicira.com> --- acinclude.m4 | 1 - datapath/linux/compat/gso.c | 3 ++ datapath/linux/compat/include/linux/netdevice.h | 24 +++++++++++----------- datapath/linux/compat/netdevice.c | 13 ++++++----- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 51cc969..6b08740 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -321,7 +321,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_disable_lro]) OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_stats]) OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_by_index_rcu]) - OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [__skb_gso_segment]) OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [can_checksum_protocol]) OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [netdev_features_t]) OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [pcpu_sw_netstats]) diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c index 552e748..f8a70d0 100644 --- a/datapath/linux/compat/gso.c +++ b/datapath/linux/compat/gso.c @@ -219,6 +219,9 @@ static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb, * make copy of it to restore it back. */ memcpy(cb, skb->cb, sizeof(cb)); + /* We are handling offloads by segmenting l3 packet, so + * no need to call OVS compat segmentation function. */ +#undef __skb_gso_segment segs = __skb_gso_segment(skb, 0, tx_path); if (!segs || IS_ERR(segs)) goto free; diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 38315c2..674a3a0 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -88,10 +88,19 @@ static inline struct net_device *dev_get_by_index_rcu(struct net *net, int ifind typedef u32 netdev_features_t; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +/* define compat version to handle MPLS segmentation offload. */ +#define __skb_gso_segment rpl__skb_gso_segment +struct sk_buff *rpl__skb_gso_segment(struct sk_buff *skb, + netdev_features_t features, + bool tx_path); + #define skb_gso_segment rpl_skb_gso_segment -struct sk_buff *rpl_skb_gso_segment(struct sk_buff *skb, - netdev_features_t features); +static inline +struct sk_buff *rpl_skb_gso_segment(struct sk_buff *skb, netdev_features_t features) +{ + return rpl__skb_gso_segment(skb, features, true); +} #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) @@ -106,15 +115,6 @@ static inline int rpl_netif_needs_gso(struct sk_buff *skb, int features) } #endif -#ifndef HAVE___SKB_GSO_SEGMENT -static inline struct sk_buff *__skb_gso_segment(struct sk_buff *skb, - netdev_features_t features, - bool tx_path) -{ - return skb_gso_segment(skb, features); -} -#endif - #if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) /* XEN dom0 networking assumes dev->master is bond device diff --git a/datapath/linux/compat/netdevice.c b/datapath/linux/compat/netdevice.c index 7bb8f77..8823a87 100644 --- a/datapath/linux/compat/netdevice.c +++ b/datapath/linux/compat/netdevice.c @@ -75,9 +75,10 @@ netdev_features_t rpl_netif_skb_features(struct sk_buff *skb) EXPORT_SYMBOL_GPL(rpl_netif_skb_features); #endif /* kernel version < 2.6.38 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) -struct sk_buff *rpl_skb_gso_segment(struct sk_buff *skb, - netdev_features_t features) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +struct sk_buff *rpl__skb_gso_segment(struct sk_buff *skb, + netdev_features_t features, + bool tx_path) { int vlan_depth = ETH_HLEN; __be16 type = skb->protocol; @@ -99,14 +100,14 @@ struct sk_buff *rpl_skb_gso_segment(struct sk_buff *skb, type = ovs_skb_get_inner_protocol(skb); /* this hack needed to get regular skb_gso_segment() */ -#undef skb_gso_segment skb_proto = skb->protocol; skb->protocol = type; - skb_gso = skb_gso_segment(skb, features); +#undef __skb_gso_segment + skb_gso = __skb_gso_segment(skb, features, tx_path); skb->protocol = skb_proto; return skb_gso; } -EXPORT_SYMBOL_GPL(rpl_skb_gso_segment); +EXPORT_SYMBOL_GPL(rpl__skb_gso_segment); #endif /* kernel version < 3.16.0 */ -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev