From: Thadeu Lima de Souza Cascardo Date: Thu, 26 May 2016 14:21:36 +0000 (-0300) Subject: dpif-netlink: add GENEVE creation support X-Git-Url: http://git.cascardo.eti.br/?p=cascardo%2Fovs.git;a=commitdiff_plain;h=eda4695914839162b140b127a4169766058c957b dpif-netlink: add GENEVE creation support Creates GENEVE devices using rtnetlink and tunnel metadata. If the kernel does not support tunnel metadata, it will return EINVAL because of the missing ID and REMOTE attributes. This was tested on kernels 4.2.3, 4.3.6, 4.4.9 and 4.5.5. All of them worked with the system traffic test "datapath - ping over geneve tunnel". Signed-off-by: Thadeu Lima de Souza Cascardo --- diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 5f1b8671e..c99d7dae6 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -970,6 +970,12 @@ netdev_gre_destroy(const char *name) return netdev_linux_destroy(name); } +static int +netdev_geneve_destroy(const char *name) +{ + return netdev_linux_destroy(name); +} + /* * On some older systems, these enums are not defined. */ @@ -988,6 +994,18 @@ netdev_gre_destroy(const char *name) #define IFLA_GRE_COLLECT_METADATA 18 #endif +#ifndef IFLA_GENEVE_MAX +#define IFLA_GENEVE_MAX 0 +#define IFLA_GENEVE_PORT 5 +#endif + +#if IFLA_GENEVE_MAX < 6 +#define IFLA_GENEVE_COLLECT_METADATA 6 +#endif +#if IFLA_GENEVE_MAX < 10 +#define IFLA_GENEVE_UDP_ZERO_CSUM6_RX 10 +#endif + static int netdev_vxlan_create(struct netdev *netdev) { @@ -1151,6 +1169,56 @@ netdev_gre_create(struct netdev *netdev) return err; } +static int +netdev_geneve_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, "geneve"); + infodata_off = nl_msg_start_nested(&request, IFLA_INFO_DATA); + nl_msg_put_flag(&request, IFLA_GENEVE_COLLECT_METADATA); + nl_msg_put_u8(&request, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, 1); + nl_msg_put_be16(&request, IFLA_GENEVE_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 GENEVE_ID 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 @@ -1165,6 +1233,12 @@ netdev_gre_create(struct netdev *netdev OVS_UNUSED) return EOPNOTSUPP; } +static int +netdev_geneve_create(struct netdev *netdev OVS_UNUSED) +{ + return EOPNOTSUPP; +} + static int netdev_vxlan_destroy(const char *name OVS_UNUSED) { @@ -1177,6 +1251,12 @@ netdev_gre_destroy(const char *name OVS_UNUSED) return EOPNOTSUPP; } +static int +netdev_geneve_destroy(const char *name OVS_UNUSED) +{ + return EOPNOTSUPP; +} + #endif static int @@ -1192,6 +1272,7 @@ dpif_netlink_port_create(struct netdev *netdev) case OVS_VPORT_TYPE_GRE: return netdev_gre_create(netdev); case OVS_VPORT_TYPE_GENEVE: + return netdev_geneve_create(netdev); case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: @@ -1213,6 +1294,7 @@ dpif_netlink_port_destroy(const char *name, const char *type) case OVS_VPORT_TYPE_GRE: return netdev_gre_destroy(name); case OVS_VPORT_TYPE_GENEVE: + return netdev_geneve_destroy(name); case OVS_VPORT_TYPE_NETDEV: case OVS_VPORT_TYPE_INTERNAL: case OVS_VPORT_TYPE_LISP: