mirror of
https://github.com/openvswitch/ovs
synced 2025-09-04 16:25: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:
committed by
Joe Stringer
parent
b6d6830d29
commit
921c370a9d
3
NEWS
3
NEWS
@@ -3,6 +3,9 @@ Post-v2.7.0
|
|||||||
- Tunnels:
|
- Tunnels:
|
||||||
* Added support to set packet mark for tunnel endpoint using
|
* Added support to set packet mark for tunnel endpoint using
|
||||||
`egress_pkt_mark` OVSDB option.
|
`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
|
- EMC insertion probability is reduced to 1% and is configurable via
|
||||||
the new 'other_config:emc-insert-inv-prob' option.
|
the new 'other_config:emc-insert-inv-prob' option.
|
||||||
- DPDK:
|
- DPDK:
|
||||||
|
@@ -419,3 +419,49 @@ dpif_netlink_rtnl_port_destroy(const char *name, const char *type)
|
|||||||
}
|
}
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
int dpif_netlink_rtnl_port_create(struct netdev *netdev);
|
int dpif_netlink_rtnl_port_create(struct netdev *netdev);
|
||||||
int dpif_netlink_rtnl_port_destroy(const char *name, const char *type);
|
int dpif_netlink_rtnl_port_destroy(const char *name, const char *type);
|
||||||
|
|
||||||
|
bool dpif_netlink_rtnl_probe_oot_tunnels(void);
|
||||||
|
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
/* Dummy implementations for non Linux builds. */
|
/* Dummy implementations for non Linux builds. */
|
||||||
|
|
||||||
@@ -41,6 +43,12 @@ dpif_netlink_rtnl_port_destroy(const char *name OVS_UNUSED,
|
|||||||
return EOPNOTSUPP;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
dpif_netlink_rtnl_probe_oot_tunnels(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* DPIF_NETLINK_RTNL_H */
|
#endif /* DPIF_NETLINK_RTNL_H */
|
||||||
|
@@ -62,9 +62,6 @@ VLOG_DEFINE_THIS_MODULE(dpif_netlink);
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "wmi.h"
|
#include "wmi.h"
|
||||||
enum { WINDOWS = 1 };
|
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
|
#else
|
||||||
enum { WINDOWS = 0 };
|
enum { WINDOWS = 0 };
|
||||||
#endif
|
#endif
|
||||||
@@ -215,6 +212,12 @@ static int ovs_packet_family;
|
|||||||
* Initialized by dpif_netlink_init(). */
|
* Initialized by dpif_netlink_init(). */
|
||||||
static unsigned int ovs_vport_mcgroup;
|
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 dpif_netlink_init(void);
|
||||||
static int open_dpif(const struct dpif_netlink_dp *, struct dpif **);
|
static int open_dpif(const struct dpif_netlink_dp *, struct dpif **);
|
||||||
static uint32_t dpif_netlink_port_get_pid(const 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 *);
|
struct ofpbuf *);
|
||||||
static int dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *,
|
static int dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *,
|
||||||
const struct ofpbuf *);
|
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 *
|
static struct dpif_netlink *
|
||||||
dpif_netlink_cast(const struct dpif *dpif)
|
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,
|
dpif_netlink_rtnl_port_create_and_add(struct dpif_netlink *dpif,
|
||||||
struct netdev *netdev,
|
struct netdev *netdev,
|
||||||
odp_port_t *port_nop)
|
odp_port_t *port_nop)
|
||||||
@@ -982,10 +988,15 @@ dpif_netlink_port_add(struct dpif *dpif_, struct netdev *netdev,
|
|||||||
odp_port_t *port_nop)
|
odp_port_t *port_nop)
|
||||||
{
|
{
|
||||||
struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
|
struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
|
||||||
int error;
|
int error = EOPNOTSUPP;
|
||||||
|
|
||||||
fat_rwlock_wrlock(&dpif->upcall_lock);
|
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);
|
fat_rwlock_unlock(&dpif->upcall_lock);
|
||||||
|
|
||||||
return error;
|
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)
|
OVS_REQ_WRLOCK(dpif->upcall_lock)
|
||||||
{
|
{
|
||||||
struct dpif_netlink_vport vport;
|
struct dpif_netlink_vport vport;
|
||||||
|
struct dpif_port dpif_port;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
error = dpif_netlink_port_query__(dpif, port_no, NULL, &dpif_port);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
dpif_netlink_vport_init(&vport);
|
dpif_netlink_vport_init(&vport);
|
||||||
vport.cmd = OVS_VPORT_CMD_DEL;
|
vport.cmd = OVS_VPORT_CMD_DEL;
|
||||||
vport.dp_ifindex = dpif->dp_ifindex;
|
vport.dp_ifindex = dpif->dp_ifindex;
|
||||||
vport.port_no = port_no;
|
vport.port_no = port_no;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
struct dpif_port temp_dpif_port;
|
if (!strcmp(dpif_port.type, "internal")) {
|
||||||
|
if (!delete_wmi_port(dpif_port.name)) {
|
||||||
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)){
|
|
||||||
VLOG_ERR("Could not delete wmi port with name: %s",
|
VLOG_ERR("Could not delete wmi port with name: %s",
|
||||||
temp_dpif_port.name);
|
dpif_port.name);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
dpif_port_destroy(&temp_dpif_port);
|
|
||||||
#endif
|
#endif
|
||||||
error = dpif_netlink_vport_transact(&vport, NULL, NULL);
|
error = dpif_netlink_vport_transact(&vport, NULL, NULL);
|
||||||
|
|
||||||
vport_del_channels(dpif, port_no);
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2549,6 +2568,8 @@ dpif_netlink_init(void)
|
|||||||
&ovs_vport_mcgroup);
|
&ovs_vport_mcgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels();
|
||||||
|
|
||||||
ovsthread_once_done(&once);
|
ovsthread_once_done(&once);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user