2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-02 07:15:17 +00:00

dpif-netlink: Probe for out-of-tree tunnels, decides used interface

On dpif init, probe for whether tunnels are created using in-tree
(upstream linux) or out-of-tree (OVS). This is done by probing for the
existence of "ovs_geneve" via rtnetlink. This is used to determine how
to create the tunnel devices.

For out-of-tree tunnels, only try genetlink/compat.
For in-tree kernel tunnels, try rtnetlink then fallback to genetlink.

Signed-off-by: Eric Garver <e@erig.me>
Signed-off-by: Joe Stringer <joe@ovn.org>
This commit is contained in:
Eric Garver
2017-05-18 16:10:33 -04:00
committed by Joe Stringer
parent b6d6830d29
commit 921c370a9d
4 changed files with 94 additions and 16 deletions

3
NEWS
View File

@@ -3,6 +3,9 @@ Post-v2.7.0
- Tunnels:
* Added support to set packet mark for tunnel endpoint using
`egress_pkt_mark` OVSDB option.
* When using Linux kernel datapath tunnels may be created using rtnetlink.
This will allow us to take advantage of new tunnel features without
having to make changes to the vport modules.
- EMC insertion probability is reduced to 1% and is configurable via
the new 'other_config:emc-insert-inv-prob' option.
- DPDK:

View File

@@ -419,3 +419,49 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type)
}
return 0;
}
/**
* Probe for whether the modules are out-of-tree (openvswitch) or in-tree
* (upstream kernel).
*
* We probe for "ovs_geneve" via rtnetlink. As long as this returns something
* other than EOPNOTSUPP we know that the module in use is the out-of-tree one.
* This will be used to determine which netlink interface to use when creating
* ports; rtnetlink or compat/genetlink.
*
* See ovs_tunnels_out_of_tree
*/
bool
dpif_netlink_rtnl_probe_oot_tunnels(void)
{
char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
struct netdev *netdev = NULL;
bool out_of_tree = false;
const char *name;
int error;
error = netdev_open("ovs-system-probe", "geneve", &netdev);
if (!error) {
const struct netdev_tunnel_config *tnl_cfg;
tnl_cfg = netdev_get_tunnel_config(netdev);
if (!tnl_cfg) {
return true;
}
name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
error = dpif_netlink_rtnl_create(tnl_cfg, name, OVS_VPORT_TYPE_GENEVE,
"ovs_geneve",
(NLM_F_REQUEST | NLM_F_ACK
| NLM_F_CREATE));
if (error != EOPNOTSUPP) {
if (!error) {
dpif_netlink_rtnl_destroy(name);
}
out_of_tree = true;
}
netdev_close(netdev);
}
return out_of_tree;
}

View File

@@ -25,6 +25,8 @@
int dpif_netlink_rtnl_port_create(struct netdev *netdev);
int dpif_netlink_rtnl_port_destroy(const char *name, const char *type);
bool dpif_netlink_rtnl_probe_oot_tunnels(void);
#ifndef __linux__
/* Dummy implementations for non Linux builds. */
@@ -41,6 +43,12 @@ dpif_netlink_rtnl_port_destroy(const char *name OVS_UNUSED,
return EOPNOTSUPP;
}
static inline bool
dpif_netlink_rtnl_probe_oot_tunnels(void)
{
return true;
}
#endif
#endif /* DPIF_NETLINK_RTNL_H */

View File

@@ -62,9 +62,6 @@ VLOG_DEFINE_THIS_MODULE(dpif_netlink);
#ifdef _WIN32
#include "wmi.h"
enum { WINDOWS = 1 };
static int dpif_netlink_port_query__(const struct dpif_netlink *dpif,
odp_port_t port_no, const char *port_name,
struct dpif_port *dpif_port);
#else
enum { WINDOWS = 0 };
#endif
@@ -215,6 +212,12 @@ static int ovs_packet_family;
* Initialized by dpif_netlink_init(). */
static unsigned int ovs_vport_mcgroup;
/* If true, tunnel devices are created using OVS compat/genetlink.
* If false, tunnel devices are created with rtnetlink and using light weight
* tunnels. If we fail to create the tunnel the rtnetlink+LWT, then we fallback
* to using the compat interface. */
static bool ovs_tunnels_out_of_tree = true;
static int dpif_netlink_init(void);
static int open_dpif(const struct dpif_netlink_dp *, struct dpif **);
static uint32_t dpif_netlink_port_get_pid(const struct dpif *,
@@ -226,6 +229,9 @@ static void dpif_netlink_vport_to_ofpbuf(const struct dpif_netlink_vport *,
struct ofpbuf *);
static int dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *,
const struct ofpbuf *);
static int dpif_netlink_port_query__(const struct dpif_netlink *dpif,
odp_port_t port_no, const char *port_name,
struct dpif_port *dpif_port);
static struct dpif_netlink *
dpif_netlink_cast(const struct dpif *dpif)
@@ -948,7 +954,7 @@ dpif_netlink_port_add_compat(struct dpif_netlink *dpif, struct netdev *netdev,
}
static int OVS_UNUSED
static int
dpif_netlink_rtnl_port_create_and_add(struct dpif_netlink *dpif,
struct netdev *netdev,
odp_port_t *port_nop)
@@ -982,10 +988,15 @@ dpif_netlink_port_add(struct dpif *dpif_, struct netdev *netdev,
odp_port_t *port_nop)
{
struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
int error;
int error = EOPNOTSUPP;
fat_rwlock_wrlock(&dpif->upcall_lock);
error = dpif_netlink_port_add_compat(dpif, netdev, port_nop);
if (!ovs_tunnels_out_of_tree) {
error = dpif_netlink_rtnl_port_create_and_add(dpif, netdev, port_nop);
}
if (error) {
error = dpif_netlink_port_add_compat(dpif, netdev, port_nop);
}
fat_rwlock_unlock(&dpif->upcall_lock);
return error;
@@ -996,31 +1007,39 @@ dpif_netlink_port_del__(struct dpif_netlink *dpif, odp_port_t port_no)
OVS_REQ_WRLOCK(dpif->upcall_lock)
{
struct dpif_netlink_vport vport;
struct dpif_port dpif_port;
int error;
error = dpif_netlink_port_query__(dpif, port_no, NULL, &dpif_port);
if (error) {
return error;
}
dpif_netlink_vport_init(&vport);
vport.cmd = OVS_VPORT_CMD_DEL;
vport.dp_ifindex = dpif->dp_ifindex;
vport.port_no = port_no;
#ifdef _WIN32
struct dpif_port temp_dpif_port;
error = dpif_netlink_port_query__(dpif, port_no, NULL, &temp_dpif_port);
if (error) {
return error;
}
if (!strcmp(temp_dpif_port.type, "internal")) {
if (!delete_wmi_port(temp_dpif_port.name)){
if (!strcmp(dpif_port.type, "internal")) {
if (!delete_wmi_port(dpif_port.name)) {
VLOG_ERR("Could not delete wmi port with name: %s",
temp_dpif_port.name);
dpif_port.name);
};
}
dpif_port_destroy(&temp_dpif_port);
#endif
error = dpif_netlink_vport_transact(&vport, NULL, NULL);
vport_del_channels(dpif, port_no);
if (!error && !ovs_tunnels_out_of_tree) {
error = dpif_netlink_rtnl_port_destroy(dpif_port.name, dpif_port.type);
if (error == EOPNOTSUPP) {
error = 0;
}
}
dpif_port_destroy(&dpif_port);
return error;
}
@@ -2549,6 +2568,8 @@ dpif_netlink_init(void)
&ovs_vport_mcgroup);
}
ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels();
ovsthread_once_done(&once);
}