- 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
- 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
### 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
| 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.
- 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.
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
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`
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
---------------------
* 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
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)|| \
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
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])
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])
#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,
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 {
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)
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;
}
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;
}
} 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);
}
}
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;
}
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);
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)
#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; }
#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>
nf_connlabels_put(net);
}
-#endif /* CONFIG_NF_CONNTRACK && LINUX > 3.10 */
+#endif /* CONFIG_NF_CONNTRACK */
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);
#include "flow_table.h"
#include "flow_netlink.h"
#include "gso.h"
-#include "vlan.h"
#include "vport-internal_dev.h"
#include "vport-netdev.h"
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;
}
.size = sizeof(struct ovs_net),
};
-DEFINE_COMPAT_PNET_REG_FUNC(device);
-
static int __init dp_init(void)
{
int err;
#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
#include "flow.h"
#include "flow_netlink.h"
#include "vport.h"
-#include "vlan.h"
u64 ovs_flow_used_time(unsigned long flow_jiffies)
{
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;
#include <net/ipv6.h>
#include <net/ndisc.h>
-#include "vlan.h"
#include "flow_netlink.h"
#define TBL_MIN_BUCKETS 1024
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)
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;
}
}
#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;
#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>
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;
}
}
-#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:
kfree_skb(skb);
}
-#ifdef HAVE_DEV_TSTATS
/* Setup stats when device is created */
static int geneve_init(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)
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;
}
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);
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);
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,
}
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,
.size = sizeof(struct geneve_net),
};
-DEFINE_COMPAT_PNET_REG_FUNC(device)
int rpl_geneve_init_module(void)
{
int rc;
#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)
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
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)
{
#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)
#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)
#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
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,
{
u8 l4_hdr = 0;
- if (!skb_encapsulation(skb))
+ if (!skb->encapsulation)
return features;
switch (vlan_get_protocol(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)) {
.size = sizeof(struct ip_tunnel_net),
};
-DEFINE_COMPAT_PNET_REG_FUNC(device);
-
int rpl_ipgre_init(void)
{
int err;
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)
static void ip_tunnel_dev_free(struct net_device *dev)
{
-#ifdef HAVE_DEV_TSTATS
free_percpu(dev->tstats);
-#endif
free_netdev(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);
#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>
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. */
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);
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;
/* 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);
#include <linux/version.h>
+#include <linux/etherdevice.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/net.h>
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)) {
/* 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)) {
}
EXPORT_SYMBOL(rpl_lisp_xmit);
-#ifdef HAVE_DEV_TSTATS
/* Setup stats when device is created */
static int lisp_init(struct net_device *dev)
{
{
free_percpu(dev->tstats);
}
-#endif
static struct socket *create_sock(struct net *net, bool ipv6,
__be16 port)
}
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,
.size = sizeof(struct lisp_net),
};
-DEFINE_COMPAT_PNET_REG_FUNC(device)
int rpl_lisp_init_module(void)
{
int rc;
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;
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;
}
}
-#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:
}
}
- 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);
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++;
}
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,
}
/* 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);
return 0;
}
-#endif
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);
free_percpu(dev->tstats);
}
-#endif
/* Start ageing timer and join group when device is brought up */
static int vxlan_open(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,
.size = sizeof(struct vxlan_net),
};
-DEFINE_COMPAT_PNET_REG_FUNC(device)
int rpl_vxlan_init_module(void)
{
int rc;
+++ /dev/null
-/*
- * 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 */
* @dst_port: destination port.
*/
struct geneve_port {
- u16 port_no;
+ u16 dst_port;
};
static inline struct geneve_port *geneve_vport(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;
}
{
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),
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);
/*
- * 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
#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>
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++;
}
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)
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 = {
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);
}
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);
rtnl_lock();
err = register_netdevice(vport->dev);
if (err)
- goto error_free_netdev;
+ goto error_unlock;
dev_set_promiscuity(vport->dev, 1);
rtnl_unlock();
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);
/* 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);
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);
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;
/*
- * 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
#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>
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)
{
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)
{
* 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();
/* 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 = {
{
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
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);
#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"
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.
*
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;
}
}
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,
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/u64_stats_sync.h>
-#include <net/route.h>
#include "datapath.h"
/**
* 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.
* @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;
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;
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 */