From 943fdfe1de347326221c6e1f72b5e3d1b56fa008 Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 8 Jun 2015 15:50:35 -0700 Subject: [PATCH] datapath: Fix build on RHEL 7.1 Some of code is backported from following commit. commit 13dd4a9738e99684a56b10ce2f1a5ee2d2ec2f9f Author: Joe Stringer Date: Tue Mar 24 16:16:18 2015 -0700 compat: Fix RHEL7 build. Tested against 3.10.0-229.el7.x86_64. ----------8<-------- Reported-by: Alex Wang Signed-off-by: Pravin B Shelar Acked-by: Flavio Leitner --- acinclude.m4 | 46 +++++++++++++++++ datapath/compat.h | 6 +-- datapath/linux/Modules.mk | 1 + datapath/linux/compat/genetlink-openvswitch.c | 2 +- datapath/linux/compat/include/net/genetlink.h | 2 +- .../linux/compat/include/net/ip_tunnels.h | 4 ++ datapath/linux/compat/include/net/udp.h | 49 +++++++++++++++++++ datapath/linux/compat/include/net/vxlan.h | 6 +-- datapath/vport-vxlan.c | 5 +- 9 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 datapath/linux/compat/include/net/udp.h diff --git a/acinclude.m4 b/acinclude.m4 index ee13e0e7d..0f53ea714 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -212,6 +212,37 @@ AC_DEFUN([OVS_GREP_IFELSE], [ fi ]) +dnl OVS_FIND_FIELD_IFELSE(FILE, STRUCTURE, REGEX, [IF-MATCH], [IF-NO-MATCH]) +dnl +dnl Looks for STRUCTURE in FILE. If it is found, greps for REGEX within the +dnl structure definition. If this is successful, runs IF-MATCH, otherwise +dnl IF_NO_MATCH. If IF-MATCH is empty then it defines to +dnl OVS_DEFINE(HAVE__WITH_), with and +dnl translated to uppercase. +AC_DEFUN([OVS_FIND_FIELD_IFELSE], [ + AC_MSG_CHECKING([whether $2 has member $3 in $1]) + if test -f $1; then + awk '/$2.{/,/^}/' $1 2>/dev/null | grep '$3' + status=$? + case $status in + 0) + AC_MSG_RESULT([yes]) + m4_if([$4], [], [OVS_DEFINE([HAVE_]m4_toupper([$2])[_WITH_]m4_toupper([$3]))], [$4]) + ;; + 1) + AC_MSG_RESULT([no]) + $5 + ;; + *) + AC_MSG_ERROR([grep exited with status $status]) + ;; + esac + else + AC_MSG_RESULT([file not found]) + $5 + fi +]) + dnl OVS_DEFINE(NAME) dnl dnl Defines NAME to 1 in kcompat.h. @@ -316,10 +347,19 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [parallel_ops]) OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [genlmsg_new_unicast]) + OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [genl_notify.*genl_family], + [OVS_DEFINE([HAVE_GENL_NOTIFY_TAKES_FAMILY])]) + + OVS_FIND_FIELD_IFELSE([$KSRC/include/net/genetlink.h], + [genl_multicast_group], [id]) + 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/ip_tunnels.h], [iptunnel_xmit.*net], [OVS_DEFINE([HAVE_IPTUNNEL_XMIT_NET])]) + OVS_GREP_IFELSE([$KSRC/include/net/ip_tunnels.h], [iptunnel_xmit.*sock], + [OVS_DEFINE([HAVE_IPTUNNEL_XMIT_SOCK])]) + 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]) @@ -327,6 +367,12 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be64]) OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_find_nested]) OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [vxlan_xmit_skb]) + OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [vxlan_xmit_skb.*net], + [OVS_DEFINE([HAVE_VXLAN_XMIT_SKB_NET])]) + + OVS_GREP_IFELSE([$KSRC/include/net/udp.h], [udp_flow_src_port], + [OVS_GREP_IFELSE([$KSRC/include/net/udp.h], [inet_get_local_port_range(net], + [OVS_DEFINE([HAVE_UDP_FLOW_SRC_PORT])])]) OVS_GREP_IFELSE([$KSRC/include/net/sctp/checksum.h], [sctp_compute_cksum]) diff --git a/datapath/compat.h b/datapath/compat.h index f38d38c06..d7447d2fc 100644 --- a/datapath/compat.h +++ b/datapath/compat.h @@ -25,10 +25,10 @@ #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) -#define GROUP_ID(grp) 0 -#else +#ifdef HAVE_GENL_MULTICAST_GROUP_WITH_ID #define GROUP_ID(grp) ((grp)->id) +#else +#define GROUP_ID(grp) 0 #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index 224eb025f..2044b7bc9 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -71,5 +71,6 @@ openvswitch_headers += \ linux/compat/include/net/net_namespace.h \ linux/compat/include/net/netlink.h \ linux/compat/include/net/sock.h \ + linux/compat/include/net/udp.h \ linux/compat/include/net/vxlan.h \ linux/compat/include/net/sctp/checksum.h diff --git a/datapath/linux/compat/genetlink-openvswitch.c b/datapath/linux/compat/genetlink-openvswitch.c index 08f0fab8b..ab149c35d 100644 --- a/datapath/linux/compat/genetlink-openvswitch.c +++ b/datapath/linux/compat/genetlink-openvswitch.c @@ -1,7 +1,7 @@ #include #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) +#ifndef HAVE_GENL_NOTIFY_TAKES_FAMILY #undef genl_notify diff --git a/datapath/linux/compat/include/net/genetlink.h b/datapath/linux/compat/include/net/genetlink.h index 9b2aa5b65..341a488a3 100644 --- a/datapath/linux/compat/include/net/genetlink.h +++ b/datapath/linux/compat/include/net/genetlink.h @@ -17,7 +17,7 @@ #define portid pid #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) +#ifndef HAVE_GENL_NOTIFY_TAKES_FAMILY struct rpl_genl_family { struct genl_family compat_family; unsigned int id; diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 4fc4fb4af..ba7ef0825 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -20,9 +20,13 @@ static inline int rpl_iptunnel_xmit(struct rtable *rt, { #ifdef HAVE_IPTUNNEL_XMIT_NET return iptunnel_xmit(NULL, rt, skb, src, dst, proto, tos, ttl, df); +#else +#ifdef HAVE_IPTUNNEL_XMIT_SOCK + return iptunnel_xmit(NULL, rt, skb, src, dst, proto, tos, ttl, df); #else return iptunnel_xmit(rt, skb, src, dst, proto, tos, ttl, df, xnet); #endif +#endif } #define iptunnel_xmit rpl_iptunnel_xmit diff --git a/datapath/linux/compat/include/net/udp.h b/datapath/linux/compat/include/net/udp.h new file mode 100644 index 000000000..94f1cb0d5 --- /dev/null +++ b/datapath/linux/compat/include/net/udp.h @@ -0,0 +1,49 @@ +#ifndef __NET_UDP_WRAPPER_H +#define __NET_UDP_WRAPPER_H 1 + +#include + +#ifdef inet_get_local_port_range +/* RHEL7 backports udp_flow_src_port() using an older version of + * inet_get_local_port_range(). */ +#undef inet_get_local_port_range +#include_next +#define inet_get_local_port_range rpl_inet_get_local_port_range +#else +#include_next +#endif + +#ifndef HAVE_UDP_FLOW_SRC_PORT +static inline __be16 rpl_udp_flow_src_port(struct net *net, struct sk_buff *skb, + int min, int max, bool use_eth) +{ + u32 hash; + + if (min >= max) { + /* Use default range */ + inet_get_local_port_range(net, &min, &max); + } + + hash = skb_get_hash(skb); + if (unlikely(!hash) && use_eth) { + /* Can't find a normal hash, caller has indicated an Ethernet + * packet so use that to compute a hash. + */ + hash = jhash(skb->data, 2 * ETH_ALEN, + (__force u32) skb->protocol); + } + + /* Since this is being sent on the wire obfuscate hash a bit + * to minimize possbility that any useful information to an + * attacker is leaked. Only upper 16 bits are relevant in the + * computation for 16 bit port value. + */ + hash ^= hash << 16; + + return htons((((u64) hash * (max - min)) >> 32) + min); +} + +#define udp_flow_src_port rpl_udp_flow_src_port +#endif + +#endif diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h index 23877adfc..be249a3bb 100644 --- a/datapath/linux/compat/include/net/vxlan.h +++ b/datapath/linux/compat/include/net/vxlan.h @@ -19,11 +19,11 @@ static inline int rpl_vxlan_xmit_skb(struct vxlan_sock *vs, kfree_skb(skb); return -ENOSYS; } -#ifndef HAVE_IPTUNNEL_XMIT_NET - return vxlan_xmit_skb(vs, rt, skb, src, dst, tos, ttl, df, +#ifdef HAVE_VXLAN_XMIT_SKB_NET + return vxlan_xmit_skb(NULL, vs, rt, skb, src, dst, tos, ttl, df, src_port, dst_port, vni); #else - return vxlan_xmit_skb(NULL, vs, rt, skb, src, dst, tos, ttl, df, + return vxlan_xmit_skb(vs, rt, skb, src, dst, tos, ttl, df, src_port, dst_port, vni); #endif } diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c index cc9477dd1..1b4333c2a 100644 --- a/datapath/vport-vxlan.c +++ b/datapath/vport-vxlan.c @@ -146,8 +146,6 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) __be16 src_port; __be32 saddr; __be16 df; - int port_min; - int port_max; int err; if (unlikely(!OVS_CB(skb)->tun_key)) { @@ -173,8 +171,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) skb->local_df = 1; - inet_get_local_port_range(net, &port_min, &port_max); - src_port = vxlan_src_port(port_min, port_max, skb); + src_port = udp_flow_src_port(net, skb, 0, 0, true); err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, saddr, OVS_CB(skb)->tun_key->ipv4_dst, -- 2.20.1