[ovs-dev] [PATCH 3/3] datapath: Add support for 4.3 kernel.
Pravin B Shelar
pshelar at nicira.com
Tue Sep 15 18:09:23 UTC 2015
Kernel 4.3 is not released yet, but we need this to support
netdev based vport in out of tree ovs module.
Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
FAQ.md | 2 +-
acinclude.m4 | 11 ++++++-
datapath/linux/compat/geneve.c | 3 +-
datapath/linux/compat/gre.c | 2 +-
datapath/linux/compat/gso.c | 5 ++-
datapath/linux/compat/gso.h | 32 +++++++++++++++--------
datapath/linux/compat/include/linux/netdevice.h | 18 +++++-------
datapath/linux/compat/include/net/geneve.h | 3 +-
datapath/linux/compat/include/net/gre.h | 10 +++++--
datapath/linux/compat/include/net/ip_tunnels.h | 3 +-
datapath/linux/compat/include/net/udp_tunnel.h | 4 ++-
datapath/linux/compat/include/net/vxlan.h | 4 ++-
datapath/linux/compat/ip_tunnels_core.c | 8 ++++-
datapath/linux/compat/udp_tunnel.c | 11 +++-----
14 files changed, 72 insertions(+), 44 deletions(-)
diff --git a/FAQ.md b/FAQ.md
index d11c493..038c28a 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -156,7 +156,7 @@ A: The following table lists the Linux kernel versions against which the
| 2.1.x | 2.6.32 to 3.11
| 2.3.x | 2.6.32 to 3.14
| 2.4.x | 2.6.32 to 4.0
-| 2.5.x | 2.6.32 to 4.2
+| 2.5.x | 2.6.32 to 4.3
Open vSwitch userspace should also work with the Linux kernel module
built into Linux 3.3 and later.
diff --git a/acinclude.m4 b/acinclude.m4
index b246dc7..c5848bc 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
AC_MSG_RESULT([$kversion])
if test "$version" -ge 4; then
- if test "$version" = 4 && test "$patchlevel" -le 2; then
+ if test "$version" = 4 && test "$patchlevel" -le 3; then
: # Linux 4.x
else
- AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.2.x is not supported (please refer to the FAQ for advice)])
+ AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.3.x is not supported (please refer to the FAQ for advice)])
fi
elif test "$version" = 3; then
: # Linux 3.x
@@ -327,6 +327,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/linux/in.h], [proto_ports_offset])
OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [__ip_select_ident.*dst_entry],
[OVS_DEFINE([HAVE_IP_SELECT_IDENT_USING_DST_ENTRY])])
+ OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [__ip_select_ident.*net],
+ [OVS_DEFINE([HAVE_IP_SELECT_IDENT_USING_NET])])
+
OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [inet_get_local_port_range.*net],
[OVS_DEFINE([HAVE_INET_GET_LOCAL_PORT_RANGE_USING_NET])])
OVS_GREP_IFELSE([$KSRC/include/net/ip.h], [ip_is_fragment])
@@ -344,6 +347,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [net_device_extended])
OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [rx_handler_func_t.*pskb],
[OVS_DEFINE([HAVE_RX_HANDLER_PSKB])])
+ OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [netif_needs_gso.*net_device],
+ [OVS_DEFINE([HAVE_NETIF_NEEDS_GSO_NETDEV])])
+
OVS_GREP_IFELSE([$KSRC/include/linux/netfilter.h], [nf_hookfn.*nf_hook_ops],
[OVS_DEFINE([HAVE_NF_HOOKFN_ARG_OPS])])
@@ -420,6 +426,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
OVS_GREP_IFELSE([$KSRC/include/net/geneve.h], [geneve_hdr])
OVS_GREP_IFELSE([$KSRC/include/net/gre.h], [gre_cisco_register])
+ OVS_GREP_IFELSE([$KSRC/include/net/gre.h], [gre_handle_offloads])
OVS_GREP_IFELSE([$KSRC/include/net/ipv6.h], [IP6_FH_F_SKIP_RH])
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be16])
diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index 85cf95f..8475419 100644
--- a/datapath/linux/compat/geneve.c
+++ b/datapath/linux/compat/geneve.c
@@ -12,7 +12,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) && \
+ defined(HAVE_GRE_HANDLE_OFFLOADS)
#include <linux/kernel.h>
#include <linux/types.h>
diff --git a/datapath/linux/compat/gre.c b/datapath/linux/compat/gre.c
index fe81380..de1dbaf 100644
--- a/datapath/linux/compat/gre.c
+++ b/datapath/linux/compat/gre.c
@@ -40,7 +40,7 @@
#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX)
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
#ifndef HAVE_GRE_CISCO_REGISTER
diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c
index 2c19b58..d11c62e 100644
--- a/datapath/linux/compat/gso.c
+++ b/datapath/linux/compat/gso.c
@@ -130,7 +130,7 @@ int rpl_dev_queue_xmit(struct sk_buff *skb)
if (mpls)
features &= NETIF_F_SG;
- if (netif_needs_gso(skb->dev, skb, features)) {
+ if (netif_needs_gso(skb, features)) {
struct sk_buff *nskb;
nskb = skb_gso_segment(skb, features);
@@ -170,7 +170,8 @@ drop:
EXPORT_SYMBOL_GPL(rpl_dev_queue_xmit);
#endif /* OVS_USE_COMPAT_GSO_SEGMENTATION */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
static __be16 __skb_network_protocol(struct sk_buff *skb)
{
__be16 type = skb->protocol;
diff --git a/datapath/linux/compat/gso.h b/datapath/linux/compat/gso.h
index 6fcaff8..bf409cf 100644
--- a/datapath/linux/compat/gso.h
+++ b/datapath/linux/compat/gso.h
@@ -2,7 +2,8 @@
#define __LINUX_GSO_WRAPPER_H
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
#include <linux/netdevice.h>
#include <linux/skbuff.h>
@@ -14,13 +15,10 @@ typedef void (*gso_fix_segment_t)(struct sk_buff *);
struct ovs_gso_cb {
struct ovs_skb_cb dp_cb;
gso_fix_segment_t fix_segment;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
__be16 inner_protocol;
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
unsigned int inner_mac_header;
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
unsigned int inner_network_header;
#endif
};
@@ -37,12 +35,15 @@ static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
}
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
+#define skb_inner_mac_header rpl_skb_inner_mac_header
static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
{
return skb->head + OVS_GSO_CB(skb)->inner_mac_header;
}
+#define skb_set_inner_mac_header rpl_skb_set_inner_mac_header
static inline void skb_set_inner_mac_header(const struct sk_buff *skb,
int offset)
{
@@ -50,12 +51,15 @@ static inline void skb_set_inner_mac_header(const struct sk_buff *skb,
}
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
+#define skb_inner_network_header rpl_skb_inner_network_header
static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
{
return skb->head + OVS_GSO_CB(skb)->inner_network_header;
}
+#define skb_inner_network_offset rpl_skb_inner_network_offset
static inline int skb_inner_network_offset(const struct sk_buff *skb)
{
return skb_inner_network_header(skb) - skb->data;
@@ -70,6 +74,7 @@ static inline int ovs_skb_inner_transport_offset(const struct sk_buff *skb)
return 0;
}
+#define skb_set_inner_network_header rpl_skb_set_inner_network_header
static inline void skb_set_inner_network_header(const struct sk_buff *skb,
int offset)
{
@@ -77,6 +82,7 @@ static inline void skb_set_inner_network_header(const struct sk_buff *skb,
+ offset;
}
+#define skb_set_inner_transport_header rpl_skb_set_inner_transport_header
static inline void skb_set_inner_transport_header(const struct sk_buff *skb,
int offset)
{ }
@@ -90,7 +96,8 @@ static inline int ovs_skb_inner_transport_offset(const struct sk_buff *skb)
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
OVS_GSO_CB(skb)->inner_protocol = htons(0);
}
@@ -114,7 +121,8 @@ static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb) {
*/
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
__be16 ethertype)
{
@@ -134,10 +142,12 @@ static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
}
#endif /* 3.11 */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) ||\
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
#define ip_local_out rpl_ip_local_out
int rpl_ip_local_out(struct sk_buff *skb);
+#define skb_inner_mac_offset rpl_skb_inner_mac_offset
static inline int skb_inner_mac_offset(const struct sk_buff *skb)
{
return skb_inner_mac_header(skb) - skb->data;
diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h
index 0fb2144..a2f7eb9 100644
--- a/datapath/linux/compat/include/linux/netdevice.h
+++ b/datapath/linux/compat/include/linux/netdevice.h
@@ -88,7 +88,8 @@ 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,19,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
#define OVS_USE_COMPAT_GSO_SEGMENTATION
#endif
@@ -112,18 +113,15 @@ struct sk_buff *rpl_skb_gso_segment(struct sk_buff *skb, netdev_features_t featu
netdev_features_t rpl_netif_skb_features(struct sk_buff *skb);
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
-static inline int rpl_netif_needs_gso(struct net_device *dev,
- struct sk_buff *skb, int features)
+#ifdef HAVE_NETIF_NEEDS_GSO_NETDEV
+#define netif_needs_gso rpl_netif_needs_gso
+static inline bool netif_needs_gso(struct sk_buff *skb,
+ netdev_features_t features)
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
return skb_is_gso(skb) && (!skb_gso_ok(skb, features) ||
- unlikely(skb->ip_summed != CHECKSUM_PARTIAL));
-#else
- return netif_needs_gso(skb, features);
-#endif
+ unlikely((skb->ip_summed != CHECKSUM_PARTIAL) &&
+ (skb->ip_summed != CHECKSUM_UNNECESSARY)));
}
-#define netif_needs_gso rpl_netif_needs_gso
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
diff --git a/datapath/linux/compat/include/net/geneve.h b/datapath/linux/compat/include/net/geneve.h
index 4f250c2..116ebc7 100644
--- a/datapath/linux/compat/include/net/geneve.h
+++ b/datapath/linux/compat/include/net/geneve.h
@@ -3,7 +3,8 @@
#include <linux/version.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) && \
+ defined(HAVE_GRE_HANDLE_OFFLOADS)
#include_next <net/geneve.h>
#else
diff --git a/datapath/linux/compat/include/net/gre.h b/datapath/linux/compat/include/net/gre.h
index 6e0df0f..040fd11 100644
--- a/datapath/linux/compat/include/net/gre.h
+++ b/datapath/linux/compat/include/net/gre.h
@@ -28,13 +28,17 @@ int rpl_gre_cisco_register(struct gre_cisco_protocol *proto);
#define gre_cisco_unregister rpl_gre_cisco_unregister
int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
+#ifndef GRE_HEADER_SECTION
struct gre_base_hdr {
__be16 flags;
__be16 protocol;
};
#define GRE_HEADER_SECTION 4
+#endif
+
+#define gre_flags_to_tnl_flags rpl_gre_flags_to_tnl_flags
static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
{
__be16 tflags = 0;
@@ -57,6 +61,7 @@ static inline __be16 gre_flags_to_tnl_flags(__be16 flags)
return tflags;
}
+#define tnl_flags_to_gre_flags rpl_tnl_flags_to_gre_flags
static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
{
__be16 flags = 0;
@@ -84,8 +89,7 @@ static inline __be16 tnl_flags_to_gre_flags(__be16 tflags)
#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)
-
+#ifndef HAVE_GRE_HANDLE_OFFLOADS
#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);
diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h
index 3ed6f91..0ca086f 100644
--- a/datapath/linux/compat/include/net/ip_tunnels.h
+++ b/datapath/linux/compat/include/net/ip_tunnels.h
@@ -7,7 +7,8 @@
#include_next <net/ip_tunnels.h>
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
#include <linux/if_tunnel.h>
#include <linux/netdevice.h>
diff --git a/datapath/linux/compat/include/net/udp_tunnel.h b/datapath/linux/compat/include/net/udp_tunnel.h
index d334746..21d05ff 100644
--- a/datapath/linux/compat/include/net/udp_tunnel.h
+++ b/datapath/linux/compat/include/net/udp_tunnel.h
@@ -4,7 +4,9 @@
#include <linux/version.h>
#include <linux/kconfig.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) && \
+ defined(HAVE_GRE_HANDLE_OFFLOADS)
+
#include_next <net/udp_tunnel.h>
static inline struct sk_buff *
diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
index cafff79..1a85a17 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -8,7 +8,9 @@
#include <linux/version.h>
-#ifdef HAVE_VXLAN_METADATA
+/* gre_handle_offload is not defined on kernel with netdev-vport support
+ * Use this as way to switch between compatibility implementations. */
+#if defined(HAVE_VXLAN_METADATA) && defined(HAVE_GRE_HANDLE_OFFLOADS)
#define USE_UPSTREAM_VXLAN
#include_next <net/vxlan.h>
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index 8ff7cd7..05c8564 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -35,7 +35,8 @@
#include "compat.h"
#include "gso.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl,
__be16 df, bool xnet)
@@ -71,6 +72,9 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
#ifdef HAVE_IP_SELECT_IDENT_USING_DST_ENTRY
__ip_select_ident(iph, &rt_dst(rt), (skb_shinfo(skb)->gso_segs ?: 1) - 1);
+#elif defined(HAVE_IP_SELECT_IDENT_USING_NET)
+ __ip_select_ident(dev_net(rt->dst.dev), iph,
+ skb_shinfo(skb)->gso_segs ?: 1);
#else
__ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1);
#endif
@@ -84,7 +88,7 @@ EXPORT_SYMBOL_GPL(rpl_iptunnel_xmit);
struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
bool csum_help, int gso_type_mask,
- void (*fix_segment)(struct sk_buff *))
+ void (*fix_segment)(struct sk_buff *))
{
int err;
diff --git a/datapath/linux/compat/udp_tunnel.c b/datapath/linux/compat/udp_tunnel.c
index b6c5bad..11cb22a 100644
--- a/datapath/linux/compat/udp_tunnel.c
+++ b/datapath/linux/compat/udp_tunnel.c
@@ -1,6 +1,7 @@
#include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) || \
+ !defined(HAVE_GRE_HANDLE_OFFLOADS)
#include <linux/module.h>
#include <linux/errno.h>
@@ -23,12 +24,10 @@ int rpl_udp_sock_create(struct net *net, struct udp_port_cfg *cfg,
if (cfg->family == AF_INET6) {
struct sockaddr_in6 udp6_addr;
- err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock);
+ err = ovs_sock_create_kern(net, AF_INET6, SOCK_DGRAM, 0, &sock);
if (err < 0)
goto error;
- sk_change_net(sock->sk, net);
-
udp6_addr.sin6_family = AF_INET6;
memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,
sizeof(udp6_addr.sin6_addr));
@@ -54,12 +53,10 @@ int rpl_udp_sock_create(struct net *net, struct udp_port_cfg *cfg,
if (cfg->family == AF_INET) {
struct sockaddr_in udp_addr;
- err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock);
+ err = ovs_sock_create_kern(net, AF_INET, SOCK_DGRAM, 0, &sock);
if (err < 0)
goto error;
- sk_change_net(sock->sk, net);
-
udp_addr.sin_family = AF_INET;
udp_addr.sin_addr = cfg->local_ip;
udp_addr.sin_port = cfg->local_udp_port;
--
1.7.1
More information about the dev
mailing list