[ovs-dev] [PATCH v6] datapath: Add support for kernel 3.14.

Pritesh Kothari pritesh.kothari at cisco.com
Tue Apr 29 22:24:35 UTC 2014


Signed-off-by: Pritesh Kothari <pritesh.kothari at cisco.com>
---
v6: rebase for changes in datapath/datapath.c
v5: move skb_clear_rxhash() from compat.h to skbuff.h,
    simplify skb_get_hash() integration,
    fix random.h order in acinclude.m4,
    move pcpu_sw_netstats to netdevice.h.
v4: rebase for changes in datapath/actions.c and datapath/vport.c,
    split patch in two for seperating out skb_clear_hash related stuff.
v3: rebase for changes in datapath/vport.c.
v2: Use OVS_GREP_IFELSE instead of upstream kernel versions as Thomas suggested.
---
 FAQ                                               |  2 +-
 NEWS                                              |  2 +-
 acinclude.m4                                      | 10 +++++++--
 datapath/actions.c                                | 14 ++++++-------
 datapath/compat.h                                 |  7 -------
 datapath/datapath.c                               |  2 +-
 datapath/linux/Modules.mk                         |  2 +-
 datapath/linux/compat/flow_dissector.c            |  2 +-
 datapath/linux/compat/include/linux/etherdevice.h |  2 ++
 datapath/linux/compat/include/linux/if_tunnel.h   | 20 ------------------
 datapath/linux/compat/include/linux/netdevice.h   | 13 ++++++++++++
 datapath/linux/compat/include/linux/random.h      | 10 +++++++++
 datapath/linux/compat/include/linux/skbuff.h      | 25 ++++++++++++++++++-----
 datapath/linux/compat/ip_tunnels_core.c           |  4 ++--
 datapath/linux/compat/vxlan.c                     |  2 +-
 datapath/vport-lisp.c                             |  2 +-
 datapath/vport.c                                  | 16 +++++++--------
 datapath/vport.h                                  |  2 +-
 18 files changed, 78 insertions(+), 59 deletions(-)
 delete mode 100644 datapath/linux/compat/include/linux/if_tunnel.h
 create mode 100644 datapath/linux/compat/include/linux/random.h

diff --git a/FAQ b/FAQ
index c43b0c8..22a1cf0 100644
--- a/FAQ
+++ b/FAQ
@@ -149,7 +149,7 @@ A: The following table lists the Linux kernel versions against which the
        1.11.x     2.6.18 to 3.8
        2.0.x      2.6.32 to 3.10
        2.1.x      2.6.32 to 3.11
-       2.2.x      2.6.32 to 3.13
+       2.2.x      2.6.32 to 3.14
 
    Open vSwitch userspace should also work with the Linux kernel module
    built into Linux 3.3 and later.
diff --git a/NEWS b/NEWS
index 74b57ff..cbf6802 100644
--- a/NEWS
+++ b/NEWS
@@ -17,7 +17,7 @@ v2.2.0 - xx xxx xxx
    - Upon the receipt of a SIGHUP signal, ovs-vswitchd no longer reopens its
      log file (it will terminate instead). Please use 'ovs-appctl vlog/reopen'
      instead.
-   - Support for Linux kernels up to 3.13. From Kernel 3.12 onwards OVS uses
+   - Support for Linux kernels up to 3.14. From Kernel 3.12 onwards OVS uses
      tunnel API for GRE and VXLAN.
    - Added DPDK support.
    - Added support for custom vlog patterns in Python
diff --git a/acinclude.m4 b/acinclude.m4
index fdcdf44..518a66b 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
     AC_MSG_RESULT([$kversion])
 
     if test "$version" -ge 3; then
-       if test "$version" = 3 && test "$patchlevel" -le 13; then
+       if test "$version" = 3 && test "$patchlevel" -le 14; then
           : # Linux 3.x
        else
-         AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.13.x is not supported (please refer to the FAQ for advice)])
+         AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.14.x is not supported (please refer to the FAQ for advice)])
        fi
     else
        if test "$version" -le 1 || test "$patchlevel" -le 5 || test "$sublevel" -le 31; then
@@ -244,6 +244,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [ERR_CAST])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [eth_hw_addr_random])
+  OVS_GREP_IFELSE([$KSRC/include/linux/etherdevice.h], [ether_addr_copy])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [vlan_set_encap_proto])
 
@@ -255,6 +256,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   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])
+
+  OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/rcupdate.h], [rcu_read_lock_held], [],
                   [OVS_GREP_IFELSE([$KSRC/include/linux/rtnetlink.h],
@@ -289,6 +293,8 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_reset_mac_len])
   OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_unclone])
   OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_orphan_frags])
+  OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_get_hash])
+  OVS_GREP_IFELSE([$KSRC/include/linux/skbuff.h], [skb_clear_hash])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/types.h], [bool],
                   [OVS_DEFINE([HAVE_BOOL_TYPE])])
diff --git a/datapath/actions.c b/datapath/actions.c
index 5871d82..96cab80 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -166,7 +166,7 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
 	}
 
 	csum_replace4(&nh->check, *addr, new_addr);
-	skb_clear_rxhash(skb);
+	skb_clear_hash(skb);
 	*addr = new_addr;
 }
 
@@ -200,7 +200,7 @@ static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
 	if (recalculate_csum)
 		update_ipv6_checksum(skb, l4_proto, addr, new_addr);
 
-	skb_clear_rxhash(skb);
+	skb_clear_hash(skb);
 	memcpy(addr, new_addr, sizeof(__be32[4]));
 }
 
@@ -297,7 +297,7 @@ static void set_tp_port(struct sk_buff *skb, __be16 *port,
 {
 	inet_proto_csum_replace2(check, skb, *port, new_port, 0);
 	*port = new_port;
-	skb_clear_rxhash(skb);
+	skb_clear_hash(skb);
 }
 
 static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port)
@@ -311,7 +311,7 @@ static void set_udp_port(struct sk_buff *skb, __be16 *port, __be16 new_port)
 			uh->check = CSUM_MANGLED_0;
 	} else {
 		*port = new_port;
-		skb_clear_rxhash(skb);
+		skb_clear_hash(skb);
 	}
 }
 
@@ -382,7 +382,7 @@ static int set_sctp(struct sk_buff *skb,
 		/* Carry any checksum errors through. */
 		sh->checksum = old_csum ^ old_correct_csum ^ new_csum;
 
-		skb_clear_rxhash(skb);
+		skb_clear_hash(skb);
 	}
 
 	return 0;
@@ -446,7 +446,7 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
 		 a = nla_next(a, &rem)) {
 		switch (nla_type(a)) {
 		case OVS_SAMPLE_ATTR_PROBABILITY:
-			if (net_random() >= nla_get_u32(a))
+			if (prandom_u32() >= nla_get_u32(a))
 				return 0;
 			break;
 
@@ -467,7 +467,7 @@ static void execute_hash(struct sk_buff *skb, const struct nlattr *attr)
 	u32 hash = 0;
 
 	/* OVS_HASH_ALG_L4 is the only possible hash algorithm.  */
-	hash = skb_get_rxhash(skb);
+	hash = skb_get_hash(skb);
 	hash = jhash_1word(hash, hash_act->hash_basis);
 	if (!hash)
 		hash = 0x1;
diff --git a/datapath/compat.h b/datapath/compat.h
index f8f0469..f38d38c 100644
--- a/datapath/compat.h
+++ b/datapath/compat.h
@@ -25,13 +25,6 @@
 #include <net/route.h>
 #include <net/xfrm.h>
 
-static inline void skb_clear_rxhash(struct sk_buff *skb)
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
-	skb->rxhash = 0;
-#endif
-}
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
 #define GROUP_ID(grp)	0
 #else
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 10706f5..e76838a 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -253,7 +253,7 @@ void ovs_dp_process_packet_with_key(struct sk_buff *skb,
 	stats = this_cpu_ptr(dp->stats_percpu);
 
 	/* Look up flow. */
-	flow = ovs_flow_tbl_lookup_stats(&dp->table, pkt_key, skb_get_rxhash(skb),
+	flow = ovs_flow_tbl_lookup_stats(&dp->table, pkt_key, skb_get_hash(skb),
 					 &n_mask_hit);
 	if (unlikely(!flow)) {
 		struct dp_upcall_info upcall;
diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk
index 1e76305..224eb02 100644
--- a/datapath/linux/Modules.mk
+++ b/datapath/linux/Modules.mk
@@ -32,7 +32,6 @@ openvswitch_headers += \
 	linux/compat/include/linux/if.h \
 	linux/compat/include/linux/if_arp.h \
 	linux/compat/include/linux/if_ether.h \
-	linux/compat/include/linux/if_tunnel.h \
 	linux/compat/include/linux/if_vlan.h \
 	linux/compat/include/linux/in.h \
 	linux/compat/include/linux/ip.h \
@@ -43,6 +42,7 @@ openvswitch_headers += \
 	linux/compat/include/linux/list.h \
 	linux/compat/include/linux/log2.h \
 	linux/compat/include/linux/net.h \
+	linux/compat/include/linux/random.h \
 	linux/compat/include/linux/netdevice.h \
 	linux/compat/include/linux/netdev_features.h \
 	linux/compat/include/linux/netlink.h \
diff --git a/datapath/linux/compat/flow_dissector.c b/datapath/linux/compat/flow_dissector.c
index a8a2e52..ab60daa 100644
--- a/datapath/linux/compat/flow_dissector.c
+++ b/datapath/linux/compat/flow_dissector.c
@@ -204,7 +204,7 @@ static __always_inline u32 __flow_hash_3words(u32 a, u32 b, u32 c)
 	return jhash_3words(a, b, c, hashrnd);
 }
 
-u32 __skb_get_rxhash(struct sk_buff *skb)
+u32 __skb_get_hash(struct sk_buff *skb)
 {
 	struct flow_keys keys;
 	u32 hash;
diff --git a/datapath/linux/compat/include/linux/etherdevice.h b/datapath/linux/compat/include/linux/etherdevice.h
index 556729d..c6e8e92 100644
--- a/datapath/linux/compat/include/linux/etherdevice.h
+++ b/datapath/linux/compat/include/linux/etherdevice.h
@@ -34,6 +34,7 @@ static inline int eth_mac_addr(struct net_device *dev, void *p)
 }
 #endif
 
+#ifndef HAVE_ETHER_ADDR_COPY
 static inline void ether_addr_copy(u8 *dst, const u8 *src)
 {
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
@@ -48,5 +49,6 @@ static inline void ether_addr_copy(u8 *dst, const u8 *src)
 	a[2] = b[2];
 #endif
 }
+#endif
 
 #endif
diff --git a/datapath/linux/compat/include/linux/if_tunnel.h b/datapath/linux/compat/include/linux/if_tunnel.h
deleted file mode 100644
index 96ab702..0000000
--- a/datapath/linux/compat/include/linux/if_tunnel.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _IF_TUNNEL_WRAPPER_H_
-#define _IF_TUNNEL_WRAPPER_H_
-
-#include <linux/version.h>
-#include_next <linux/if_tunnel.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
-
-#include <linux/u64_stats_sync.h>
-
-struct pcpu_tstats {
-	u64     rx_packets;
-	u64     rx_bytes;
-	u64     tx_packets;
-	u64     tx_bytes;
-	struct u64_stats_sync   syncp;
-};
-#endif
-
-#endif /* _IF_TUNNEL_WRAPPER_H_ */
diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h
index e04f308..d726390 100644
--- a/datapath/linux/compat/include/linux/netdevice.h
+++ b/datapath/linux/compat/include/linux/netdevice.h
@@ -125,4 +125,17 @@ static inline struct net_device *netdev_notifier_info_to_dev(void *info)
 }
 #endif
 
+#ifndef HAVE_PCPU_SW_NETSTATS
+
+#include <linux/u64_stats_sync.h>
+
+struct pcpu_sw_netstats {
+	u64     rx_packets;
+	u64     rx_bytes;
+	u64     tx_packets;
+	u64     tx_bytes;
+	struct u64_stats_sync   syncp;
+};
+#endif
+
 #endif
diff --git a/datapath/linux/compat/include/linux/random.h b/datapath/linux/compat/include/linux/random.h
new file mode 100644
index 0000000..f2a6d6a
--- /dev/null
+++ b/datapath/linux/compat/include/linux/random.h
@@ -0,0 +1,10 @@
+#ifndef __LINUX_RANDOM_WRAPPER_H
+#define __LINUX_RANDOM_WRAPPER_H 1
+
+#include_next <linux/random.h>
+
+#ifndef HAVE_PRANDOM_U32
+#define prandom_u32()		random32()
+#endif
+
+#endif
diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h
index 714c955..de9b29d 100644
--- a/datapath/linux/compat/include/linux/skbuff.h
+++ b/datapath/linux/compat/include/linux/skbuff.h
@@ -250,20 +250,27 @@ static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask)
 }
 #endif
 
+#ifndef HAVE_SKB_GET_HASH
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
-#define __skb_get_rxhash rpl__skb_get_rxhash
-#define skb_get_rxhash rpl_skb_get_rxhash
+#define __skb_get_hash rpl__skb_get_rxhash
+#define skb_get_hash rpl_skb_get_rxhash
 
-extern u32 __skb_get_rxhash(struct sk_buff *skb);
-static inline __u32 skb_get_rxhash(struct sk_buff *skb)
+extern u32 __skb_get_hash(struct sk_buff *skb);
+static inline __u32 skb_get_hash(struct sk_buff *skb)
 {
 #ifdef HAVE_RXHASH
 	if (skb->rxhash)
 		return skb->rxhash;
 #endif
-	return __skb_get_rxhash(skb);
+	return __skb_get_hash(skb);
 }
 
+#else
+#define skb_get_hash skb_get_rxhash
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) */
+#endif /* HAVE_SKB_GET_HASH */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
 static inline void skb_tx_error(struct sk_buff *skb)
 {
 	return;
@@ -276,6 +283,14 @@ int skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len,
 		  int hlen);
 #endif
 
+#ifndef HAVE_SKB_CLEAR_HASH
+static inline void skb_clear_hash(struct sk_buff *skb)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+	skb->rxhash = 0;
+#endif
+}
+#endif
 
 #ifndef HAVE_SKB_HAS_FRAG_LIST
 #define skb_has_frag_list skb_has_frags
diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c
index 779075d..d650be2 100644
--- a/datapath/linux/compat/ip_tunnels_core.c
+++ b/datapath/linux/compat/ip_tunnels_core.c
@@ -48,7 +48,7 @@ int iptunnel_xmit(struct rtable *rt,
 
 	nf_reset(skb);
 	secpath_reset(skb);
-	skb_clear_rxhash(skb);
+	skb_clear_hash(skb);
 	skb_dst_drop(skb);
 	skb_dst_set(skb, &rt_dst(rt));
 #if 0
@@ -104,7 +104,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
 
 	nf_reset(skb);
 	secpath_reset(skb);
-	skb_clear_rxhash(skb);
+	skb_clear_hash(skb);
 	skb_dst_drop(skb);
 	vlan_set_tci(skb, 0);
 	skb_set_queue_mapping(skb, 0);
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 848a395..b8b8fa7 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -132,7 +132,7 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
 	unsigned int range = (port_max - port_min) + 1;
 	u32 hash;
 
-	hash = skb_get_rxhash(skb);
+	hash = skb_get_hash(skb);
 	if (!hash)
 		hash = jhash(skb->data, 2 * ETH_ALEN,
 			     (__force u32) skb->protocol);
diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
index 8e3ff69..a1e2b2b 100644
--- a/datapath/vport-lisp.c
+++ b/datapath/vport-lisp.c
@@ -165,7 +165,7 @@ static __be64 instance_id_to_tunnel_id(__u8 *iid)
  */
 static u16 get_src_port(struct net *net, struct sk_buff *skb)
 {
-	u32 hash = skb_get_rxhash(skb);
+	u32 hash = skb_get_hash(skb);
 	unsigned int range;
 	int high;
 	int low;
diff --git a/datapath/vport.c b/datapath/vport.c
index 8f618b5..0dcecd0 100644
--- a/datapath/vport.c
+++ b/datapath/vport.c
@@ -142,14 +142,14 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
 	if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids))
 		return ERR_PTR(-EINVAL);
 
-	vport->percpu_stats = alloc_percpu(struct pcpu_tstats);
+	vport->percpu_stats = alloc_percpu(struct pcpu_sw_netstats);
 	if (!vport->percpu_stats) {
 		kfree(vport);
 		return ERR_PTR(-ENOMEM);
 	}
 
 	for_each_possible_cpu(i) {
-		struct pcpu_tstats *vport_stats;
+		struct pcpu_sw_netstats *vport_stats;
 		vport_stats = per_cpu_ptr(vport->percpu_stats, i);
 		u64_stats_init(&vport_stats->syncp);
 	}
@@ -302,8 +302,8 @@ void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
 	spin_unlock_bh(&vport->stats_lock);
 
 	for_each_possible_cpu(i) {
-		const struct pcpu_tstats *percpu_stats;
-		struct pcpu_tstats local_stats;
+		const struct pcpu_sw_netstats *percpu_stats;
+		struct pcpu_sw_netstats local_stats;
 		unsigned int start;
 
 		percpu_stats = per_cpu_ptr(vport->percpu_stats, i);
@@ -436,7 +436,7 @@ int ovs_vport_get_upcall_portids(const struct vport *vport,
  * @vport: vport from which the missed packet is received.
  * @skb: skb that the missed packet was received.
  *
- * Uses the skb_get_rxhash() to select the upcall portid to send the
+ * Uses the skb_get_hash() to select the upcall portid to send the
  * upcall.
  *
  * Returns the portid of the target socket.  Must be called with rcu_read_lock.
@@ -451,7 +451,7 @@ u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
 	if (ids->n_ids == 1 && ids->ids[0] == 0)
 		return 0;
 
-	hash = skb_get_rxhash(skb);
+	hash = skb_get_hash(skb);
 	return ids->ids[hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids)];
 }
 
@@ -469,7 +469,7 @@ u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb)
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
 		       struct ovs_key_ipv4_tunnel *tun_key)
 {
-	struct pcpu_tstats *stats;
+	struct pcpu_sw_netstats *stats;
 
 	stats = this_cpu_ptr(vport->percpu_stats);
 	u64_stats_update_begin(&stats->syncp);
@@ -495,7 +495,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
 	int sent = vport->ops->send(vport, skb);
 
 	if (likely(sent > 0)) {
-		struct pcpu_tstats *stats;
+		struct pcpu_sw_netstats *stats;
 
 		stats = this_cpu_ptr(vport->percpu_stats);
 
diff --git a/datapath/vport.h b/datapath/vport.h
index 6e76601..cfaea09 100644
--- a/datapath/vport.h
+++ b/datapath/vport.h
@@ -106,7 +106,7 @@ struct vport {
 	struct hlist_node dp_hash_node;
 	const struct vport_ops *ops;
 
-	struct pcpu_tstats __percpu *percpu_stats;
+	struct pcpu_sw_netstats __percpu *percpu_stats;
 
 	spinlock_t stats_lock;
 	struct vport_err_stats err_stats;
-- 
1.9.1




More information about the dev mailing list