datapath: Fix build on RHEL 7.1
authorPravin B Shelar <pshelar@nicira.com>
Mon, 8 Jun 2015 22:50:35 +0000 (15:50 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Thu, 11 Jun 2015 16:55:51 +0000 (09:55 -0700)
Some of code is backported from following commit.

commit 13dd4a9738e99684a56b10ce2f1a5ee2d2ec2f9f
Author: Joe Stringer <joestringer@nicira.com>
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 <alexw@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Flavio Leitner <fbl@redhat.com>
acinclude.m4
datapath/compat.h
datapath/linux/Modules.mk
datapath/linux/compat/genetlink-openvswitch.c
datapath/linux/compat/include/net/genetlink.h
datapath/linux/compat/include/net/ip_tunnels.h
datapath/linux/compat/include/net/udp.h [new file with mode: 0644]
datapath/linux/compat/include/net/vxlan.h
datapath/vport-vxlan.c

index ee13e0e..0f53ea7 100644 (file)
@@ -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_<STRUCTURE>_WITH_<REGEX>), with <STRUCTURE> and <REGEX>
+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])
 
index f38d38c..d7447d2 100644 (file)
 #include <net/route.h>
 #include <net/xfrm.h>
 
-#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)
index 224eb02..2044b7b 100644 (file)
@@ -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
index 08f0fab..ab149c3 100644 (file)
@@ -1,7 +1,7 @@
 #include <net/genetlink.h>
 #include <linux/version.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
+#ifndef HAVE_GENL_NOTIFY_TAKES_FAMILY
 
 #undef genl_notify
 
index 9b2aa5b..341a488 100644 (file)
@@ -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;
index 4fc4fb4..ba7ef08 100644 (file)
@@ -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 (file)
index 0000000..94f1cb0
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __NET_UDP_WRAPPER_H
+#define __NET_UDP_WRAPPER_H  1
+
+#include <linux/version.h>
+
+#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 <net/udp.h>
+#define inet_get_local_port_range rpl_inet_get_local_port_range
+#else
+#include_next <net/udp.h>
+#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
index 23877ad..be249a3 100644 (file)
@@ -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
 }
index cc9477d..1b4333c 100644 (file)
@@ -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,