[ovs-dev] [PATCH v3 3/5] dpif-netlink: add VXLAN creation support

Thadeu Lima de Souza Cascardo cascardo at redhat.com
Wed Jun 22 15:47:40 UTC 2016


Creates VXLAN devices using rtnetlink and tunnel metadata. If the kernel does
not support tunnel metadata, it will return EINVAL because of the missing VNI
attribute.

This was tested on kernels 4.2.3, 4.3.6, 4.4.9, 4.5.5 and RHEL-based 3.10. All
of them worked with the system traffic test "datapath - ping over vxlan tunnel".

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at redhat.com>
---
 lib/dpif-netlink.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 119 insertions(+), 1 deletion(-)

diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index b624118..b8b908f 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -24,7 +24,9 @@
 #include <inttypes.h>
 #include <net/if.h>
 #include <linux/types.h>
+#include <linux/ip.h>
 #include <linux/pkt_sched.h>
+#include <linux/rtnetlink.h>
 #include <poll.h>
 #include <stdlib.h>
 #include <strings.h>
@@ -931,6 +933,120 @@ dpif_netlink_port_add_compat(struct dpif_netlink *dpif, struct netdev *netdev,
 
 }
 
+#ifdef __linux__
+
+static int
+netdev_linux_destroy(const char *name)
+{
+    int err;
+    struct ofpbuf request, *reply;
+
+    ofpbuf_init(&request, 0);
+    nl_msg_put_nlmsghdr(&request, 0, RTM_DELLINK,
+                        NLM_F_REQUEST | NLM_F_ACK);
+    ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
+    nl_msg_put_string(&request, IFLA_IFNAME, name);
+
+    err = nl_transact(NETLINK_ROUTE, &request, &reply);
+
+    if (!err) {
+        ofpbuf_uninit(reply);
+    }
+
+    ofpbuf_uninit(&request);
+    return err;
+}
+
+static int
+netdev_vxlan_destroy(const char *name)
+{
+    return netdev_linux_destroy(name);
+}
+
+/*
+ * On some older systems, these enums are not defined.
+ */
+
+#ifndef IFLA_VXLAN_MAX
+#define IFLA_VXLAN_MAX 0
+#define IFLA_VXLAN_PORT 15
+#endif
+#if IFLA_VXLAN_MAX < 20
+#define IFLA_VXLAN_UDP_ZERO_CSUM6_RX 20
+#define IFLA_VXLAN_GBP 23
+#define IFLA_VXLAN_COLLECT_METADATA 25
+#endif
+
+static int
+netdev_vxlan_create(struct netdev *netdev)
+{
+    int err;
+    struct ofpbuf request, *reply;
+    size_t linkinfo_off, infodata_off;
+    char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
+    const char *name = netdev_vport_get_dpif_port(netdev,
+                                                  namebuf, sizeof namebuf);
+    struct ifinfomsg *ifinfo;
+    const struct netdev_tunnel_config *tnl_cfg;
+    tnl_cfg = netdev_get_tunnel_config(netdev);
+    if (!tnl_cfg) { /* or assert? */
+        return EINVAL;
+    }
+
+    ofpbuf_init(&request, 0);
+    nl_msg_put_nlmsghdr(&request, 0, RTM_NEWLINK,
+                        NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE);
+    ifinfo = ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
+    ifinfo->ifi_change = ifinfo->ifi_flags = IFF_UP;
+    nl_msg_put_string(&request, IFLA_IFNAME, name);
+    nl_msg_put_u32(&request, IFLA_MTU, UINT16_MAX);
+    linkinfo_off = nl_msg_start_nested(&request, IFLA_LINKINFO);
+        nl_msg_put_string(&request, IFLA_INFO_KIND, "vxlan");
+        infodata_off = nl_msg_start_nested(&request, IFLA_INFO_DATA);
+            nl_msg_put_u8(&request, IFLA_VXLAN_LEARNING, 0);
+            nl_msg_put_u8(&request, IFLA_VXLAN_COLLECT_METADATA, 1);
+            nl_msg_put_u8(&request, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 1);
+            if (tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GBP)) {
+                nl_msg_put_flag(&request, IFLA_VXLAN_GBP);
+            }
+            nl_msg_put_be16(&request, IFLA_VXLAN_PORT, tnl_cfg->dst_port);
+        nl_msg_end_nested(&request, infodata_off);
+    nl_msg_end_nested(&request, linkinfo_off);
+
+    err = nl_transact(NETLINK_ROUTE, &request, &reply);
+
+    if (!err) {
+        ofpbuf_uninit(reply);
+    }
+
+    /*
+     * Linux versions older than 4.3 will return EINVAL in case the VID is not
+     * set, which is sufficient to verify COLLECT_METADATA is supported.
+     */
+    if (err == EINVAL) {
+        err = EOPNOTSUPP;
+    }
+
+    ofpbuf_uninit(&request);
+    return err;
+}
+
+#else
+
+static int
+netdev_vxlan_create(struct netdev *netdev OVS_UNUSED)
+{
+    return EOPNOTSUPP;
+}
+
+static int
+netdev_vxlan_destroy(const char *name OVS_UNUSED)
+{
+    return EOPNOTSUPP;
+}
+
+#endif
+
 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);
@@ -940,6 +1056,7 @@ dpif_netlink_port_create(struct netdev *netdev)
 {
     switch (netdev_to_ovs_vport_type(netdev_get_type(netdev))) {
     case OVS_VPORT_TYPE_VXLAN:
+        return netdev_vxlan_create(netdev);
     case OVS_VPORT_TYPE_GRE:
     case OVS_VPORT_TYPE_GENEVE:
     case OVS_VPORT_TYPE_NETDEV:
@@ -955,10 +1072,11 @@ dpif_netlink_port_create(struct netdev *netdev)
 }
 
 static int
-dpif_netlink_port_destroy(const char *name OVS_UNUSED, const char *type)
+dpif_netlink_port_destroy(const char *name, const char *type)
 {
     switch (netdev_to_ovs_vport_type(type)) {
     case OVS_VPORT_TYPE_VXLAN:
+        return netdev_vxlan_destroy(name);
     case OVS_VPORT_TYPE_GRE:
     case OVS_VPORT_TYPE_GENEVE:
     case OVS_VPORT_TYPE_NETDEV:
-- 
2.7.4




More information about the dev mailing list