For kernel version 3.12 to 3.18, GRE uses compat code to transmit packets which used fix_segment to segment packets. but ovs_gso_cb->fix_segment is not initialized for GRE tunnels. Following patches fixes it by resetting fix_segment.
Signed-off-by: Pravin B Shelar <pshe...@nicira.com> --- Fixed for kernel 3.12 and newer. --- datapath/linux/compat/gre.c | 50 ++++++++++++++++++------------ datapath/linux/compat/include/net/gre.h | 18 ++--------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c index e2a7591..fe81380 100644 --- a/datapath/linux/compat/gre.c +++ b/datapath/linux/compat/gre.c @@ -17,11 +17,7 @@ */ #include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0) - #include <linux/kconfig.h> -#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) - #include <linux/module.h> #include <linux/if.h> #include <linux/if_tunnel.h> @@ -42,6 +38,10 @@ #include "gso.h" +#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0) + #ifndef HAVE_GRE_CISCO_REGISTER #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) @@ -287,20 +287,6 @@ static void gre_csum_fix(struct sk_buff *skb) skb->len - gre_offset, 0)); } -struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) -{ - int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; - gso_fix_segment_t fix_segment; - - if (gre_csum) - fix_segment = gre_csum_fix; - else - fix_segment = gre_nop_fix; - - return ovs_iptunnel_handle_offloads(skb, gre_csum, type, fix_segment); -} -EXPORT_SYMBOL_GPL(rpl_gre_handle_offloads); - static bool is_gre_gso(struct sk_buff *skb) { return skb_is_gso(skb); @@ -339,6 +325,30 @@ void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, } EXPORT_SYMBOL_GPL(rpl_gre_build_header); -#endif /* CONFIG_NET_IPGRE_DEMUX */ +struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; + gso_fix_segment_t fix_segment; + + if (gre_csum) + fix_segment = gre_csum_fix; + else + fix_segment = gre_nop_fix; -#endif /* 3.12 */ + return ovs_iptunnel_handle_offloads(skb, gre_csum, type, fix_segment); +} +#else +struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +{ + if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { + kfree_skb(skb); + return ERR_PTR(-ENOSYS); + } + skb_clear_ovs_gso_cb(skb); +#undef gre_handle_offloads + return gre_handle_offloads(skb, gre_csum); +} +#endif +EXPORT_SYMBOL_GPL(rpl_gre_handle_offloads); + +#endif /* CONFIG_NET_IPGRE_DEMUX */ diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h index f572ac9..6e0df0f 100644 --- a/datapath/linux/compat/include/net/gre.h +++ b/datapath/linux/compat/include/net/gre.h @@ -81,15 +81,15 @@ static inline __be16 tnl_flags_to_gre_flags(__be16 tflags) #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */ #endif /* HAVE_GRE_CISCO_REGISTER */ +#define gre_handle_offloads rpl_gre_handle_offloads +struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum); + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0) #define gre_build_header rpl_gre_build_header void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, int hdr_len); -#define gre_handle_offloads rpl_gre_handle_offloads -struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum); - #define ip_gre_calc_hlen rpl_ip_gre_calc_hlen static inline int ip_gre_calc_hlen(__be16 o_flags) { @@ -103,18 +103,6 @@ static inline int ip_gre_calc_hlen(__be16 o_flags) addend += 4; return addend; } -#else - -static inline struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, - bool gre_csum) -{ - if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { - kfree_skb(skb); - return ERR_PTR(-ENOSYS); - } - return gre_handle_offloads(skb, gre_csum); -} -#define gre_handle_offloads rpl_gre_handle_offloads #endif #endif -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev