@@ -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:
@@ -463,3 +463,41 @@ 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)
+{
+ struct netdev *netdev = NULL;
+ bool out_of_tree = false;
+ int error;
+
+ error = netdev_open("ovs-system-probe", "geneve", &netdev);
+ if (!error) {
+ error = dpif_netlink_rtnl_geneve_create_kind(netdev, "ovs_geneve");
+ if (error != EOPNOTSUPP) {
+ if (!error) {
+ char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
+ const char *dp_port;
+
+ dp_port = netdev_vport_get_dpif_port(netdev, namebuf,
+ sizeof namebuf);
+ dpif_netlink_rtnl_geneve_destroy(dp_port);
+ }
+ 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_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 */
@@ -211,6 +211,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 *,
@@ -947,7 +953,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)
@@ -981,10 +987,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;
@@ -1019,6 +1030,12 @@ dpif_netlink_port_del__(struct dpif_netlink *dpif, odp_port_t 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;
@@ -2532,6 +2549,8 @@ dpif_netlink_init(void)
&ovs_vport_mcgroup);
}
+ ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels();
+
ovsthread_once_done(&once);
}
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> --- NEWS | 3 +++ lib/dpif-netlink-rtnl.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/dpif-netlink-rtnl.h | 8 ++++++++ lib/dpif-netlink.c | 25 ++++++++++++++++++++++--- 4 files changed, 71 insertions(+), 3 deletions(-)