From e2f3178f0582eda302bdc5629189b6a56d9fbcdd Mon Sep 17 00:00:00 2001 From: Pritesh Kothari Date: Thu, 1 May 2014 15:50:48 -0700 Subject: [PATCH] datapath: Add support for kernel 3.14. Signed-off-by: Pritesh Kothari Signed-off-by: Jesse Gross --- 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 +- .../linux/compat/include/linux/etherdevice.h | 2 ++ .../linux/compat/include/linux/if_tunnel.h | 20 --------------- .../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 128abe8ef..86b48a216 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 59e69afe0..704513e5e 100644 --- a/NEWS +++ b/NEWS @@ -27,7 +27,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 fdcdf4491..518a66b79 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 f71f1f67a..7fe2f5454 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 f8f04697c..f38d38c06 100644 --- a/datapath/compat.h +++ b/datapath/compat.h @@ -25,13 +25,6 @@ #include #include -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 0611dada1..81ecc0f70 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -254,7 +254,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 1e76305c6..224eb025f 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 a8a2e5233..ab60daa3b 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 556729d8c..c6e8e92f7 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 96ab7026e..000000000 --- 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 -#include_next - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) - -#include - -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 e04f308cf..d726390ef 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 + +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 000000000..f2a6d6aa1 --- /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 + +#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 714c955be..b5caa9680 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 HAVE_RXHASH + 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 779075d1e..d650be290 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 848a3952b..b8b8fa762 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 8e3ff6928..a1e2b2b69 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 8f618b5a1..0dcecd048 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 6e7660157..cfaea09bf 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; -- 2.43.0