2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 01:51:26 +00:00

datapath: Drop support for kernel older than 3.10

Currently OVS out of tree datapath supports a large number of kernel
versions. From 2.6.32 to 4.3 and various distribution-specific
kernels. But at this point major features are only available on more
recent kernels.  For example, stateful services are only available
starting in kernel 3.10 and STT is available on starting with 3.5.

Since these features are becoming essential to many OVS deployments,
and the effort of maintaining the backports is high. We have decided
to drop support for older kernel. Following patch drops supports
for kernel older than 3.10.

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
This commit is contained in:
Pravin B Shelar 2016-02-29 09:54:15 -08:00
parent 0bac7164d7
commit 8063e09587
33 changed files with 139 additions and 591 deletions

View File

@ -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

View File

@ -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

3
FAQ.md
View File

@ -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.

View File

@ -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`

2
NEWS
View File

@ -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
---------------------

View File

@ -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

View File

@ -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])

View File

@ -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)

View File

@ -27,33 +27,14 @@
#include <net/xfrm.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
/* 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; }

View File

@ -14,8 +14,7 @@
#include <linux/kconfig.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) && \
IS_ENABLED(CONFIG_NF_CONNTRACK)
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <linux/module.h>
#include <linux/openvswitch.h>
@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -44,7 +44,6 @@
#include <net/ipv6.h>
#include <net/ndisc.h>
#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;
}
}

View File

@ -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;

View File

@ -16,6 +16,7 @@
#include <linux/etherdevice.h>
#include <linux/hash.h>
#include <linux/if_link.h>
#include <linux/if_vlan.h>
#include <net/dst_metadata.h>
#include <net/net_namespace.h>
@ -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 @@ drop:
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;

View File

@ -39,18 +39,6 @@
#include <net/xfrm.h>
#include "gso.h"
#include "vlan.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) && \
!defined(HAVE_VLAN_BUG_WORKAROUND)
#include <linux/module.h>
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

View File

@ -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 <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;
};
#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)

View File

@ -3,57 +3,6 @@
#include_next <net/net_namespace.h>
#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

View File

@ -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)) {

View File

@ -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;

View File

@ -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);

View File

@ -19,6 +19,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/if_vlan.h>
#include <linux/in.h>
#include <linux/in_route.h>
#include <linux/inetdevice.h>
@ -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);

View File

@ -17,6 +17,7 @@
#include <linux/version.h>
#include <linux/etherdevice.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/net.h>
@ -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 @@ error:
}
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;

View File

@ -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;

View File

@ -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 <linux/if_vlan.h>
#include <linux/skbuff.h>
#include <linux/version.h>
/**
* 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 */

View File

@ -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);

View File

@ -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 <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/skbuff.h>
#include <linux/percpu.h>
#include <linux/u64_stats_sync.h>
#include <linux/netdev_features.h>
#include <net/dst.h>
#include <net/xfrm.h>
@ -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;
static void internal_dev_uninit(struct net_device *dev)
{
free_percpu(dev->tstats);
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;
}
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;

View File

@ -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 <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/openvswitch.h>
#include <linux/export.h>
#include <net/ip_tunnels.h>
#include <net/rtnetlink.h>
@ -65,13 +66,6 @@ error:
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);
#ifndef HAVE_METADATA_DST
netdev_port_receive(skb, NULL);
#else
netdev_port_receive(skb, skb_tunnel_info(skb));
#endif
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;
}
#else
#error
#endif
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

View File

@ -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);

View File

@ -33,8 +33,9 @@
#include <net/lisp.h>
#include <net/gre.h>
#include <net/geneve.h>
#include <net/vxlan.h>
#include <net/route.h>
#include <net/stt.h>
#include <net/vxlan.h>
#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,

View File

@ -27,7 +27,6 @@
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/u64_stats_sync.h>
#include <net/route.h>
#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 */