mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
Merge branch 'openvswitch-remove-support-for-legacy-tunnel-ports'
Ilya Maximets says: ==================== openvswitch: remove support for legacy tunnel ports ovs-vswitchd doesn't use OVS_VPORT_TYPE_GRE/VXLAN/GENEVE with the Linux kernel module since adding support for standard tunnel devices with COLLECT_METADATA back in 2017. The code to use them was only activated as a fallback for old kernels, so not used in practice. And it is now fully removed in the upcoming OVS 4.0 release. Modern way to use tunnels with OVS is to create standard tunnel ports with RTM_NEWLINK + COLLECT_METADATA and add them as OVS_VPORT_TYPE_NETDEV. Device reference management and the netlink options parsing for these legacy port types is complicated and was a CVE magnet in the previous release cycles. Existence of these modules also makes locking analysis for geneve module and other core tunnel devices unnecessarily more complicated, especially in light of migration to per-netns locking: https://lore.kernel.org/r/CAAVpQUDmZEaQNDSySLayqexgTrUbhBaL7XPCt9XNQzh+NGQ=UQ@mail.gmail.com Since there are no actual users for these port types for a very long time, let's just remove the support entirely. There is no practical reason to run OVS from 2017 on a recent kernel. While it's technically a uAPI change in some sense, from the user's perspective this removal looks indistinguishable from the kernel built with CONFIG_OPENVSWITCH_GENEVE/VXLAN/GRE disabled. And it seems like removal of unused drivers/modules is not a rare event these days. There are 3 parts to this set: 1. The first patch does the tunnel port removal, which is the primary goal here. 2. Patches 2 and 3 remove extra infrastructure that is no longer in use by anything inside the openvswitch module. 3. Patches 4-6 remove functions from gre/vxlan/geneve modules that were added for openvswitch in the past to support the tunnel types. openvswitch is the only in-tree consumer of these functions. Version 1: - Rebased. - Removed the tunnel modules from the new OVS selftest config. - Addressed RFC review from Sashiko: * Made ovs_netdev_link() static. * Restored -EOPNOTSUPP if OVS_VPORT_ATTR_OPTIONS was provided. * Removed retry in ovs_vport_cmd_new() as not needed anymore. RFC: - https://lore.kernel.org/r/20260513183559.2141010-1-i.maximets@ovn.org ==================== Link: https://patch.msgid.link/20260804182049.2289754-1-i.maximets@ovn.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -2670,55 +2670,6 @@ static struct rtnl_link_ops geneve_link_ops __read_mostly = {
|
||||
.fill_info = geneve_fill_info,
|
||||
};
|
||||
|
||||
struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
|
||||
u8 name_assign_type, u16 dst_port)
|
||||
{
|
||||
struct nlattr *tb[IFLA_MAX + 1];
|
||||
struct net_device *dev;
|
||||
LIST_HEAD(list_kill);
|
||||
int err;
|
||||
struct geneve_config cfg = {
|
||||
.df = GENEVE_DF_UNSET,
|
||||
.use_udp6_rx_checksums = true,
|
||||
.ttl_inherit = false,
|
||||
.collect_md = true,
|
||||
.dualstack = true,
|
||||
.port_min = 1,
|
||||
.port_max = USHRT_MAX,
|
||||
};
|
||||
|
||||
memset(tb, 0, sizeof(tb));
|
||||
dev = rtnl_create_link(net, name, name_assign_type,
|
||||
&geneve_link_ops, tb, NULL);
|
||||
if (IS_ERR(dev))
|
||||
return dev;
|
||||
|
||||
init_tnl_info(&cfg.info, dst_port);
|
||||
err = geneve_configure(net, dev, NULL, &cfg);
|
||||
if (err) {
|
||||
free_netdev(dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/* openvswitch users expect packet sizes to be unrestricted,
|
||||
* so set the largest MTU we can.
|
||||
*/
|
||||
err = geneve_change_mtu(dev, IP_MAX_MTU);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = rtnl_configure_link(dev, NULL, 0, NULL);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
return dev;
|
||||
err:
|
||||
geneve_dellink(dev, &list_kill);
|
||||
unregister_netdevice_many(&list_kill);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(geneve_dev_create_fb);
|
||||
|
||||
static int geneve_netdevice_event(struct notifier_block *unused,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
|
||||
@@ -3966,9 +3966,9 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __vxlan_dev_create(struct net *net, struct net_device *dev,
|
||||
struct vxlan_config *conf,
|
||||
struct netlink_ext_ack *extack)
|
||||
static int vxlan_dev_create(struct net *net, struct net_device *dev,
|
||||
struct vxlan_config *conf,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
|
||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||
@@ -4416,7 +4416,7 @@ static int vxlan_newlink(struct net_device *dev,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return __vxlan_dev_create(link_net, dev, &conf, extack);
|
||||
return vxlan_dev_create(link_net, dev, &conf, extack);
|
||||
}
|
||||
|
||||
static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
|
||||
@@ -4700,40 +4700,6 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
|
||||
.get_link_net = vxlan_get_link_net,
|
||||
};
|
||||
|
||||
struct net_device *vxlan_dev_create(struct net *net, const char *name,
|
||||
u8 name_assign_type,
|
||||
struct vxlan_config *conf)
|
||||
{
|
||||
struct nlattr *tb[IFLA_MAX + 1];
|
||||
struct net_device *dev;
|
||||
int err;
|
||||
|
||||
memset(&tb, 0, sizeof(tb));
|
||||
|
||||
dev = rtnl_create_link(net, name, name_assign_type,
|
||||
&vxlan_link_ops, tb, NULL);
|
||||
if (IS_ERR(dev))
|
||||
return dev;
|
||||
|
||||
err = __vxlan_dev_create(net, dev, conf, NULL);
|
||||
if (err < 0) {
|
||||
free_netdev(dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
err = rtnl_configure_link(dev, NULL, 0, NULL);
|
||||
if (err < 0) {
|
||||
LIST_HEAD(list_kill);
|
||||
|
||||
vxlan_dellink(dev, &list_kill);
|
||||
unregister_netdevice_many(&list_kill);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vxlan_dev_create);
|
||||
|
||||
static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
|
||||
struct net_device *dev)
|
||||
{
|
||||
|
||||
@@ -68,9 +68,4 @@ static inline bool netif_is_geneve(const struct net_device *dev)
|
||||
!strcmp(dev->rtnl_link_ops->kind, "geneve");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
|
||||
u8 name_assign_type, u16 dst_port);
|
||||
#endif /*ifdef CONFIG_INET */
|
||||
|
||||
#endif /*ifdef__NET_GENEVE_H */
|
||||
|
||||
@@ -32,8 +32,6 @@ struct gre_protocol {
|
||||
int gre_add_protocol(const struct gre_protocol *proto, u8 version);
|
||||
int gre_del_protocol(const struct gre_protocol *proto, u8 version);
|
||||
|
||||
struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
|
||||
u8 name_assign_type);
|
||||
int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
|
||||
bool *csum_err, __be16 proto, int nhs);
|
||||
|
||||
|
||||
@@ -359,9 +359,6 @@ struct vxlan_dev {
|
||||
VXLAN_F_MC_ROUTE | \
|
||||
0)
|
||||
|
||||
struct net_device *vxlan_dev_create(struct net *net, const char *name,
|
||||
u8 name_assign_type, struct vxlan_config *conf);
|
||||
|
||||
static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
|
||||
@@ -244,13 +244,33 @@ enum ovs_vport_cmd {
|
||||
OVS_VPORT_CMD_SET
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ovs_vport_type - OVS vport types for %OVS_VPORT_ATTR_TYPE.
|
||||
* @OVS_VPORT_TYPE_NETDEV: Existing network device attached as a vport.
|
||||
* @OVS_VPORT_TYPE_INTERNAL: Network device implemented by the OVS datapath.
|
||||
* @OVS_VPORT_TYPE_GRE: Legacy GRE tunnel. Not supported, see below.
|
||||
* @OVS_VPORT_TYPE_VXLAN: Legacy VXLAN tunnel. Not supported, see below.
|
||||
* @OVS_VPORT_TYPE_GENEVE: Legacy Geneve tunnel. Not supported, see below.
|
||||
*
|
||||
* The tunnel vport types are not supported. Instead, create the tunnel device
|
||||
* using %RTM_NEWLINK with the appropriate %IFLA_INFO_KIND (e.g. ``gre``,
|
||||
* ``gretap``, ``vxlan``, ``geneve``, or other tunnel types) and add it as
|
||||
* %OVS_VPORT_TYPE_NETDEV. To match and set tunnel parameters on a per-flow
|
||||
* basis, the tunnel device should collect metadata. To do that, some tunnel
|
||||
* types require an explicit flag such as %IFLA_VXLAN_COLLECT_METADATA for
|
||||
* ``vxlan``, while others such as ``bareudp`` collect metadata
|
||||
* unconditionally.
|
||||
*/
|
||||
enum ovs_vport_type {
|
||||
/* private: */
|
||||
OVS_VPORT_TYPE_UNSPEC,
|
||||
/* public: */
|
||||
OVS_VPORT_TYPE_NETDEV, /* network device */
|
||||
OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */
|
||||
OVS_VPORT_TYPE_GRE, /* GRE tunnel. */
|
||||
OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel. */
|
||||
OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */
|
||||
OVS_VPORT_TYPE_GRE, /* GRE tunnel (legacy, not supported). */
|
||||
OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel (legacy, not supported). */
|
||||
OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel (legacy, not supported). */
|
||||
/* private: */
|
||||
__OVS_VPORT_TYPE_MAX
|
||||
};
|
||||
|
||||
@@ -284,7 +304,7 @@ enum ovs_vport_type {
|
||||
* %OVS_VPORT_ATTR_NAME attributes are required. %OVS_VPORT_ATTR_PORT_NO is
|
||||
* optional; if not specified a free port number is automatically selected.
|
||||
* Whether %OVS_VPORT_ATTR_OPTIONS is required or optional depends on the type
|
||||
* of vport.
|
||||
* of vport. None of currently supported vport types support options.
|
||||
*
|
||||
* For other requests, if %OVS_VPORT_ATTR_NAME is specified then it is used to
|
||||
* look up the vport to operate on; otherwise dp_idx from the &struct
|
||||
@@ -336,7 +356,8 @@ enum {
|
||||
#define OVS_VXLAN_EXT_MAX (__OVS_VXLAN_EXT_MAX - 1)
|
||||
|
||||
|
||||
/* OVS_VPORT_ATTR_OPTIONS attributes for tunnels.
|
||||
/* OVS_VPORT_ATTR_OPTIONS attributes for legacy tunnel vports.
|
||||
* Not supported, see the note for enum ovs_vport_type.
|
||||
*/
|
||||
enum {
|
||||
OVS_TUNNEL_ATTR_UNSPEC,
|
||||
|
||||
@@ -1716,53 +1716,6 @@ static struct rtnl_link_ops erspan_link_ops __read_mostly = {
|
||||
.get_link_net = ip_tunnel_get_link_net,
|
||||
};
|
||||
|
||||
struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
|
||||
u8 name_assign_type)
|
||||
{
|
||||
struct rtnl_newlink_params params = { .src_net = net };
|
||||
struct nlattr *tb[IFLA_MAX + 1];
|
||||
struct net_device *dev;
|
||||
LIST_HEAD(list_kill);
|
||||
struct ip_tunnel *t;
|
||||
int err;
|
||||
|
||||
memset(&tb, 0, sizeof(tb));
|
||||
params.tb = tb;
|
||||
|
||||
dev = rtnl_create_link(net, name, name_assign_type,
|
||||
&ipgre_tap_ops, tb, NULL);
|
||||
if (IS_ERR(dev))
|
||||
return dev;
|
||||
|
||||
/* Configure flow based GRE device. */
|
||||
t = netdev_priv(dev);
|
||||
t->collect_md = true;
|
||||
|
||||
err = ipgre_newlink(dev, ¶ms, NULL);
|
||||
if (err < 0) {
|
||||
free_netdev(dev);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/* openvswitch users expect packet sizes to be unrestricted,
|
||||
* so set the largest MTU we can.
|
||||
*/
|
||||
err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = rtnl_configure_link(dev, NULL, 0, NULL);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
return dev;
|
||||
out:
|
||||
ip_tunnel_dellink(dev, &list_kill);
|
||||
unregister_netdevice_many(&list_kill);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
|
||||
|
||||
static int __net_init ipgre_tap_init_net(struct net *net)
|
||||
{
|
||||
return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");
|
||||
|
||||
@@ -40,38 +40,3 @@ config OPENVSWITCH
|
||||
called openvswitch.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config OPENVSWITCH_GRE
|
||||
tristate "Open vSwitch GRE tunneling support"
|
||||
depends on OPENVSWITCH
|
||||
depends on NET_IPGRE
|
||||
default OPENVSWITCH
|
||||
help
|
||||
If you say Y here, then the Open vSwitch will be able create GRE
|
||||
vport.
|
||||
|
||||
Say N to exclude this support and reduce the binary size.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config OPENVSWITCH_VXLAN
|
||||
tristate "Open vSwitch VXLAN tunneling support"
|
||||
depends on OPENVSWITCH
|
||||
depends on VXLAN
|
||||
default OPENVSWITCH
|
||||
help
|
||||
If you say Y here, then the Open vSwitch will be able create vxlan vport.
|
||||
|
||||
Say N to exclude this support and reduce the binary size.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config OPENVSWITCH_GENEVE
|
||||
tristate "Open vSwitch Geneve tunneling support"
|
||||
depends on OPENVSWITCH
|
||||
depends on GENEVE
|
||||
default OPENVSWITCH
|
||||
help
|
||||
If you say Y here, then the Open vSwitch will be able create geneve vport.
|
||||
|
||||
Say N to exclude this support and reduce the binary size.
|
||||
|
||||
@@ -22,8 +22,4 @@ ifneq ($(CONFIG_NF_CONNTRACK),)
|
||||
openvswitch-y += conntrack.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_OPENVSWITCH_VXLAN)+= vport-vxlan.o
|
||||
obj-$(CONFIG_OPENVSWITCH_GENEVE)+= vport-geneve.o
|
||||
obj-$(CONFIG_OPENVSWITCH_GRE) += vport-gre.o
|
||||
|
||||
CFLAGS_openvswitch_trace.o = -I$(src)
|
||||
|
||||
@@ -1856,7 +1856,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
/* Set up our datapath device. */
|
||||
parms.name = nla_data(a[OVS_DP_ATTR_NAME]);
|
||||
parms.type = OVS_VPORT_TYPE_INTERNAL;
|
||||
parms.options = NULL;
|
||||
parms.dp = dp;
|
||||
parms.port_no = OVSP_LOCAL;
|
||||
parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
|
||||
@@ -2172,10 +2171,6 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
|
||||
if (ovs_vport_get_upcall_portids(vport, skb))
|
||||
goto nla_put_failure;
|
||||
|
||||
err = ovs_vport_get_options(vport, skb);
|
||||
if (err == -EMSGSIZE)
|
||||
goto error;
|
||||
|
||||
genlmsg_end(skb, ovs_header);
|
||||
return 0;
|
||||
|
||||
@@ -2183,7 +2178,6 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
|
||||
rcu_read_unlock();
|
||||
nla_put_failure:
|
||||
err = -EMSGSIZE;
|
||||
error:
|
||||
genlmsg_cancel(skb, ovs_header);
|
||||
return err;
|
||||
}
|
||||
@@ -2210,12 +2204,6 @@ static size_t ovs_vport_cmd_msg_size(void)
|
||||
/* OVS_VPORT_ATTR_UPCALL_PID */
|
||||
msgsize += nla_total_size(nr_cpu_ids * sizeof(u32));
|
||||
|
||||
/* OVS_VPORT_ATTR_OPTIONS(OVS_TUNNEL_ATTR_DST_PORT +
|
||||
* OVS_TUNNEL_ATTR_EXTENSION(OVS_VXLAN_EXT_GBP))
|
||||
*/
|
||||
msgsize += nla_total_size(nla_total_size(sizeof(u16)) +
|
||||
nla_total_size(nla_total_size(0)));
|
||||
|
||||
return msgsize;
|
||||
}
|
||||
|
||||
@@ -2343,7 +2331,6 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
return -ENOMEM;
|
||||
|
||||
ovs_lock();
|
||||
restart:
|
||||
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
|
||||
err = -ENODEV;
|
||||
if (!dp)
|
||||
@@ -2367,7 +2354,6 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
parms.name = nla_data(a[OVS_VPORT_ATTR_NAME]);
|
||||
parms.options = a[OVS_VPORT_ATTR_OPTIONS];
|
||||
parms.dp = dp;
|
||||
parms.port_no = port_no;
|
||||
parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
|
||||
@@ -2376,11 +2362,8 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
vport = new_vport(&parms);
|
||||
err = PTR_ERR(vport);
|
||||
if (IS_ERR(vport)) {
|
||||
if (err == -EAGAIN)
|
||||
goto restart;
|
||||
if (IS_ERR(vport))
|
||||
goto exit_unlock_free;
|
||||
}
|
||||
|
||||
err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),
|
||||
info->snd_portid, info->snd_seq, 0,
|
||||
@@ -2429,12 +2412,11 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
if (a[OVS_VPORT_ATTR_OPTIONS]) {
|
||||
err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
|
||||
if (err)
|
||||
goto exit_unlock_free;
|
||||
/* There are no vport types that support legacy options. */
|
||||
err = -EOPNOTSUPP;
|
||||
goto exit_unlock_free;
|
||||
}
|
||||
|
||||
|
||||
if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
|
||||
struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
|
||||
|
||||
@@ -2608,7 +2590,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
|
||||
[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_UNSPEC },
|
||||
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
|
||||
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED }, /* Unused. */
|
||||
[OVS_VPORT_ATTR_IFINDEX] = NLA_POLICY_MIN(NLA_S32, 0),
|
||||
[OVS_VPORT_ATTR_NETNSID] = { .type = NLA_S32 },
|
||||
[OVS_VPORT_ATTR_UPCALL_STATS] = { .type = NLA_NESTED },
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2014 Nicira, Inc.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <net/geneve.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/route.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
#include "datapath.h"
|
||||
#include "vport.h"
|
||||
#include "vport-netdev.h"
|
||||
|
||||
static struct vport_ops ovs_geneve_vport_ops;
|
||||
/**
|
||||
* struct geneve_port - Keeps track of open UDP ports
|
||||
* @dst_port: destination port.
|
||||
*/
|
||||
struct geneve_port {
|
||||
u16 dst_port;
|
||||
};
|
||||
|
||||
static inline struct geneve_port *geneve_vport(const struct vport *vport)
|
||||
{
|
||||
return vport_priv(vport);
|
||||
}
|
||||
|
||||
static int geneve_get_options(const struct vport *vport,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct geneve_port *geneve_port = geneve_vport(vport);
|
||||
|
||||
if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->dst_port))
|
||||
return -EMSGSIZE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vport *geneve_tnl_create(const struct vport_parms *parms)
|
||||
{
|
||||
struct net *net = ovs_dp_get_net(parms->dp);
|
||||
struct nlattr *options = parms->options;
|
||||
struct geneve_port *geneve_port;
|
||||
struct net_device *dev;
|
||||
struct vport *vport;
|
||||
struct nlattr *a;
|
||||
u16 dst_port;
|
||||
int err;
|
||||
|
||||
if (!options) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
|
||||
if (a && nla_len(a) == sizeof(u16)) {
|
||||
dst_port = nla_get_u16(a);
|
||||
} else {
|
||||
/* Require destination port from userspace. */
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
vport = ovs_vport_alloc(sizeof(struct geneve_port),
|
||||
&ovs_geneve_vport_ops, parms);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
|
||||
geneve_port = geneve_vport(vport);
|
||||
geneve_port->dst_port = dst_port;
|
||||
|
||||
rtnl_lock();
|
||||
dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port);
|
||||
if (IS_ERR(dev)) {
|
||||
rtnl_unlock();
|
||||
ovs_vport_free(vport);
|
||||
return ERR_CAST(dev);
|
||||
}
|
||||
|
||||
err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
|
||||
if (err < 0) {
|
||||
rtnl_delete_link(dev, 0, NULL);
|
||||
rtnl_unlock();
|
||||
ovs_vport_free(vport);
|
||||
goto error;
|
||||
}
|
||||
|
||||
vport->dev = dev;
|
||||
netdev_hold(vport->dev, &vport->dev_tracker, GFP_KERNEL);
|
||||
|
||||
rtnl_unlock();
|
||||
return vport;
|
||||
error:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static struct vport *geneve_create(const struct vport_parms *parms)
|
||||
{
|
||||
struct vport *vport;
|
||||
|
||||
vport = geneve_tnl_create(parms);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
|
||||
return ovs_netdev_link(vport, true);
|
||||
}
|
||||
|
||||
static struct vport_ops ovs_geneve_vport_ops = {
|
||||
.type = OVS_VPORT_TYPE_GENEVE,
|
||||
.create = geneve_create,
|
||||
.destroy = ovs_netdev_tunnel_destroy,
|
||||
.get_options = geneve_get_options,
|
||||
.send = dev_queue_xmit,
|
||||
};
|
||||
|
||||
static int __init ovs_geneve_tnl_init(void)
|
||||
{
|
||||
return ovs_vport_ops_register(&ovs_geneve_vport_ops);
|
||||
}
|
||||
|
||||
static void __exit ovs_geneve_tnl_exit(void)
|
||||
{
|
||||
ovs_vport_ops_unregister(&ovs_geneve_vport_ops);
|
||||
}
|
||||
|
||||
module_init(ovs_geneve_tnl_init);
|
||||
module_exit(ovs_geneve_tnl_exit);
|
||||
|
||||
MODULE_DESCRIPTION("OVS: Geneve switching port");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("vport-type-5");
|
||||
@@ -1,106 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2007-2014 Nicira, Inc.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/if_tunnel.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/in_route.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <net/route.h>
|
||||
#include <net/xfrm.h>
|
||||
|
||||
#include <net/icmp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ip_tunnels.h>
|
||||
#include <net/gre.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include <net/protocol.h>
|
||||
|
||||
#include "datapath.h"
|
||||
#include "vport.h"
|
||||
#include "vport-netdev.h"
|
||||
|
||||
static struct vport_ops ovs_gre_vport_ops;
|
||||
|
||||
static struct vport *gre_tnl_create(const struct vport_parms *parms)
|
||||
{
|
||||
struct net *net = ovs_dp_get_net(parms->dp);
|
||||
struct net_device *dev;
|
||||
struct vport *vport;
|
||||
int err;
|
||||
|
||||
vport = ovs_vport_alloc(0, &ovs_gre_vport_ops, parms);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
|
||||
rtnl_lock();
|
||||
dev = gretap_fb_dev_create(net, parms->name, NET_NAME_USER);
|
||||
if (IS_ERR(dev)) {
|
||||
rtnl_unlock();
|
||||
ovs_vport_free(vport);
|
||||
return ERR_CAST(dev);
|
||||
}
|
||||
|
||||
err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
|
||||
if (err < 0) {
|
||||
rtnl_delete_link(dev, 0, NULL);
|
||||
rtnl_unlock();
|
||||
ovs_vport_free(vport);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
vport->dev = dev;
|
||||
netdev_hold(vport->dev, &vport->dev_tracker, GFP_KERNEL);
|
||||
|
||||
rtnl_unlock();
|
||||
return vport;
|
||||
}
|
||||
|
||||
static struct vport *gre_create(const struct vport_parms *parms)
|
||||
{
|
||||
struct vport *vport;
|
||||
|
||||
vport = gre_tnl_create(parms);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
|
||||
return ovs_netdev_link(vport, true);
|
||||
}
|
||||
|
||||
static struct vport_ops ovs_gre_vport_ops = {
|
||||
.type = OVS_VPORT_TYPE_GRE,
|
||||
.create = gre_create,
|
||||
.send = dev_queue_xmit,
|
||||
.destroy = ovs_netdev_tunnel_destroy,
|
||||
};
|
||||
|
||||
static int __init ovs_gre_tnl_init(void)
|
||||
{
|
||||
return ovs_vport_ops_register(&ovs_gre_vport_ops);
|
||||
}
|
||||
|
||||
static void __exit ovs_gre_tnl_exit(void)
|
||||
{
|
||||
ovs_vport_ops_unregister(&ovs_gre_vport_ops);
|
||||
}
|
||||
|
||||
module_init(ovs_gre_tnl_init);
|
||||
module_exit(ovs_gre_tnl_exit);
|
||||
|
||||
MODULE_DESCRIPTION("OVS: GRE switching port");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("vport-type-3");
|
||||
@@ -73,7 +73,7 @@ static struct net_device *get_dpdev(const struct datapath *dp)
|
||||
return local->dev;
|
||||
}
|
||||
|
||||
struct vport *ovs_netdev_link(struct vport *vport, bool tunnel)
|
||||
static struct vport *ovs_netdev_link(struct vport *vport)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -112,15 +112,12 @@ struct vport *ovs_netdev_link(struct vport *vport, bool tunnel)
|
||||
error_master_upper_dev_unlink:
|
||||
netdev_upper_dev_unlink(vport->dev, get_dpdev(vport->dp));
|
||||
error_put_unlock:
|
||||
if (tunnel && vport->dev->reg_state == NETREG_REGISTERED)
|
||||
rtnl_delete_link(vport->dev, 0, NULL);
|
||||
netdev_put(vport->dev, &vport->dev_tracker);
|
||||
rtnl_unlock();
|
||||
error_free_vport:
|
||||
ovs_vport_free(vport);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ovs_netdev_link);
|
||||
|
||||
static struct vport *netdev_create(const struct vport_parms *parms)
|
||||
{
|
||||
@@ -152,7 +149,7 @@ static struct vport *netdev_create(const struct vport_parms *parms)
|
||||
goto error_put;
|
||||
}
|
||||
|
||||
return ovs_netdev_link(vport, false);
|
||||
return ovs_netdev_link(vport);
|
||||
error_put:
|
||||
netdev_put(vport->dev, &vport->dev_tracker);
|
||||
error_free_vport:
|
||||
@@ -204,28 +201,6 @@ static void netdev_destroy(struct vport *vport)
|
||||
call_rcu(&vport->rcu, vport_netdev_free);
|
||||
}
|
||||
|
||||
void ovs_netdev_tunnel_destroy(struct vport *vport)
|
||||
{
|
||||
rtnl_lock();
|
||||
if (netif_is_ovs_port(vport->dev))
|
||||
ovs_netdev_detach_dev(vport);
|
||||
|
||||
/* We can be invoked by both explicit vport deletion and
|
||||
* 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, 0, NULL);
|
||||
|
||||
/* We can't put the device reference yet, since it can still be in
|
||||
* use, but rtnl_unlock()->netdev_run_todo() will block until all
|
||||
* the references are released, so the RCU call must be before it.
|
||||
*/
|
||||
call_rcu(&vport->rcu, vport_netdev_free);
|
||||
rtnl_unlock();
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -13,11 +13,9 @@
|
||||
|
||||
struct vport *ovs_netdev_get_vport(struct net_device *dev);
|
||||
|
||||
struct vport *ovs_netdev_link(struct vport *vport, bool tunnel);
|
||||
void ovs_netdev_detach_dev(struct vport *);
|
||||
|
||||
int __init ovs_netdev_init(void);
|
||||
void ovs_netdev_exit(void);
|
||||
|
||||
void ovs_netdev_tunnel_destroy(struct vport *vport);
|
||||
#endif /* vport_netdev.h */
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2014 Nicira, Inc.
|
||||
* Copyright (c) 2013 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/openvswitch.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/ip_tunnels.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/vxlan.h>
|
||||
|
||||
#include "datapath.h"
|
||||
#include "vport.h"
|
||||
#include "vport-netdev.h"
|
||||
|
||||
static struct vport_ops ovs_vxlan_netdev_vport_ops;
|
||||
|
||||
static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
|
||||
{
|
||||
struct vxlan_dev *vxlan = netdev_priv(vport->dev);
|
||||
__be16 dst_port = vxlan->cfg.dst_port;
|
||||
|
||||
if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, ntohs(dst_port)))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (vxlan->cfg.flags & VXLAN_F_GBP) {
|
||||
struct nlattr *exts;
|
||||
|
||||
exts = nla_nest_start_noflag(skb, OVS_TUNNEL_ATTR_EXTENSION);
|
||||
if (!exts)
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (vxlan->cfg.flags & VXLAN_F_GBP &&
|
||||
nla_put_flag(skb, OVS_VXLAN_EXT_GBP))
|
||||
return -EMSGSIZE;
|
||||
|
||||
nla_nest_end(skb, exts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nla_policy exts_policy[OVS_VXLAN_EXT_MAX + 1] = {
|
||||
[OVS_VXLAN_EXT_GBP] = { .type = NLA_FLAG, },
|
||||
};
|
||||
|
||||
static int vxlan_configure_exts(struct vport *vport, struct nlattr *attr,
|
||||
struct vxlan_config *conf)
|
||||
{
|
||||
struct nlattr *exts[OVS_VXLAN_EXT_MAX + 1];
|
||||
int err;
|
||||
|
||||
if (nla_len(attr) < sizeof(struct nlattr))
|
||||
return -EINVAL;
|
||||
|
||||
err = nla_parse_nested_deprecated(exts, OVS_VXLAN_EXT_MAX, attr,
|
||||
exts_policy, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (exts[OVS_VXLAN_EXT_GBP])
|
||||
conf->flags |= VXLAN_F_GBP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
|
||||
{
|
||||
struct net *net = ovs_dp_get_net(parms->dp);
|
||||
struct nlattr *options = parms->options;
|
||||
struct net_device *dev;
|
||||
struct vport *vport;
|
||||
struct nlattr *a;
|
||||
int err;
|
||||
struct vxlan_config conf = {
|
||||
.no_share = true,
|
||||
.flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX,
|
||||
/* Don't restrict the packets that can be sent by MTU */
|
||||
.mtu = IP_MAX_MTU,
|
||||
};
|
||||
|
||||
if (!options) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
|
||||
if (a && nla_len(a) == sizeof(u16)) {
|
||||
conf.dst_port = htons(nla_get_u16(a));
|
||||
} else {
|
||||
/* Require destination port from userspace. */
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
vport = ovs_vport_alloc(0, &ovs_vxlan_netdev_vport_ops, parms);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
|
||||
a = nla_find_nested(options, OVS_TUNNEL_ATTR_EXTENSION);
|
||||
if (a) {
|
||||
err = vxlan_configure_exts(vport, a, &conf);
|
||||
if (err) {
|
||||
ovs_vport_free(vport);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
dev = vxlan_dev_create(net, parms->name, NET_NAME_USER, &conf);
|
||||
if (IS_ERR(dev)) {
|
||||
rtnl_unlock();
|
||||
ovs_vport_free(vport);
|
||||
return ERR_CAST(dev);
|
||||
}
|
||||
|
||||
err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
|
||||
if (err < 0) {
|
||||
rtnl_delete_link(dev, 0, NULL);
|
||||
rtnl_unlock();
|
||||
ovs_vport_free(vport);
|
||||
goto error;
|
||||
}
|
||||
|
||||
vport->dev = dev;
|
||||
netdev_hold(vport->dev, &vport->dev_tracker, GFP_KERNEL);
|
||||
|
||||
rtnl_unlock();
|
||||
return vport;
|
||||
error:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static struct vport *vxlan_create(const struct vport_parms *parms)
|
||||
{
|
||||
struct vport *vport;
|
||||
|
||||
vport = vxlan_tnl_create(parms);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
|
||||
return ovs_netdev_link(vport, true);
|
||||
}
|
||||
|
||||
static struct vport_ops ovs_vxlan_netdev_vport_ops = {
|
||||
.type = OVS_VPORT_TYPE_VXLAN,
|
||||
.create = vxlan_create,
|
||||
.destroy = ovs_netdev_tunnel_destroy,
|
||||
.get_options = vxlan_get_options,
|
||||
.send = dev_queue_xmit,
|
||||
};
|
||||
|
||||
static int __init ovs_vxlan_tnl_init(void)
|
||||
{
|
||||
return ovs_vport_ops_register(&ovs_vxlan_netdev_vport_ops);
|
||||
}
|
||||
|
||||
static void __exit ovs_vxlan_tnl_exit(void)
|
||||
{
|
||||
ovs_vport_ops_unregister(&ovs_vxlan_netdev_vport_ops);
|
||||
}
|
||||
|
||||
module_init(ovs_vxlan_tnl_init);
|
||||
module_exit(ovs_vxlan_tnl_exit);
|
||||
|
||||
MODULE_DESCRIPTION("OVS: VXLAN switching port");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("vport-type-4");
|
||||
@@ -57,7 +57,7 @@ static struct hlist_head *hash_bucket(const struct net *net, const char *name)
|
||||
return &dev_table[hash & (VPORT_HASH_BUCKETS - 1)];
|
||||
}
|
||||
|
||||
int __ovs_vport_ops_register(struct vport_ops *ops)
|
||||
int ovs_vport_ops_register(struct vport_ops *ops)
|
||||
{
|
||||
int err = -EEXIST;
|
||||
struct vport_ops *o;
|
||||
@@ -73,7 +73,6 @@ int __ovs_vport_ops_register(struct vport_ops *ops)
|
||||
ovs_unlock();
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__ovs_vport_ops_register);
|
||||
|
||||
void ovs_vport_ops_unregister(struct vport_ops *ops)
|
||||
{
|
||||
@@ -81,7 +80,6 @@ void ovs_vport_ops_unregister(struct vport_ops *ops)
|
||||
list_del(&ops->list);
|
||||
ovs_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ovs_vport_ops_unregister);
|
||||
|
||||
/**
|
||||
* ovs_vport_locate - find a port that has already been created
|
||||
@@ -210,14 +208,9 @@ struct vport *ovs_vport_add(const struct vport_parms *parms)
|
||||
if (ops) {
|
||||
struct hlist_head *bucket;
|
||||
|
||||
if (!try_module_get(ops->owner))
|
||||
return ERR_PTR(-EAFNOSUPPORT);
|
||||
|
||||
vport = ops->create(parms);
|
||||
if (IS_ERR(vport)) {
|
||||
module_put(ops->owner);
|
||||
if (IS_ERR(vport))
|
||||
return vport;
|
||||
}
|
||||
|
||||
bucket = hash_bucket(ovs_dp_get_net(vport->dp),
|
||||
ovs_vport_name(vport));
|
||||
@@ -225,34 +218,7 @@ struct vport *ovs_vport_add(const struct vport_parms *parms)
|
||||
return vport;
|
||||
}
|
||||
|
||||
/* Unlock to attempt module load and return -EAGAIN if load
|
||||
* was successful as we need to restart the port addition
|
||||
* workflow.
|
||||
*/
|
||||
ovs_unlock();
|
||||
request_module("vport-type-%d", parms->type);
|
||||
ovs_lock();
|
||||
|
||||
if (!ovs_vport_lookup(parms))
|
||||
return ERR_PTR(-EAFNOSUPPORT);
|
||||
else
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* ovs_vport_set_options - modify existing vport device (for kernel callers)
|
||||
*
|
||||
* @vport: vport to modify.
|
||||
* @options: New configuration.
|
||||
*
|
||||
* Modifies an existing device with the specified configuration (which is
|
||||
* dependent on device type). ovs_mutex must be held.
|
||||
*/
|
||||
int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
|
||||
{
|
||||
if (!vport->ops->set_options)
|
||||
return -EOPNOTSUPP;
|
||||
return vport->ops->set_options(vport, options);
|
||||
return ERR_PTR(-EAFNOSUPPORT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,7 +232,6 @@ int ovs_vport_set_options(struct vport *vport, struct nlattr *options)
|
||||
void ovs_vport_del(struct vport *vport)
|
||||
{
|
||||
hlist_del_rcu(&vport->hash_node);
|
||||
module_put(vport->ops->owner);
|
||||
vport->ops->destroy(vport);
|
||||
}
|
||||
|
||||
@@ -348,44 +313,6 @@ int ovs_vport_get_upcall_stats(struct vport *vport, struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ovs_vport_get_options - retrieve device options
|
||||
*
|
||||
* @vport: vport from which to retrieve the options.
|
||||
* @skb: sk_buff where options should be appended.
|
||||
*
|
||||
* Retrieves the configuration of the given device, appending an
|
||||
* %OVS_VPORT_ATTR_OPTIONS attribute that in turn contains nested
|
||||
* vport-specific attributes to @skb.
|
||||
*
|
||||
* Returns 0 if successful, -EMSGSIZE if @skb has insufficient room, or another
|
||||
* negative error code if a real error occurred. If an error occurs, @skb is
|
||||
* left unmodified.
|
||||
*
|
||||
* Must be called with ovs_mutex or rcu_read_lock.
|
||||
*/
|
||||
int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
int err;
|
||||
|
||||
if (!vport->ops->get_options)
|
||||
return 0;
|
||||
|
||||
nla = nla_nest_start_noflag(skb, OVS_VPORT_ATTR_OPTIONS);
|
||||
if (!nla)
|
||||
return -EMSGSIZE;
|
||||
|
||||
err = vport->ops->get_options(vport, skb);
|
||||
if (err) {
|
||||
nla_nest_cancel(skb, nla);
|
||||
return err;
|
||||
}
|
||||
|
||||
nla_nest_end(skb, nla);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ovs_vport_set_upcall_portids - set upcall portids of @vport.
|
||||
*
|
||||
|
||||
@@ -34,9 +34,6 @@ void ovs_vport_get_stats(struct vport *, struct ovs_vport_stats *);
|
||||
|
||||
int ovs_vport_get_upcall_stats(struct vport *vport, struct sk_buff *skb);
|
||||
|
||||
int ovs_vport_set_options(struct vport *, struct nlattr *options);
|
||||
int ovs_vport_get_options(const struct vport *, struct sk_buff *);
|
||||
|
||||
int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids);
|
||||
int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
|
||||
u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
|
||||
@@ -92,8 +89,6 @@ struct vport {
|
||||
*
|
||||
* @name: New vport's name.
|
||||
* @type: New vport's type.
|
||||
* @options: %OVS_VPORT_ATTR_OPTIONS attribute from Netlink message, %NULL if
|
||||
* none was supplied.
|
||||
* @desired_ifindex: New vport's ifindex.
|
||||
* @dp: New vport's datapath.
|
||||
* @port_no: New vport's port number.
|
||||
@@ -104,7 +99,6 @@ struct vport_parms {
|
||||
const char *name;
|
||||
enum ovs_vport_type type;
|
||||
int desired_ifindex;
|
||||
struct nlattr *options;
|
||||
|
||||
/* For ovs_vport_alloc(). */
|
||||
struct datapath *dp;
|
||||
@@ -120,14 +114,8 @@ struct vport_parms {
|
||||
* a new vport allocated with ovs_vport_alloc(), otherwise an ERR_PTR() value.
|
||||
* @destroy: Destroys a vport. Must call vport_free() on the vport but not
|
||||
* before an RCU grace period has elapsed.
|
||||
* @set_options: Modify the configuration of an existing vport. May be %NULL
|
||||
* if modification is not supported.
|
||||
* @get_options: Appends vport-specific attributes for the configuration of an
|
||||
* existing vport to a &struct sk_buff. May be %NULL for a vport that does not
|
||||
* have any configuration.
|
||||
* @send: Send a packet on the device.
|
||||
* zero for dropped packets or negative for error.
|
||||
* @owner: Module that implements this vport type.
|
||||
* @list: List entry in the global list of vport types.
|
||||
*/
|
||||
struct vport_ops {
|
||||
@@ -137,11 +125,7 @@ struct vport_ops {
|
||||
struct vport *(*create)(const struct vport_parms *);
|
||||
void (*destroy)(struct vport *);
|
||||
|
||||
int (*set_options)(struct vport *, struct nlattr *);
|
||||
int (*get_options)(const struct vport *, struct sk_buff *);
|
||||
|
||||
int (*send)(struct sk_buff *skb);
|
||||
struct module *owner;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
@@ -205,12 +189,7 @@ static inline const char *ovs_vport_name(struct vport *vport)
|
||||
return vport->dev->name;
|
||||
}
|
||||
|
||||
int __ovs_vport_ops_register(struct vport_ops *ops);
|
||||
#define ovs_vport_ops_register(ops) \
|
||||
({ \
|
||||
(ops)->owner = THIS_MODULE; \
|
||||
__ovs_vport_ops_register(ops); \
|
||||
})
|
||||
int ovs_vport_ops_register(struct vport_ops *ops);
|
||||
|
||||
void ovs_vport_ops_unregister(struct vport_ops *ops);
|
||||
void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto);
|
||||
|
||||
@@ -117,9 +117,6 @@ CONFIG_NFT_COMPAT=m
|
||||
CONFIG_NFT_NAT=m
|
||||
CONFIG_NUMA=y
|
||||
CONFIG_OPENVSWITCH=m
|
||||
CONFIG_OPENVSWITCH_GENEVE=m
|
||||
CONFIG_OPENVSWITCH_GRE=m
|
||||
CONFIG_OPENVSWITCH_VXLAN=m
|
||||
CONFIG_PAGE_POOL_STATS=y
|
||||
CONFIG_PROC_SYSCTL=y
|
||||
CONFIG_PSAMPLE=m
|
||||
|
||||
@@ -7,9 +7,6 @@ CONFIG_NET_IPGRE_DEMUX=m
|
||||
CONFIG_NF_CONNTRACK=m
|
||||
CONFIG_NF_CONNTRACK_OVS=y
|
||||
CONFIG_OPENVSWITCH=m
|
||||
CONFIG_OPENVSWITCH_GENEVE=m
|
||||
CONFIG_OPENVSWITCH_GRE=m
|
||||
CONFIG_OPENVSWITCH_VXLAN=m
|
||||
CONFIG_PSAMPLE=m
|
||||
CONFIG_VETH=y
|
||||
CONFIG_VLAN_8021Q=y
|
||||
|
||||
@@ -26,7 +26,6 @@ tests="
|
||||
netlink_checks ovsnl: validate netlink attrs and settings
|
||||
upcall_interfaces ovs: test the upcall interfaces
|
||||
tunnel_metadata ovs: test extraction of tunnel metadata
|
||||
tunnel_refcount ovs: test tunnel vport reference cleanup
|
||||
drop_reason drop: test drop reasons are emitted
|
||||
pop_vlan vlan: POP_VLAN action strips tag
|
||||
dec_ttl ttl: dec_ttl decrements IP TTL
|
||||
@@ -1210,43 +1209,6 @@ test_tunnel_metadata() {
|
||||
return 0
|
||||
}
|
||||
|
||||
test_tunnel_refcount() {
|
||||
sbxname="test_tunnel_refcount"
|
||||
sbx_add "${sbxname}" || return 1
|
||||
|
||||
ovs_sbx "${sbxname}" ip netns add trefns || return 1
|
||||
on_exit "ovs_sbx ${sbxname} ip netns del trefns"
|
||||
|
||||
for tun_type in gre vxlan geneve; do
|
||||
info "testing ${tun_type} tunnel vport refcount"
|
||||
|
||||
ovs_sbx "${sbxname}" ip netns exec trefns \
|
||||
python3 $ovs_base/ovs-dpctl.py \
|
||||
add-dp dp-${tun_type} || return 1
|
||||
|
||||
ovs_sbx "${sbxname}" ip netns exec trefns \
|
||||
python3 $ovs_base/ovs-dpctl.py \
|
||||
add-if --no-lwt -t ${tun_type} \
|
||||
dp-${tun_type} ovs-${tun_type}0 || return 1
|
||||
|
||||
ovs_wait ip -netns trefns link show \
|
||||
ovs-${tun_type}0 >/dev/null 2>&1 || return 1
|
||||
|
||||
info "deleting dp - may hang if reference counting is broken"
|
||||
ovs_sbx "${sbxname}" ip netns exec trefns \
|
||||
python3 $ovs_base/ovs-dpctl.py \
|
||||
del-dp dp-${tun_type} &
|
||||
|
||||
dev_removed() {
|
||||
! ip -netns trefns link show "$1" >/dev/null 2>&1
|
||||
}
|
||||
ovs_wait dev_removed dp-${tun_type} || return 1
|
||||
ovs_wait dev_removed ovs-${tun_type}0 || return 1
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
test_pop_vlan() {
|
||||
local sbx="test_pop_vlan"
|
||||
sbx_add "$sbx" || return $?
|
||||
|
||||
@@ -2364,9 +2364,6 @@ class OvsDatapath(GenericNetlinkSocket):
|
||||
class OvsVport(GenericNetlinkSocket):
|
||||
OVS_VPORT_TYPE_NETDEV = 1
|
||||
OVS_VPORT_TYPE_INTERNAL = 2
|
||||
OVS_VPORT_TYPE_GRE = 3
|
||||
OVS_VPORT_TYPE_VXLAN = 4
|
||||
OVS_VPORT_TYPE_GENEVE = 5
|
||||
|
||||
class ovs_vport_msg(ovs_dp_msg):
|
||||
nla_map = (
|
||||
@@ -2374,7 +2371,7 @@ class OvsVport(GenericNetlinkSocket):
|
||||
("OVS_VPORT_ATTR_PORT_NO", "uint32"),
|
||||
("OVS_VPORT_ATTR_TYPE", "uint32"),
|
||||
("OVS_VPORT_ATTR_NAME", "asciiz"),
|
||||
("OVS_VPORT_ATTR_OPTIONS", "vportopts"),
|
||||
("OVS_VPORT_ATTR_OPTIONS", "none"),
|
||||
("OVS_VPORT_ATTR_UPCALL_PID", "array(uint32)"),
|
||||
("OVS_VPORT_ATTR_STATS", "vportstats"),
|
||||
("OVS_VPORT_ATTR_PAD", "none"),
|
||||
@@ -2382,13 +2379,6 @@ class OvsVport(GenericNetlinkSocket):
|
||||
("OVS_VPORT_ATTR_NETNSID", "uint32"),
|
||||
)
|
||||
|
||||
class vportopts(nla):
|
||||
nla_map = (
|
||||
("OVS_TUNNEL_ATTR_UNSPEC", "none"),
|
||||
("OVS_TUNNEL_ATTR_DST_PORT", "uint16"),
|
||||
("OVS_TUNNEL_ATTR_EXTENSION", "none"),
|
||||
)
|
||||
|
||||
class vportstats(nla):
|
||||
fields = (
|
||||
("rx_packets", "=Q"),
|
||||
@@ -2406,25 +2396,13 @@ class OvsVport(GenericNetlinkSocket):
|
||||
return "netdev"
|
||||
elif vport_type == OvsVport.OVS_VPORT_TYPE_INTERNAL:
|
||||
return "internal"
|
||||
elif vport_type == OvsVport.OVS_VPORT_TYPE_GRE:
|
||||
return "gre"
|
||||
elif vport_type == OvsVport.OVS_VPORT_TYPE_VXLAN:
|
||||
return "vxlan"
|
||||
elif vport_type == OvsVport.OVS_VPORT_TYPE_GENEVE:
|
||||
return "geneve"
|
||||
raise ValueError("Unknown vport type:%d" % vport_type)
|
||||
|
||||
def str_to_type(vport_type):
|
||||
if vport_type == "netdev":
|
||||
if vport_type in ["netdev", "gre", "vxlan", "geneve"]:
|
||||
return OvsVport.OVS_VPORT_TYPE_NETDEV
|
||||
elif vport_type == "internal":
|
||||
return OvsVport.OVS_VPORT_TYPE_INTERNAL
|
||||
elif vport_type == "gre":
|
||||
return OvsVport.OVS_VPORT_TYPE_GRE
|
||||
elif vport_type == "vxlan":
|
||||
return OvsVport.OVS_VPORT_TYPE_VXLAN
|
||||
elif vport_type == "geneve":
|
||||
return OvsVport.OVS_VPORT_TYPE_GENEVE
|
||||
raise ValueError("Unknown vport type: '%s'" % vport_type)
|
||||
|
||||
def __init__(self, packet=OvsPacket()):
|
||||
@@ -2457,16 +2435,18 @@ class OvsVport(GenericNetlinkSocket):
|
||||
raise ne
|
||||
return reply
|
||||
|
||||
def attach(self, dpindex, vport_ifname, ptype, dport, lwt):
|
||||
def attach(self, dpindex, vport_ifname, ptype, dport):
|
||||
msg = OvsVport.ovs_vport_msg()
|
||||
|
||||
msg["cmd"] = OVS_VPORT_CMD_NEW
|
||||
msg["version"] = OVS_DATAPATH_VERSION
|
||||
msg["reserved"] = 0
|
||||
msg["dpifindex"] = dpindex
|
||||
port_type = OvsVport.str_to_type(ptype)
|
||||
|
||||
msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname])
|
||||
msg["attrs"].append(
|
||||
["OVS_VPORT_ATTR_TYPE", OvsVport.str_to_type(ptype)]
|
||||
)
|
||||
msg["attrs"].append(
|
||||
["OVS_VPORT_ATTR_UPCALL_PID", [self.upcall_packet.epid]]
|
||||
)
|
||||
@@ -2480,36 +2460,21 @@ class OvsVport(GenericNetlinkSocket):
|
||||
if not dport:
|
||||
dport = tnl[1]
|
||||
|
||||
if not lwt:
|
||||
if tnl[0] == "gre":
|
||||
# GRE tunnels have no options.
|
||||
break
|
||||
ipr = pyroute2.iproute.IPRoute()
|
||||
|
||||
vportopt = OvsVport.ovs_vport_msg.vportopts()
|
||||
vportopt["attrs"].append(
|
||||
["OVS_TUNNEL_ATTR_DST_PORT", dport]
|
||||
)
|
||||
msg["attrs"].append(
|
||||
["OVS_VPORT_ATTR_OPTIONS", vportopt]
|
||||
)
|
||||
else:
|
||||
port_type = OvsVport.OVS_VPORT_TYPE_NETDEV
|
||||
ipr = pyroute2.iproute.IPRoute()
|
||||
|
||||
if tnl[0] == "geneve":
|
||||
ipr.link("add", ifname=vport_ifname, kind=tnl[0],
|
||||
geneve_port=dport,
|
||||
geneve_collect_metadata=True,
|
||||
geneve_udp_zero_csum6_rx=1)
|
||||
elif tnl[0] == "gre":
|
||||
ipr.link("add", ifname=vport_ifname, kind="gretap",
|
||||
gre_collect_metadata=True)
|
||||
elif tnl[0] == "vxlan":
|
||||
ipr.link("add", ifname=vport_ifname, kind=tnl[0],
|
||||
vxlan_learning=0, vxlan_collect_metadata=1,
|
||||
vxlan_udp_zero_csum6_rx=1, vxlan_port=dport)
|
||||
if tnl[0] == "geneve":
|
||||
ipr.link("add", ifname=vport_ifname, kind=tnl[0],
|
||||
geneve_port=dport,
|
||||
geneve_collect_metadata=True,
|
||||
geneve_udp_zero_csum6_rx=1)
|
||||
elif tnl[0] == "gre":
|
||||
ipr.link("add", ifname=vport_ifname, kind="gretap",
|
||||
gre_collect_metadata=True)
|
||||
elif tnl[0] == "vxlan":
|
||||
ipr.link("add", ifname=vport_ifname, kind=tnl[0],
|
||||
vxlan_learning=0, vxlan_collect_metadata=1,
|
||||
vxlan_udp_zero_csum6_rx=1, vxlan_port=dport)
|
||||
break
|
||||
msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type])
|
||||
|
||||
try:
|
||||
reply = self.nlm_request(
|
||||
@@ -2937,19 +2902,12 @@ def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()):
|
||||
for iface in ndb.interfaces:
|
||||
rep = vpl.info(iface.ifname, ifindex)
|
||||
if rep is not None:
|
||||
opts = ""
|
||||
vpo = rep.get_attr("OVS_VPORT_ATTR_OPTIONS")
|
||||
if vpo:
|
||||
dpo = vpo.get_attr("OVS_TUNNEL_ATTR_DST_PORT")
|
||||
if dpo:
|
||||
opts += " tnl-dport:%s" % dpo
|
||||
print(
|
||||
" port %d: %s (%s%s)"
|
||||
" port %d: %s (%s)"
|
||||
% (
|
||||
rep.get_attr("OVS_VPORT_ATTR_PORT_NO"),
|
||||
rep.get_attr("OVS_VPORT_ATTR_NAME"),
|
||||
OvsVport.type_to_str(rep.get_attr("OVS_VPORT_ATTR_TYPE")),
|
||||
opts,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -3022,13 +2980,6 @@ def main(argv):
|
||||
default=0,
|
||||
help="Destination port (0 for default)"
|
||||
)
|
||||
addifcmd.add_argument(
|
||||
"-l",
|
||||
"--lwt",
|
||||
action=argparse.BooleanOptionalAction,
|
||||
default=True,
|
||||
help="Use LWT infrastructure instead of vport (default true)."
|
||||
)
|
||||
delifcmd = subparsers.add_parser("del-if")
|
||||
delifcmd.add_argument("dpname", help="Datapath Name")
|
||||
delifcmd.add_argument("delif", help="Interface name for adding")
|
||||
@@ -3108,7 +3059,7 @@ def main(argv):
|
||||
return 1
|
||||
dpindex = rep["dpifindex"]
|
||||
rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype,
|
||||
args.dport, args.lwt)
|
||||
args.dport)
|
||||
msg = "vport '%s'" % args.addif
|
||||
if rep and rep["header"]["error"] is None:
|
||||
msg += " added."
|
||||
|
||||
Reference in New Issue
Block a user