diff --git a/.travis.yml b/.travis.yml index 52c9362c892..2b262e47355 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,9 +30,6 @@ env: - KERNEL=3.14.60 - KERNEL=3.12.53 - KERNEL=3.10.96 - - KERNEL=3.4.110 - - KERNEL=3.2.76 - - KERNEL=2.6.32.70 script: ./.travis/build.sh $OPTS diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f69cfff0b9..439c56ad4b0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ Testing is also important: - A patch that modifies Linux kernel code should be at least build-tested on various Linux kernel versions before - submission. I suggest versions 2.6.32 and whatever + submission. I suggest versions 3.10 and whatever the current latest release version is at the time. - A patch that modifies the ofproto or vswitchd code should be diff --git a/FAQ.md b/FAQ.md index 8bd7ab91903..0ebf1d5cb6e 100644 --- a/FAQ.md +++ b/FAQ.md @@ -27,7 +27,7 @@ A: Open vSwitch is a production quality open source software switch ### Q: What virtualization platforms can use Open vSwitch? A: Open vSwitch can currently run on any Linux-based virtualization - platform (kernel 2.6.32 and newer), including: KVM, VirtualBox, Xen, + platform (kernel 3.10 and newer), including: KVM, VirtualBox, Xen, Xen Cloud Platform, XenServer. As of Linux 3.3 it is part of the mainline kernel. The bulk of the code is written in platform- independent C and is easily ported to other environments. We welcome @@ -157,6 +157,7 @@ A: The following table lists the Linux kernel versions against which the | 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.3 +| 2.6.x | 3.10 to 4.3 Open vSwitch userspace should also work with the Linux kernel module built into Linux 3.3 and later. diff --git a/INSTALL.md b/INSTALL.md index 9c96bbe0f6e..9dadcee53cb 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -63,23 +63,13 @@ install the following: - A supported Linux kernel version. Please refer to [README.md] for a list of supported versions. - The Open vSwitch datapath requires bridging support - (CONFIG_BRIDGE) to be built as a kernel module. (This is common - in kernels provided by Linux distributions.) The bridge module - must not be loaded or in use. If the bridge module is running - (check with "lsmod | grep bridge"), you must remove it ("rmmod - bridge") before starting the datapath. - For optional support of ingress policing, you must enable kernel configuration options NET_CLS_BASIC, NET_SCH_INGRESS, and NET_ACT_POLICE, either built-in or as modules. (NET_CLS_POLICE is obsolete and not needed.) - To use GRE tunneling on Linux 2.6.37 or newer, kernel support - for GRE demultiplexing (CONFIG_NET_IPGRE_DEMUX) must be compiled - in or available as a module. Also, on kernels before 3.11, the - ip_gre module, for GRE tunnels over IP (NET_IPGRE), must not be - loaded or compiled in. + On kernels before 3.11, the ip_gre module, for GRE tunnels over IP + (NET_IPGRE), must not be loaded or compiled in. To configure HTB or HFSC quality of service with Open vSwitch, you must enable the respective configuration options. @@ -301,23 +291,6 @@ Building the Sources If the `modprobe` operation fails, look at the last few kernel log messages (e.g. with `dmesg | tail`): - - The message "openvswitch: exports duplicate symbol - br_should_route_hook (owned by bridge)" means that the bridge - module is loaded. Run `/sbin/rmmod bridge` to remove it. - - If `/sbin/rmmod bridge` fails with "ERROR: Module bridge does - not exist in /proc/modules", then the bridge is compiled into - the kernel, rather than as a module. Open vSwitch does not - support this configuration (see "Build Requirements", above). - - - The message "openvswitch: exports duplicate symbol - dp_ioctl_hook (owned by ofdatapath)" means that the ofdatapath - module from the OpenFlow reference implementation is loaded. - Run `/sbin/rmmod ofdatapath` to remove it. (You might have to - delete any existing datapaths beforehand, using the "dpctl" - program included with the OpenFlow reference implementation. - "ovs-dpctl" will not work.) - - Otherwise, the most likely problem is that Open vSwitch was built for a kernel different from the one into which you are trying to load it. Run `modinfo` on openvswitch.ko and on @@ -335,18 +308,6 @@ Building the Sources module loading, please include the output from the `dmesg` and `modinfo` commands mentioned above. -There is an optional module parameter to openvswitch.ko called -vlan_tso that enables TCP segmentation offload over VLANs on NICs -that support it. Many drivers do not expose support for TSO on VLANs -in a way that Open vSwitch can use but there is no way to detect -whether this is the case. If you know that your particular driver can -handle it (for example by testing sending large TCP packets over VLANs) -then passing in a value of 1 may improve performance. Modules built for -Linux kernels 2.6.37 and later, as well as specially patched versions -of earlier kernels, do not need this and do not have this parameter. If -you do not understand what this means or do not know if your driver -will work, do not set this. - 6. Initialize the configuration database using ovsdb-tool, e.g.: `% mkdir -p /usr/local/etc/openvswitch` diff --git a/NEWS b/NEWS index 38f6b56a7f2..e612f76e042 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,8 @@ Post-v2.5.0 for 2.7+. - SELinux: * Introduced SELinux policy package. + - Datapath Linux kernel compatibility. + * Dropped support for kernel older than 3.10. v2.5.0 - xx xxx xxxx --------------------- diff --git a/README.md b/README.md index 82065c7d806..69c49128a6b 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,7 @@ vSwitch supports the following features: * Transactional configuration database with C and Python bindings * High-performance forwarding using a Linux kernel module -The included Linux kernel module supports Linux 2.6.32 and up, with -testing focused on 2.6.32 with Centos and Xen patches. Open vSwitch -also has special support for Citrix XenServer and Red Hat Enterprise -Linux hosts. +The included Linux kernel module supports Linux 3.10 and up. Open vSwitch can also operate, at a cost in performance, entirely in userspace, without assistance from a kernel module. This userspace diff --git a/acinclude.m4 b/acinclude.m4 index 11c77877d46..ed8ab78251e 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -139,14 +139,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [ else 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 + elif test "$version" = 3 && test "$patchlevel" -ge 10; then : # Linux 3.x else - if test "$version" -le 1 || test "$patchlevel" -le 5 || test "$sublevel" -le 31; then - AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version 2.6.32 or later is required]) - else - : # Linux 2.6.x - fi + AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version 3.10 or later is required]) fi if (test ! -e "$KBUILD"/include/linux/version.h && \ test ! -e "$KBUILD"/include/generated/uapi/linux/version.h)|| \ @@ -307,7 +303,7 @@ AC_DEFUN([OVS_DEFINE], [ dnl OVS_CHECK_LINUX_COMPAT dnl -dnl Runs various Autoconf checks on the Linux 2.6 kernel source in +dnl Runs various Autoconf checks on the Linux kernel source in dnl the directory in $KBUILD. AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ rm -f datapath/linux/kcompat.h.new @@ -381,11 +377,10 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [can_checksum_protocol]) OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [ndo_get_iflink]) 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/netdevice.h], [netdev_rx_handler_register]) - 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])]) + dnl Ubuntu kernel 3.13 has defined this struct but not used for netdev->tstats. + dnl So check type of tstats. + OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [pcpu_sw_netstats.*tstats], + [OVS_DEFINE([HAVE_PCPU_SW_NETSTATS])]) 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/netdevice.h], [udp_offload]) @@ -530,8 +525,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_GREP_IFELSE([$KSRC/include/linux/u64_stats_sync.h], [u64_stats_fetch_begin_irq]) - OVS_GREP_IFELSE([$KSRC/include/linux/openvswitch.h], [openvswitch_handle_frame_hook], - [OVS_DEFINE([HAVE_RHEL_OVS_HOOK])]) OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [struct vxlan_metadata], [OVS_DEFINE([HAVE_VXLAN_METADATA])]) OVS_GREP_IFELSE([$KSRC/include/net/vxlan.h], [VXLAN_HF_RCO]) diff --git a/datapath/actions.c b/datapath/actions.c index 20413c950f3..dcf8591b0f5 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -41,7 +41,6 @@ #include "datapath.h" #include "conntrack.h" #include "gso.h" -#include "vlan.h" #include "vport.h" static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, @@ -68,9 +67,7 @@ struct ovs_frag_data { u8 l2_data[MAX_L2_LEN]; }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) static DEFINE_PER_CPU(struct ovs_frag_data, ovs_frag_data_storage); -#endif #define DEFERRED_ACTION_FIFO_SIZE 10 struct action_fifo { @@ -149,7 +146,7 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, struct ethhdr *hdr; /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ - if (skb_encapsulation(skb)) + if (skb->encapsulation) return -ENOTSUPP; if (skb_cow_head(skb, MPLS_HLEN) < 0) @@ -302,14 +299,14 @@ static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh, if (nh->protocol == IPPROTO_TCP) { if (likely(transport_len >= sizeof(struct tcphdr))) inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb, - addr, new_addr, 1); + addr, new_addr, true); } else if (nh->protocol == IPPROTO_UDP) { if (likely(transport_len >= sizeof(struct udphdr))) { struct udphdr *uh = udp_hdr(skb); if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { inet_proto_csum_replace4(&uh->check, skb, - addr, new_addr, 1); + addr, new_addr, true); if (!uh->check) uh->check = CSUM_MANGLED_0; } @@ -335,14 +332,14 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto, if (l4_proto == NEXTHDR_TCP) { if (likely(transport_len >= sizeof(struct tcphdr))) inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb, - addr, new_addr, 1); + addr, new_addr, true); } else if (l4_proto == NEXTHDR_UDP) { if (likely(transport_len >= sizeof(struct udphdr))) { struct udphdr *uh = udp_hdr(skb); if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { inet_proto_csum_replace16(&uh->check, skb, - addr, new_addr, 1); + addr, new_addr, true); if (!uh->check) uh->check = CSUM_MANGLED_0; } @@ -350,7 +347,7 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto, } else if (l4_proto == NEXTHDR_ICMP) { if (likely(transport_len >= sizeof(struct icmp6hdr))) inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum, - skb, addr, new_addr, 1); + skb, addr, new_addr, true); } } @@ -518,7 +515,7 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key, static void set_tp_port(struct sk_buff *skb, __be16 *port, __be16 new_port, __sum16 *check) { - inet_proto_csum_replace2(check, skb, *port, new_port, 0); + inet_proto_csum_replace2(check, skb, *port, new_port, false); *port = new_port; } @@ -625,7 +622,6 @@ static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key, return 0; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) static int ovs_vport_output(OVS_VPORT_OUTPUT_PARAMS) { struct ovs_frag_data *data = get_pcpu_ptr(ovs_frag_data_storage); @@ -740,16 +736,6 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru, err: kfree_skb(skb); } -#else /* < 3.10 */ -static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru, - __be16 ethertype) -{ - WARN_ONCE(1, "Fragment unavailable ->%s: eth=%04x, MRU=%d, MTU=%d.", - ovs_vport_name(vport), ntohs(ethertype), mru, - vport->dev->mtu); - kfree_skb(skb); -} -#endif static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, struct sw_flow_key *key) diff --git a/datapath/compat.h b/datapath/compat.h index 0e19051fb09..8bf779f5f20 100644 --- a/datapath/compat.h +++ b/datapath/compat.h @@ -27,33 +27,14 @@ #include #include +/* Even though vanilla 3.10 kernel has grp->id, RHEL 7 kernel is missing + * this field. */ #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) -#define rt_dst(rt) (rt->dst) -#else -#define rt_dst(rt) (rt->u.dst) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#define inet_sport(sk) (inet_sk(sk)->sport) -#else -#define inet_sport(sk) (inet_sk(sk)->inet_sport) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -static inline bool skb_encapsulation(struct sk_buff *skb) -{ - return skb->encapsulation; -} -#else -#define skb_encapsulation(skb) false -#endif - #ifdef OVS_FRAGMENT_BACKPORT #ifdef HAVE_NF_IPV6_OPS_FRAGMENT static inline int __init ip6_output_init(void) { return 0; } diff --git a/datapath/conntrack.c b/datapath/conntrack.c index 795ed91056b..0338f9f0c93 100644 --- a/datapath/conntrack.c +++ b/datapath/conntrack.c @@ -14,8 +14,7 @@ #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) && \ - IS_ENABLED(CONFIG_NF_CONNTRACK) +#if IS_ENABLED(CONFIG_NF_CONNTRACK) #include #include @@ -799,4 +798,4 @@ void ovs_ct_exit(struct net *net) nf_connlabels_put(net); } -#endif /* CONFIG_NF_CONNTRACK && LINUX > 3.10 */ +#endif /* CONFIG_NF_CONNTRACK */ diff --git a/datapath/conntrack.h b/datapath/conntrack.h index 90b91be39fd..8a849e84488 100644 --- a/datapath/conntrack.h +++ b/datapath/conntrack.h @@ -20,7 +20,7 @@ struct ovs_conntrack_info; enum ovs_key_attr; -#if IS_ENABLED(CONFIG_NF_CONNTRACK) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#if IS_ENABLED(CONFIG_NF_CONNTRACK) void ovs_ct_init(struct net *); void ovs_ct_exit(struct net *); bool ovs_ct_verify(struct net *, enum ovs_key_attr attr); diff --git a/datapath/datapath.c b/datapath/datapath.c index e3d3c8ca2c3..5bec072d930 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -58,7 +58,6 @@ #include "flow_table.h" #include "flow_netlink.h" #include "gso.h" -#include "vlan.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -450,12 +449,10 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, if (!nskb) return -ENOMEM; - nskb = vlan_insert_tag_set_proto(nskb, nskb->vlan_proto, skb_vlan_tag_get(nskb)); + nskb = __vlan_hwaccel_push_inside(nskb); if (!nskb) return -ENOMEM; - vlan_set_tci(nskb, 0); - skb = nskb; } @@ -2316,8 +2313,6 @@ static struct pernet_operations ovs_net_ops = { .size = sizeof(struct ovs_net), }; -DEFINE_COMPAT_PNET_REG_FUNC(device); - static int __init dp_init(void) { int err; diff --git a/datapath/datapath.h b/datapath/datapath.h index ce5b82a650b..ceb3372432c 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -31,7 +31,6 @@ #include "compat.h" #include "flow.h" #include "flow_table.h" -#include "vlan.h" #define DP_MAX_PORTS USHRT_MAX #define DP_VPORT_HASH_BUCKETS 1024 diff --git a/datapath/flow.c b/datapath/flow.c index 057dde1f6dc..c97c9c9e516 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -50,7 +50,6 @@ #include "flow.h" #include "flow_netlink.h" #include "vport.h" -#include "vlan.h" u64 ovs_flow_used_time(unsigned long flow_jiffies) { @@ -477,7 +476,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) key->eth.tci = 0; if (skb_vlan_tag_present(skb)) - key->eth.tci = htons(vlan_get_tci(skb)); + key->eth.tci = htons(skb->vlan_tci); else if (eth->h_proto == htons(ETH_P_8021Q)) if (unlikely(parse_vlan(skb, key))) return -ENOMEM; diff --git a/datapath/flow_table.c b/datapath/flow_table.c index b51be69e8d9..dd77922d695 100644 --- a/datapath/flow_table.c +++ b/datapath/flow_table.c @@ -44,7 +44,6 @@ #include #include -#include "vlan.h" #include "flow_netlink.h" #define TBL_MIN_BUCKETS 1024 @@ -168,13 +167,6 @@ static void rcu_free_flow_callback(struct rcu_head *rcu) flow_free(flow); } -static void rcu_free_sw_flow_mask_cb(struct rcu_head *rcu) -{ - struct sw_flow_mask *mask = container_of(rcu, struct sw_flow_mask, rcu); - - kfree(mask); -} - void ovs_flow_free(struct sw_flow *flow, bool deferred) { if (!flow) @@ -774,7 +766,7 @@ static void tbl_mask_array_delete_mask(struct mask_array *ma, if (mask == ovsl_dereference(ma->masks[i])) { RCU_INIT_POINTER(ma->masks[i], NULL); ma->count--; - call_rcu(&mask->rcu, rcu_free_sw_flow_mask_cb); + kfree_rcu(mask, rcu); return; } } diff --git a/datapath/linux/compat/dev-openvswitch.c b/datapath/linux/compat/dev-openvswitch.c index d7d4224a1cb..0d2088b38f3 100644 --- a/datapath/linux/compat/dev-openvswitch.c +++ b/datapath/linux/compat/dev-openvswitch.c @@ -34,67 +34,6 @@ void dev_disable_lro(struct net_device *dev) { } #endif /* HAVE_DEV_DISABLE_LRO */ -#if !defined HAVE_NETDEV_RX_HANDLER_REGISTER || \ - defined HAVE_RHEL_OVS_HOOK - -static int nr_bridges; - -#ifdef HAVE_RHEL_OVS_HOOK -int rpl_netdev_rx_handler_register(struct net_device *dev, - openvswitch_handle_frame_hook_t *hook, - void *rx_handler_data) -{ - nr_bridges++; - rcu_assign_pointer(dev->ax25_ptr, rx_handler_data); - - if (nr_bridges == 1) - rcu_assign_pointer(openvswitch_handle_frame_hook, hook); - return 0; -} -EXPORT_SYMBOL_GPL(rpl_netdev_rx_handler_register); -#else - -int rpl_netdev_rx_handler_register(struct net_device *dev, - struct sk_buff *(*hook)(struct net_bridge_port *p, - struct sk_buff *skb), - void *rx_handler_data) -{ - nr_bridges++; - if (dev->br_port) - return -EBUSY; - - rcu_assign_pointer(dev->br_port, rx_handler_data); - - if (nr_bridges == 1) - br_handle_frame_hook = hook; - return 0; -} -EXPORT_SYMBOL_GPL(rpl_netdev_rx_handler_register); -#endif - -void rpl_netdev_rx_handler_unregister(struct net_device *dev) -{ - nr_bridges--; -#ifdef HAVE_RHEL_OVS_HOOK - rcu_assign_pointer(dev->ax25_ptr, NULL); - - if (nr_bridges) - return; - - rcu_assign_pointer(openvswitch_handle_frame_hook, NULL); -#else - rcu_assign_pointer(dev->br_port, NULL); - - if (nr_bridges) - return; - - br_handle_frame_hook = NULL; -#endif -} -EXPORT_SYMBOL_GPL(rpl_netdev_rx_handler_unregister); - -#endif - int rpl_rtnl_delete_link(struct net_device *dev) { const struct rtnl_link_ops *ops; diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c index 92feeef0900..0399de70663 100644 --- a/datapath/linux/compat/geneve.c +++ b/datapath/linux/compat/geneve.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -125,9 +126,7 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) struct genevehdr *gnvh = geneve_hdr(skb); struct metadata_dst *tun_dst; struct geneve_dev *geneve = NULL; -#ifdef HAVE_DEV_TSTATS struct pcpu_sw_netstats *stats; -#endif struct iphdr *iph; u8 *vni; __be32 addr; @@ -200,13 +199,11 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) } } -#ifdef HAVE_DEV_TSTATS stats = this_cpu_ptr((struct pcpu_sw_netstats __percpu *)geneve->dev->tstats); u64_stats_update_begin(&stats->syncp); stats->rx_packets++; stats->rx_bytes += skb->len; u64_stats_update_end(&stats->syncp); -#endif netdev_port_receive(skb, &tun_dst->u.tun_info); return; drop: @@ -214,7 +211,6 @@ static void geneve_rx(struct geneve_sock *gs, struct sk_buff *skb) kfree_skb(skb); } -#ifdef HAVE_DEV_TSTATS /* Setup stats when device is created */ static int geneve_init(struct net_device *dev) { @@ -229,7 +225,6 @@ static void geneve_uninit(struct net_device *dev) { free_percpu(dev->tstats); } -#endif /* Callback from net/ipv4/udp.c to receive packets */ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb) @@ -495,7 +490,7 @@ static struct geneve_sock *geneve_find_sock(struct geneve_net *gn, struct geneve_sock *gs; list_for_each_entry(gs, &gn->sock_list, list) { - if (inet_sport(gs->sock->sk) == dst_port && + if (inet_sk(gs->sock->sk)->inet_sport == dst_port && inet_sk(gs->sock->sk)->sk.sk_family == AF_INET) { return gs; } @@ -549,7 +544,7 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, int min_headroom; int err; - min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr) + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); err = skb_cow_head(skb, min_headroom); @@ -623,7 +618,7 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb, dev->stats.tx_carrier_errors++; return rt; } - if (rt_dst(rt).dev == dev) { /* is this necessary? */ + if (rt->dst.dev == dev) { /* is this necessary? */ netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr); dev->stats.collisions++; ip_rt_put(rt); @@ -712,7 +707,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb) ttl = geneve->ttl; if (!ttl && IN_MULTICAST(ntohl(fl4.daddr))) ttl = 1; - ttl = ttl ? : ip4_dst_hoplimit(&rt_dst(rt)); + ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); df = 0; } err = udp_tunnel_xmit_skb(rt, gs->sock->sk, skb, fl4.saddr, fl4.daddr, @@ -771,11 +766,9 @@ static int geneve_change_mtu(struct net_device *dev, int new_mtu) } static const struct net_device_ops geneve_netdev_ops = { -#ifdef HAVE_DEV_TSTATS .ndo_init = geneve_init, .ndo_uninit = geneve_uninit, .ndo_get_stats64 = ip_tunnel_get_stats64, -#endif .ndo_open = geneve_open, .ndo_stop = geneve_stop, .ndo_start_xmit = geneve_dev_xmit, @@ -1118,7 +1111,6 @@ static struct pernet_operations geneve_net_ops = { .size = sizeof(struct geneve_net), }; -DEFINE_COMPAT_PNET_REG_FUNC(device) int rpl_geneve_init_module(void) { int rc; diff --git a/datapath/linux/compat/gso.c b/datapath/linux/compat/gso.c index c52b2b13606..fb4749a7e8a 100644 --- a/datapath/linux/compat/gso.c +++ b/datapath/linux/compat/gso.c @@ -39,18 +39,6 @@ #include #include "gso.h" -#include "vlan.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) && \ - !defined(HAVE_VLAN_BUG_WORKAROUND) -#include - -static int vlan_tso __read_mostly; -module_param(vlan_tso, int, 0644); -MODULE_PARM_DESC(vlan_tso, "Enable TSO for VLAN packets"); -#else -#define vlan_tso true -#endif #ifdef OVS_USE_COMPAT_GSO_SEGMENTATION static bool dev_supports_vlan_tx(struct net_device *dev) @@ -106,15 +94,11 @@ int rpl_dev_queue_xmit(struct sk_buff *skb) features = netif_skb_features(skb); if (vlan) { - if (!vlan_tso) - features &= ~(NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_UFO | NETIF_F_FSO); - skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, skb_vlan_tag_get(skb)); if (unlikely(!skb)) return err; - vlan_set_tci(skb, 0); + skb->vlan_tci = 0; } /* As of v3.11 the kernel provides an mpls_features field in diff --git a/datapath/linux/compat/include/linux/netdevice.h b/datapath/linux/compat/include/linux/netdevice.h index 19a7b8ef53d..e9fa9957906 100644 --- a/datapath/linux/compat/include/linux/netdevice.h +++ b/datapath/linux/compat/include/linux/netdevice.h @@ -49,30 +49,6 @@ struct net; extern void dev_disable_lro(struct net_device *dev); #endif -#if !defined HAVE_NETDEV_RX_HANDLER_REGISTER || \ - defined HAVE_RHEL_OVS_HOOK - -#ifdef HAVE_RHEL_OVS_HOOK -typedef struct sk_buff *(openvswitch_handle_frame_hook_t)(struct sk_buff *skb); -extern openvswitch_handle_frame_hook_t *openvswitch_handle_frame_hook; - -#define netdev_rx_handler_register rpl_netdev_rx_handler_register -int rpl_netdev_rx_handler_register(struct net_device *dev, - openvswitch_handle_frame_hook_t *hook, - void *rx_handler_data); -#else - -#define netdev_rx_handler_register rpl_netdev_rx_handler_register -int rpl_netdev_rx_handler_register(struct net_device *dev, - struct sk_buff *(*netdev_hook)(struct net_bridge_port *p, - struct sk_buff *skb), - void *rx_handler_data); -#endif - -#define netdev_rx_handler_unregister rpl_netdev_rx_handler_unregister -void rpl_netdev_rx_handler_unregister(struct net_device *dev); -#endif - #ifndef HAVE_DEV_GET_BY_INDEX_RCU static inline struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex) { @@ -166,16 +142,7 @@ 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; -}; +#define pcpu_sw_netstats pcpu_tstats #endif #if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(8,0) @@ -258,12 +225,6 @@ static inline void *skb_gro_remcsum_process(struct sk_buff *skb, void *ptr, #define dev_get_stats rpl_dev_get_stats struct rtnl_link_stats64 *rpl_dev_get_stats(struct net_device *dev, struct rtnl_link_stats64 *storage); - -#else -#define HAVE_DEV_TSTATS -#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) -#undef HAVE_DEV_TSTATS -#endif #endif #if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) diff --git a/datapath/linux/compat/include/net/net_namespace.h b/datapath/linux/compat/include/net/net_namespace.h index 9f508721639..427072249c6 100644 --- a/datapath/linux/compat/include/net/net_namespace.h +++ b/datapath/linux/compat/include/net/net_namespace.h @@ -3,57 +3,6 @@ #include_next -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -/* for 2.6.32* */ -struct rpl_pernet_operations { - int (*init)(struct net *net); - void (*exit)(struct net *net); - int *id; - size_t size; - struct pernet_operations ops; -}; -#define pernet_operations rpl_pernet_operations - -#define register_pernet_device rpl_register_pernet_gen_device -#define unregister_pernet_device rpl_unregister_pernet_gen_device - -#define register_pernet_subsys rpl_register_pernet_gen_device -#define unregister_pernet_subsys rpl_unregister_pernet_gen_device - -#define compat_init_net ovs_compat_init_net -int ovs_compat_init_net(struct net *net, struct rpl_pernet_operations *pnet); -#define compat_exit_net ovs_compat_exit_net -void ovs_compat_exit_net(struct net *net, struct rpl_pernet_operations *pnet); - -#define DEFINE_COMPAT_PNET_REG_FUNC(TYPE) \ - \ -static struct rpl_pernet_operations *pnet_gen_##TYPE; \ -static int compat_init_net_gen_##TYPE(struct net *net) \ -{ \ - return compat_init_net(net, pnet_gen_##TYPE); \ -} \ - \ -static void compat_exit_net_gen_##TYPE(struct net *net) \ -{ \ - compat_exit_net(net, pnet_gen_##TYPE); \ -} \ - \ -static int rpl_register_pernet_gen_##TYPE(struct rpl_pernet_operations *rpl_pnet) \ -{ \ - pnet_gen_##TYPE = rpl_pnet; \ - rpl_pnet->ops.init = compat_init_net_gen_##TYPE; \ - rpl_pnet->ops.exit = compat_exit_net_gen_##TYPE; \ - return register_pernet_gen_##TYPE(pnet_gen_##TYPE->id, &rpl_pnet->ops); \ -} \ - \ -static void rpl_unregister_pernet_gen_##TYPE(struct rpl_pernet_operations *rpl_pnet) \ -{ \ - unregister_pernet_gen_##TYPE(*pnet_gen_##TYPE->id, &rpl_pnet->ops); \ -} -#else -#define DEFINE_COMPAT_PNET_REG_FUNC(TYPE) -#endif /* 2.6.33 */ - #ifndef HAVE_POSSIBLE_NET_T typedef struct { #ifdef CONFIG_NET_NS diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h index b50cd171c11..75a5a7acdf8 100644 --- a/datapath/linux/compat/include/net/vxlan.h +++ b/datapath/linux/compat/include/net/vxlan.h @@ -220,7 +220,7 @@ struct net_device *rpl_vxlan_dev_create(struct net *net, const char *name, static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan) { - return inet_sport(vxlan->vn_sock->sock->sk); + return inet_sk(vxlan->vn_sock->sock->sk)->inet_sport; } static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, @@ -228,7 +228,7 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, { u8 l4_hdr = 0; - if (!skb_encapsulation(skb)) + if (!skb->encapsulation) return features; switch (vlan_get_protocol(skb)) { diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index f6a841fbc4d..2e138434871 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -289,7 +289,7 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb) tunnel_hlen = ip_gre_calc_hlen(key->tun_flags); - min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + tunnel_hlen + sizeof(struct iphdr) + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { @@ -647,8 +647,6 @@ static struct pernet_operations ipgre_tap_net_ops = { .size = sizeof(struct ip_tunnel_net), }; -DEFINE_COMPAT_PNET_REG_FUNC(device); - int rpl_ipgre_init(void) { int err; diff --git a/datapath/linux/compat/ip_tunnel.c b/datapath/linux/compat/ip_tunnel.c index 81909370271..b3b4fde0e68 100644 --- a/datapath/linux/compat/ip_tunnel.c +++ b/datapath/linux/compat/ip_tunnel.c @@ -113,7 +113,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) rt = ip_route_output_key(tunnel->net, &fl4); if (!IS_ERR(rt)) { - tdev = rt_dst(rt).dev; + tdev = rt->dst.dev; ip_rt_put(rt); } if (dev->type != ARPHRD_ETHER) @@ -164,9 +164,7 @@ int rpl_ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) static void ip_tunnel_dev_free(struct net_device *dev) { -#ifdef HAVE_DEV_TSTATS free_percpu(dev->tstats); -#endif free_netdev(dev); } @@ -261,11 +259,9 @@ int rpl_ip_tunnel_init(struct net_device *dev) struct iphdr *iph = &tunnel->parms.iph; dev->destructor = ip_tunnel_dev_free; -#ifdef HAVE_DEV_TSTATS dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; -#endif tunnel->dev = dev; tunnel->net = dev_net(dev); strcpy(tunnel->parms.name, dev->name); diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c index 179fa47b255..0858d028f7a 100644 --- a/datapath/linux/compat/ip_tunnels_core.c +++ b/datapath/linux/compat/ip_tunnels_core.c @@ -19,6 +19,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -48,7 +49,7 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, skb_scrub_packet(skb, xnet); skb_clear_hash(skb); - skb_dst_set(skb, &rt_dst(rt)); + skb_dst_set(skb, &rt->dst); #if 0 /* Do not clear ovs_skb_cb. It will be done in gso code. */ @@ -71,7 +72,7 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, iph->ttl = ttl; #ifdef HAVE_IP_SELECT_IDENT_USING_DST_ENTRY - __ip_select_ident(iph, &rt_dst(rt), (skb_shinfo(skb)->gso_segs ?: 1) - 1); + __ip_select_ident(iph, &rt->dst, (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); @@ -167,7 +168,7 @@ int rpl_iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_prot secpath_reset(skb); skb_clear_hash(skb); skb_dst_drop(skb); - vlan_set_tci(skb, 0); + skb->vlan_tci = 0; skb_set_queue_mapping(skb, 0); skb->pkt_type = PACKET_HOST; return 0; @@ -181,7 +182,7 @@ bool ovs_skb_is_encapsulated(struct sk_buff *skb) /* checking for inner protocol should be sufficient on newer kernel, but * old kernel just set encapsulation bit. */ - return ovs_skb_get_inner_protocol(skb) || skb_encapsulation(skb); + return ovs_skb_get_inner_protocol(skb) || skb->encapsulation; } EXPORT_SYMBOL_GPL(ovs_skb_is_encapsulated); diff --git a/datapath/linux/compat/lisp.c b/datapath/linux/compat/lisp.c index fa6da6c9b17..f1f50aea581 100644 --- a/datapath/linux/compat/lisp.c +++ b/datapath/linux/compat/lisp.c @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -310,7 +311,7 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb) goto error; } - min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + sizeof(struct iphdr) + LISP_HLEN; if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { @@ -327,7 +328,7 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb) /* Reset l2 headers. */ skb_pull(skb, network_offset); skb_reset_mac_header(skb); - vlan_set_tci(skb, 0); + skb->vlan_tci = 0; skb = udp_tunnel_handle_offloads(skb, false, 0, false); if (IS_ERR(skb)) { @@ -362,7 +363,6 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb) } EXPORT_SYMBOL(rpl_lisp_xmit); -#ifdef HAVE_DEV_TSTATS /* Setup stats when device is created */ static int lisp_init(struct net_device *dev) { @@ -377,7 +377,6 @@ static void lisp_uninit(struct net_device *dev) { free_percpu(dev->tstats); } -#endif static struct socket *create_sock(struct net *net, bool ipv6, __be16 port) @@ -458,11 +457,9 @@ static int lisp_change_mtu(struct net_device *dev, int new_mtu) } static const struct net_device_ops lisp_netdev_ops = { -#ifdef HAVE_DEV_TSTATS .ndo_init = lisp_init, .ndo_uninit = lisp_uninit, .ndo_get_stats64 = ip_tunnel_get_stats64, -#endif .ndo_open = lisp_open, .ndo_stop = lisp_stop, .ndo_start_xmit = lisp_dev_xmit, @@ -697,7 +694,6 @@ static struct pernet_operations lisp_net_ops = { .size = sizeof(struct lisp_net), }; -DEFINE_COMPAT_PNET_REG_FUNC(device) int rpl_lisp_init_module(void) { int rc; diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index 769b76f53ac..4faa18f3ee8 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -199,7 +199,7 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, flags &= VXLAN_F_RCV_FLAGS; hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { - if (inet_sport(vs->sock->sk) == port && + if (inet_sk(vs->sock->sk)->inet_sport == port && vxlan_get_sk_family(vs) == family && vs->flags == flags) return vs; @@ -819,9 +819,7 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, struct iphdr *oip = NULL; struct ipv6hdr *oip6 = NULL; struct vxlan_dev *vxlan; -#ifdef HAVE_DEV_TSTATS struct pcpu_sw_netstats *stats; -#endif union vxlan_addr saddr; int err = 0; @@ -885,13 +883,11 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, } } -#ifdef HAVE_DEV_TSTATS stats = this_cpu_ptr((struct pcpu_sw_netstats __percpu *)vxlan->dev->tstats); u64_stats_update_begin(&stats->syncp); stats->rx_packets++; stats->rx_bytes += skb->len; u64_stats_update_end(&stats->syncp); -#endif netdev_port_receive(skb, skb_tunnel_info(skb)); return; drop: @@ -1152,7 +1148,7 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk } } - min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len + min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len + VXLAN_HLEN + sizeof(struct iphdr) + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); @@ -1306,7 +1302,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - if (rt_dst(rt).dev == dev) { + if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to %pI4\n", &dst->sin.sin_addr.s_addr); dev->stats.collisions++; @@ -1330,7 +1326,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } tos = ip_tunnel_ecn_encap(tos, old_iph, skb); - ttl = ttl ? : ip4_dst_hoplimit(&rt_dst(rt)); + ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); err = vxlan_xmit_skb(rt, sk, skb, fl4.saddr, dst->sin.sin_addr.s_addr, tos, ttl, df, src_port, dst_port, htonl(vni << 8), md, @@ -1500,7 +1496,6 @@ static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) } /* Setup stats when device is created */ -#ifdef HAVE_DEV_TSTATS static int vxlan_init(struct net_device *dev) { dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); @@ -1509,7 +1504,6 @@ static int vxlan_init(struct net_device *dev) return 0; } -#endif static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan) { @@ -1522,7 +1516,6 @@ static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan) spin_unlock_bh(&vxlan->hash_lock); } -#ifdef HAVE_DEV_TSTATS static void vxlan_uninit(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); @@ -1531,7 +1524,6 @@ static void vxlan_uninit(struct net_device *dev) free_percpu(dev->tstats); } -#endif /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) @@ -1657,11 +1649,9 @@ static netdev_tx_t vxlan_dev_xmit(struct sk_buff *skb, struct net_device *dev) } static const struct net_device_ops vxlan_netdev_ops = { -#ifdef HAVE_DEV_TSTATS .ndo_init = vxlan_init, .ndo_uninit = vxlan_uninit, .ndo_get_stats64 = ip_tunnel_get_stats64, -#endif .ndo_open = vxlan_open, .ndo_stop = vxlan_stop, .ndo_start_xmit = vxlan_dev_xmit, @@ -2206,7 +2196,6 @@ static struct pernet_operations vxlan_net_ops = { .size = sizeof(struct vxlan_net), }; -DEFINE_COMPAT_PNET_REG_FUNC(device) int rpl_vxlan_init_module(void) { int rc; diff --git a/datapath/vlan.h b/datapath/vlan.h deleted file mode 100644 index 13ae6a7e371..00000000000 --- a/datapath/vlan.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2007-2011 Nicira, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA - */ - -#ifndef VLAN_H -#define VLAN_H 1 - -#include -#include -#include - -/** - * DOC: VLAN tag manipulation. - * - * &struct sk_buff handling of VLAN tags has evolved over time: - * - * In 2.6.26 and earlier, VLAN tags did not have any generic representation in - * an skb, other than as a raw 802.1Q header inside the packet data. - * - * In 2.6.27 &struct sk_buff added a @vlan_tci member. Between 2.6.27 and - * 2.6.32, its value was the raw contents of the 802.1Q TCI field, or zero if - * no 802.1Q header was present. This worked OK except for the corner case of - * an 802.1Q header with an all-0-bits TCI, which could not be represented. - * - * In 2.6.33, @vlan_tci semantics changed. Now, if an 802.1Q header is - * present, then the VLAN_TAG_PRESENT bit is always set. This fixes the - * all-0-bits TCI corner case. - * - * For compatibility we emulate the 2.6.33+ behavior on earlier kernel - * versions. The client must not access @vlan_tci directly. Instead, use - * vlan_get_tci() to read it or vlan_set_tci() to write it, with semantics - * equivalent to those on 2.6.33+. - */ - -static inline u16 vlan_get_tci(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - if (skb->vlan_tci) - return skb->vlan_tci | VLAN_TAG_PRESENT; -#endif - return skb->vlan_tci; -} - -static inline void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - vlan_tci &= ~VLAN_TAG_PRESENT; -#endif - skb->vlan_tci = vlan_tci; -} -#endif /* vlan.h */ diff --git a/datapath/vport-geneve.c b/datapath/vport-geneve.c index 392d7503ab2..e65e43dd9c7 100644 --- a/datapath/vport-geneve.c +++ b/datapath/vport-geneve.c @@ -34,7 +34,7 @@ static struct vport_ops ovs_geneve_vport_ops; * @dst_port: destination port. */ struct geneve_port { - u16 port_no; + u16 dst_port; }; static inline struct geneve_port *geneve_vport(const struct vport *vport) @@ -47,7 +47,7 @@ static int geneve_get_options(const struct vport *vport, { struct geneve_port *geneve_port = geneve_vport(vport); - if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->port_no)) + if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->dst_port)) return -EMSGSIZE; return 0; } @@ -57,7 +57,7 @@ static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, { struct geneve_port *geneve_port = geneve_vport(vport); struct net *net = ovs_dp_get_net(vport->dp); - __be16 dport = htons(geneve_port->port_no); + __be16 dport = htons(geneve_port->dst_port); __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true); return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), @@ -95,7 +95,7 @@ static struct vport *geneve_tnl_create(const struct vport_parms *parms) return vport; geneve_port = geneve_vport(vport); - geneve_port->port_no = dst_port; + geneve_port->dst_port = dst_port; rtnl_lock(); dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port); diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c index 7f216792bff..ec76398a792 100644 --- a/datapath/vport-internal_dev.c +++ b/datapath/vport-internal_dev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2015 Nicira, Inc. + * Copyright (c) 2007-2012 Nicira, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include @@ -57,16 +54,12 @@ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) rcu_read_unlock(); if (likely(!err)) { -#ifdef HAVE_DEV_TSTATS - struct pcpu_sw_netstats *tstats; - - tstats = this_cpu_ptr((struct pcpu_sw_netstats __percpu *)netdev->tstats); + struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev->tstats); u64_stats_update_begin(&tstats->syncp); tstats->tx_bytes += len; tstats->tx_packets++; u64_stats_update_end(&tstats->syncp); -#endif } else { netdev->stats.tx_errors++; } @@ -94,14 +87,6 @@ static void internal_dev_getinfo(struct net_device *netdev, static const struct ethtool_ops internal_dev_ethtool_ops = { .get_drvinfo = internal_dev_getinfo, .get_link = ethtool_op_get_link, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_hw_csum, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, -#endif }; static int internal_dev_change_mtu(struct net_device *netdev, int new_mtu) @@ -121,32 +106,45 @@ static void internal_dev_destructor(struct net_device *dev) free_netdev(dev); } -#ifdef HAVE_DEV_TSTATS -static int internal_dev_init(struct net_device *dev) +static struct rtnl_link_stats64 * +internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) { - dev->tstats = (typeof(dev->tstats)) netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); - if (!dev->tstats) - return -ENOMEM; - return 0; -} + int i; + + memset(stats, 0, sizeof(*stats)); + stats->rx_errors = dev->stats.rx_errors; + stats->tx_errors = dev->stats.tx_errors; + stats->tx_dropped = dev->stats.tx_dropped; + stats->rx_dropped = dev->stats.rx_dropped; + + for_each_possible_cpu(i) { + const struct pcpu_sw_netstats *percpu_stats; + struct pcpu_sw_netstats local_stats; + unsigned int start; + + percpu_stats = per_cpu_ptr(dev->tstats, i); + + do { + start = u64_stats_fetch_begin_irq(&percpu_stats->syncp); + local_stats = *percpu_stats; + } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start)); + + stats->rx_bytes += local_stats.rx_bytes; + stats->rx_packets += local_stats.rx_packets; + stats->tx_bytes += local_stats.tx_bytes; + stats->tx_packets += local_stats.tx_packets; + } -static void internal_dev_uninit(struct net_device *dev) -{ - free_percpu(dev->tstats); + return stats; } -#endif static const struct net_device_ops internal_dev_netdev_ops = { -#ifdef HAVE_DEV_TSTATS - .ndo_init = internal_dev_init, - .ndo_uninit = internal_dev_uninit, - .ndo_get_stats64 = ip_tunnel_get_stats64, -#endif .ndo_open = internal_dev_open, .ndo_stop = internal_dev_stop, .ndo_start_xmit = internal_dev_xmit, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = internal_dev_change_mtu, + .ndo_get_stats64 = internal_get_stats, }; static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { @@ -171,14 +169,10 @@ static void do_setup(struct net_device *netdev) NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL; netdev->vlan_features = netdev->features; - netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) netdev->hw_enc_features = netdev->features; -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) + netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; netdev->hw_features = netdev->features & ~NETIF_F_LLTX; -#endif + eth_hw_addr_random(netdev); } @@ -200,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) err = -ENOMEM; goto error_free_vport; } + vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); + if (!vport->dev->tstats) { + err = -ENOMEM; + goto error_free_netdev; + } dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); internal_dev = internal_dev_priv(vport->dev); @@ -212,7 +211,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) rtnl_lock(); err = register_netdevice(vport->dev); if (err) - goto error_free_netdev; + goto error_unlock; dev_set_promiscuity(vport->dev, 1); rtnl_unlock(); @@ -220,8 +219,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) return vport; -error_free_netdev: +error_unlock: rtnl_unlock(); + free_percpu(vport->dev->tstats); +error_free_netdev: free_netdev(vport->dev); error_free_vport: ovs_vport_free(vport); @@ -237,16 +238,14 @@ static void internal_dev_destroy(struct vport *vport) /* unregister_netdevice() waits for an RCU grace period. */ unregister_netdevice(vport->dev); - + free_percpu(vport->dev->tstats); rtnl_unlock(); } static netdev_tx_t internal_dev_recv(struct sk_buff *skb) { struct net_device *netdev = skb->dev; -#ifdef HAVE_DEV_TSTATS struct pcpu_sw_netstats *stats; -#endif if (unlikely(!(netdev->flags & IFF_UP))) { kfree_skb(skb); @@ -254,22 +253,6 @@ static netdev_tx_t internal_dev_recv(struct sk_buff *skb) return NETDEV_TX_OK; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - if (skb_vlan_tag_present(skb)) { - if (unlikely(!vlan_insert_tag_set_proto(skb, - skb->vlan_proto, - skb_vlan_tag_get(skb)))) - return NETDEV_TX_OK; - - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->csum = csum_add(skb->csum, - csum_partial(skb->data + (2 * ETH_ALEN), - VLAN_HLEN, 0)); - - vlan_set_tci(skb, 0); - } -#endif - skb_dst_drop(skb); nf_reset(skb); secpath_reset(skb); @@ -278,13 +261,11 @@ static netdev_tx_t internal_dev_recv(struct sk_buff *skb) skb->protocol = eth_type_trans(skb, netdev); skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); -#ifdef HAVE_DEV_TSTATS - stats = this_cpu_ptr((struct pcpu_sw_netstats __percpu *)netdev->tstats); + stats = this_cpu_ptr(netdev->tstats); u64_stats_update_begin(&stats->syncp); stats->rx_packets++; stats->rx_bytes += skb->len; u64_stats_update_end(&stats->syncp); -#endif netif_rx(skb); return NETDEV_TX_OK; diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c index a1df79b2b9d..ddd3f5c56e4 100644 --- a/datapath/vport-netdev.c +++ b/datapath/vport-netdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2015 Nicira, Inc. + * Copyright (c) 2007-2012 Nicira, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -65,13 +66,6 @@ void netdev_port_receive(struct sk_buff *skb, struct ip_tunnel_info *tun_info) kfree_skb(skb); } -#ifndef HAVE_METADATA_DST -#define port_receive(skb) netdev_port_receive(skb, NULL) -#else -#define port_receive(skb) netdev_port_receive(skb, skb_tunnel_info(skb)) -#endif - -#if defined HAVE_RX_HANDLER_PSKB /* 2.6.39 and above or backports */ /* Called with rcu_read_lock and bottom-halves disabled. */ static rx_handler_result_t netdev_frame_hook(struct sk_buff **pskb) { @@ -80,35 +74,13 @@ static rx_handler_result_t netdev_frame_hook(struct sk_buff **pskb) if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) return RX_HANDLER_PASS; - port_receive(skb); - return RX_HANDLER_CONSUMED; -} -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) || \ - defined HAVE_RHEL_OVS_HOOK -/* Called with rcu_read_lock and bottom-halves disabled. */ -static struct sk_buff *netdev_frame_hook(struct sk_buff *skb) -{ - if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) - return skb; - - port_receive(skb); - return NULL; -} -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -/* - * Used as br_handle_frame_hook. (Cannot run bridge at the same time, even on - * different set of devices!) - */ -/* Called with rcu_read_lock and bottom-halves disabled. */ -static struct sk_buff *netdev_frame_hook(struct net_bridge_port *p, - struct sk_buff *skb) -{ - port_receive(skb); - return NULL; -} +#ifndef HAVE_METADATA_DST + netdev_port_receive(skb, NULL); #else -#error + netdev_port_receive(skb, skb_tunnel_info(skb)); #endif + return RX_HANDLER_CONSUMED; +} static struct net_device *get_dpdev(const struct datapath *dp) { @@ -217,10 +189,8 @@ void ovs_netdev_tunnel_destroy(struct vport *vport) * underlying netdev deregistration; delete the link only * if it's not already shutting down. */ - if (vport->dev->reg_state == NETREG_REGISTERED) rtnl_delete_link(vport->dev); - dev_put(vport->dev); vport->dev = NULL; rtnl_unlock(); @@ -232,28 +202,11 @@ EXPORT_SYMBOL_GPL(ovs_netdev_tunnel_destroy); /* Returns null if this device is not attached to a datapath. */ struct vport *ovs_netdev_get_vport(struct net_device *dev) { -#if defined HAVE_NETDEV_RX_HANDLER_REGISTER || \ - defined HAVE_RHEL_OVS_HOOK -#ifdef HAVE_OVS_DATAPATH if (likely(dev->priv_flags & IFF_OVS_DATAPATH)) -#else - if (likely(rcu_access_pointer(dev->rx_handler) == netdev_frame_hook)) -#endif -#ifdef HAVE_RHEL_OVS_HOOK - return (struct vport *)rcu_dereference_rtnl(dev->ax25_ptr); -#else -#ifdef HAVE_NET_DEVICE_EXTENDED return (struct vport *) - rcu_dereference_rtnl(netdev_extended(dev)->rx_handler_data); -#else - return (struct vport *)rcu_dereference_rtnl(dev->rx_handler_data); -#endif -#endif + rcu_dereference_rtnl(dev->rx_handler_data); else return NULL; -#else - return (struct vport *)rcu_dereference_rtnl(dev->br_port); -#endif } static struct vport_ops ovs_netdev_vport_ops = { @@ -272,23 +225,3 @@ void ovs_netdev_exit(void) { ovs_vport_ops_unregister(&ovs_netdev_vport_ops); } - -#if !defined HAVE_NETDEV_RX_HANDLER_REGISTER && \ - !defined HAVE_RHEL_OVS_HOOK -/* - * Enforces, mutual exclusion with the Linux bridge module, by declaring and - * exporting br_should_route_hook. Because the bridge module also exports the - * same symbol, the module loader will refuse to load both modules at the same - * time (e.g. "bridge: exports duplicate symbol br_should_route_hook (owned by - * openvswitch)"). - * - * Before Linux 2.6.36, Open vSwitch cannot safely coexist with the Linux - * bridge module, so openvswitch uses this macro in those versions. In - * Linux 2.6.36 and later, Open vSwitch can coexist with the bridge module. - * - * The use of "typeof" here avoids the need to track changes in the type of - * br_should_route_hook over various kernel versions. - */ -typeof(br_should_route_hook) br_should_route_hook; -EXPORT_SYMBOL(br_should_route_hook); -#endif diff --git a/datapath/vport-netdev.h b/datapath/vport-netdev.h index f8fbb8689e3..04ad190c9b7 100644 --- a/datapath/vport-netdev.h +++ b/datapath/vport-netdev.h @@ -27,7 +27,6 @@ struct vport *ovs_netdev_get_vport(struct net_device *dev); struct vport *ovs_netdev_link(struct vport *vport, const char *name); -void ovs_netdev_send(struct vport *vport, struct sk_buff *skb); void ovs_netdev_detach_dev(struct vport *); int __init ovs_netdev_init(void); diff --git a/datapath/vport.c b/datapath/vport.c index 7fd98583c78..44b9dfbc21c 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -33,8 +33,9 @@ #include #include #include -#include +#include #include +#include #include "datapath.h" #include "gso.h" @@ -375,14 +376,6 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb) return 0; } -static void vport_portids_destroy_rcu_cb(struct rcu_head *rcu) -{ - struct vport_portids *ids = container_of(rcu, struct vport_portids, - rcu); - - kfree(ids); -} - /** * ovs_vport_set_upcall_portids - set upcall portids of @vport. * @@ -417,7 +410,7 @@ int ovs_vport_set_upcall_portids(struct vport *vport, const struct nlattr *ids) rcu_assign_pointer(vport->upcall_portids, vport_portids); if (old) - call_rcu(&old->rcu, vport_portids_destroy_rcu_cb); + kfree_rcu(old, rcu); return 0; } @@ -532,6 +525,25 @@ void ovs_vport_deferred_free(struct vport *vport) } EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); +static struct rtable *ovs_tunnel_route_lookup(struct net *net, + const struct ip_tunnel_key *key, + u32 mark, + struct flowi4 *fl, + u8 protocol) +{ + struct rtable *rt; + + memset(fl, 0, sizeof(*fl)); + fl->daddr = key->u.ipv4.dst; + fl->saddr = key->u.ipv4.src; + fl->flowi4_tos = RT_TOS(key->tos); + fl->flowi4_mark = mark; + fl->flowi4_proto = protocol; + + rt = ip_route_output_key(net, fl); + return rt; +} + int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, struct net *net, struct sk_buff *skb, diff --git a/datapath/vport.h b/datapath/vport.h index 33c3935e9fd..6e804933bb5 100644 --- a/datapath/vport.h +++ b/datapath/vport.h @@ -27,7 +27,6 @@ #include #include #include -#include #include "datapath.h" @@ -81,7 +80,7 @@ struct vport_portids { /** * struct vport - one port within a datapath - * @rcu: RCU callback head for deferred destruction. + * @dev: Pointer to net_device. * @dp: Datapath to which this port belongs. * @upcall_portids: RCU protected 'struct vport_portids'. * @port_no: Index into @dp's @ports array. @@ -89,6 +88,7 @@ struct vport_portids { * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. * @ops: Class structure. * @detach_list: list used for detaching vport in net-exit call. + * @rcu: RCU callback head for deferred destruction. */ struct vport { struct net_device *dev; @@ -153,9 +153,9 @@ struct vport_ops { int (*set_options)(struct vport *, struct nlattr *); int (*get_options)(const struct vport *, struct sk_buff *); + netdev_tx_t (*send)(struct sk_buff *skb); int (*get_egress_tun_info)(struct vport *, struct sk_buff *, struct dp_upcall_info *upcall); - netdev_tx_t (*send)(struct sk_buff *skb); struct module *owner; struct list_head list; @@ -214,31 +214,12 @@ static inline const char *ovs_vport_name(struct vport *vport) int __ovs_vport_ops_register(struct vport_ops *ops); #define ovs_vport_ops_register(ops) \ -({ \ - (ops)->owner = THIS_MODULE; \ - __ovs_vport_ops_register(ops); \ -}) + ({ \ + (ops)->owner = THIS_MODULE; \ + __ovs_vport_ops_register(ops); \ + }) void ovs_vport_ops_unregister(struct vport_ops *ops); - -static inline struct rtable *ovs_tunnel_route_lookup(struct net *net, - const struct ip_tunnel_key *key, - u32 mark, - struct flowi4 *fl, - u8 protocol) -{ - struct rtable *rt; - - memset(fl, 0, sizeof(*fl)); - fl->daddr = key->u.ipv4.dst; - fl->saddr = key->u.ipv4.src; - fl->flowi4_tos = RT_TOS(key->tos); - fl->flowi4_mark = mark; - fl->flowi4_proto = protocol; - - rt = ip_route_output_key(net, fl); - return rt; -} - void ovs_vport_send(struct vport *vport, struct sk_buff *skb); + #endif /* vport.h */