Commit 42df06e5 authored by Dan Winship's avatar Dan Winship

platform, devices: add support for vxlan devices

Since vxlan is new-ish, and vxlan IPv6 support in particular has only
been in the kernel since 3.11, we include our own copy of the vxlan
netlink constants rather than depending on the installed headers.
parent b1adf22e
......@@ -58,6 +58,7 @@
#define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth"
#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun"
#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan"
#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan"
#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre"
......
......@@ -20,6 +20,7 @@ EXTRA_DIST = \
nm-device-veth.xml \
nm-device-tun.xml \
nm-device-macvlan.xml \
nm-device-vxlan.xml \
nm-device-gre.xml \
nm-device.xml \
nm-ip4-config.xml \
......
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.Device.Vxlan">
<property name="Parent" type="o" access="read">
<tp:docstring>
The object path of the parent device (if the VXLAN is not
purely internal to this host).
</tp:docstring>
</property>
<property name="Id" type="u" access="read">
<tp:docstring>
The VXLAN Network Identifier (VNI).
</tp:docstring>
</property>
<property name="Group" type="s" access="read">
<tp:docstring>
The IP (v4 or v6) multicast group used to communicate with other physical
hosts on this VXLAN.
</tp:docstring>
</property>
<property name="Local" type="s" access="read">
<tp:docstring>
The local IPv4 or IPv6 address to use when sending VXLAN packets to other
physical hosts.
</tp:docstring>
</property>
<property name="Tos" type="y" access="read">
<tp:docstring>
The value to use in the IP ToS field for VXLAN packets sent to
other physical hosts.
</tp:docstring>
</property>
<property name="Ttl" type="y" access="read">
<tp:docstring>
The value to use in the IP TTL field for VXLAN packets sent to
other physical hosts.
</tp:docstring>
</property>
<property name="Learning" type="b" access="read">
<tp:docstring>
True if the VXLAN dynamically learns remote IP addresses.
</tp:docstring>
</property>
<property name="Ageing" type="u" access="read">
<tp:docstring>
The interval at which the kernel purges stale cached addresses
(in kernel jiffies, ie, centiseconds).
</tp:docstring>
</property>
<property name="Limit" type="u" access="read">
<tp:docstring>
The maximum number of entries that can be added to the VXLAN's
forwarding table.
</tp:docstring>
</property>
<property name="DstPort" type="q" access="read">
<tp:docstring>
Destination port for outgoing VXLAN packets.
</tp:docstring>
</property>
<property name="SrcPortMin" type="q" access="read">
<tp:docstring>
The lowest source port number to use for outgoing VXLAN packets.
</tp:docstring>
</property>
<property name="SrcPortMax" type="q" access="read">
<tp:docstring>
The highest source port number to use for outgoing VXLAN packets.
</tp:docstring>
</property>
<property name="Proxy" type="b" access="read">
<tp:docstring>
True if the VXLAN is implementing DOVE ARP proxying for remote
clients.
</tp:docstring>
</property>
<property name="Rsc" type="b" access="read">
<tp:docstring>
True if the VXLAN is implementing DOVE route short-circuiting
of known remote IP addresses.
</tp:docstring>
</property>
<property name="L2miss" type="b" access="read">
<tp:docstring>
True if the VXLAN will emit netlink notifications of L2 switch
misses.
</tp:docstring>
</property>
<property name="L3miss" type="b" access="read">
<tp:docstring>
True if the VXLAN will emit netlink notifications of L3 switch
misses.
</tp:docstring>
</property>
<signal name="PropertiesChanged">
<arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
<tp:docstring>
A dictionary mapping property names to variant boxed values
</tp:docstring>
</arg>
</signal>
</interface>
</node>
......@@ -88,6 +88,8 @@ nm_sources = \
devices/nm-device-veth.h \
devices/nm-device-vlan.c \
devices/nm-device-vlan.h \
devices/nm-device-vxlan.c \
devices/nm-device-vxlan.h \
devices/nm-device-wifi.c \
devices/nm-device-wifi.h \
\
......@@ -302,6 +304,7 @@ glue_sources = \
nm-device-tun-glue.h \
nm-device-veth-glue.h \
nm-device-vlan-glue.h \
nm-device-vxlan-glue.h \
nm-device-wifi-glue.h \
nm-dhcp4-config-glue.h \
nm-dhcp6-config-glue.h \
......
This diff is collapsed.
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2013, 2014 Red Hat, Inc.
*/
#ifndef NM_DEVICE_VXLAN_H
#define NM_DEVICE_VXLAN_H
#include <glib-object.h>
#include "nm-device-generic.h"
G_BEGIN_DECLS
#define NM_TYPE_DEVICE_VXLAN (nm_device_vxlan_get_type ())
#define NM_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlan))
#define NM_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass))
#define NM_IS_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VXLAN))
#define NM_IS_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VXLAN))
#define NM_DEVICE_VXLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass))
#define NM_DEVICE_VXLAN_PARENT "parent"
#define NM_DEVICE_VXLAN_ID "id"
#define NM_DEVICE_VXLAN_GROUP "group"
#define NM_DEVICE_VXLAN_LOCAL "local"
#define NM_DEVICE_VXLAN_TOS "tos"
#define NM_DEVICE_VXLAN_TTL "ttl"
#define NM_DEVICE_VXLAN_LEARNING "learning"
#define NM_DEVICE_VXLAN_AGEING "ageing"
#define NM_DEVICE_VXLAN_LIMIT "limit"
#define NM_DEVICE_VXLAN_DST_PORT "dst-port"
#define NM_DEVICE_VXLAN_SRC_PORT_MIN "src-port-min"
#define NM_DEVICE_VXLAN_SRC_PORT_MAX "src-port-max"
#define NM_DEVICE_VXLAN_PROXY "proxy"
#define NM_DEVICE_VXLAN_RSC "rsc"
#define NM_DEVICE_VXLAN_L2MISS "l2miss"
#define NM_DEVICE_VXLAN_L3MISS "l3miss"
typedef struct {
NMDeviceGeneric parent;
} NMDeviceVxlan;
typedef struct {
NMDeviceGenericClass parent;
} NMDeviceVxlanClass;
GType nm_device_vxlan_get_type (void);
NMDevice *nm_device_vxlan_new (NMPlatformLink *platform_device);
G_END_DECLS
#endif /* NM_DEVICE_VXLAN_H */
......@@ -52,6 +52,7 @@
#include "nm-device-veth.h"
#include "nm-device-tun.h"
#include "nm-device-macvlan.h"
#include "nm-device-vxlan.h"
#include "nm-device-gre.h"
#include "nm-setting-connection.h"
#include "nm-setting-wireless.h"
......@@ -2155,6 +2156,9 @@ platform_link_added_cb (NMPlatform *platform,
case NM_LINK_TYPE_MACVTAP:
device = nm_device_macvlan_new (plink);
break;
case NM_LINK_TYPE_VXLAN:
device = nm_device_vxlan_new (plink);
break;
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
device = nm_device_gre_new (plink);
......
......@@ -666,6 +666,12 @@ macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProp
return FALSE;
}
static gboolean
vxlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformVxlanProperties *props)
{
return FALSE;
}
static gboolean
gre_get_properties (NMPlatform *platform, int ifindex, NMPlatformGreProperties *props)
{
......@@ -1219,6 +1225,7 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->veth_get_properties = veth_get_properties;
platform_class->tun_get_properties = tun_get_properties;
platform_class->macvlan_get_properties = macvlan_get_properties;
platform_class->vxlan_get_properties = vxlan_get_properties;
platform_class->gre_get_properties = gre_get_properties;
platform_class->ip4_address_get_all = ip4_address_get_all;
......
......@@ -532,6 +532,8 @@ type_to_string (NMLinkType type)
return "veth";
case NM_LINK_TYPE_VLAN:
return "vlan";
case NM_LINK_TYPE_VXLAN:
return "vxlan";
case NM_LINK_TYPE_BRIDGE:
return "bridge";
case NM_LINK_TYPE_BOND:
......@@ -608,6 +610,7 @@ link_is_software (struct rtnl_link *rtnllink)
!strcmp (type, "tun") ||
!strcmp (type, "veth") ||
!strcmp (type, "vlan") ||
!strcmp (type, "vxlan") ||
!strcmp (type, "bridge") ||
!strcmp (type, "bond") ||
!strcmp (type, "team"))
......@@ -718,6 +721,8 @@ link_extract_type (NMPlatform *platform, struct rtnl_link *rtnllink, const char
return_type (NM_LINK_TYPE_VETH, "veth");
else if (!strcmp (type, "vlan"))
return_type (NM_LINK_TYPE_VLAN, "vlan");
else if (!strcmp (type, "vxlan"))
return_type (NM_LINK_TYPE_VXLAN, "vxlan");
else if (!strcmp (type, "bridge"))
return_type (NM_LINK_TYPE_BRIDGE, "bridge");
else if (!strcmp (type, "bond"))
......@@ -2362,6 +2367,115 @@ macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProp
return (err == 0);
}
/* The installed kernel headers might not have VXLAN stuff at all, or
* they might have the original properties, but not PORT, GROUP6, or LOCAL6.
* So until we depend on kernel >= 3.11, we just ignore the actual enum
* in if_link.h and define the values ourselves.
*/
#define IFLA_VXLAN_UNSPEC 0
#define IFLA_VXLAN_ID 1
#define IFLA_VXLAN_GROUP 2
#define IFLA_VXLAN_LINK 3
#define IFLA_VXLAN_LOCAL 4
#define IFLA_VXLAN_TTL 5
#define IFLA_VXLAN_TOS 6
#define IFLA_VXLAN_LEARNING 7
#define IFLA_VXLAN_AGEING 8
#define IFLA_VXLAN_LIMIT 9
#define IFLA_VXLAN_PORT_RANGE 10
#define IFLA_VXLAN_PROXY 11
#define IFLA_VXLAN_RSC 12
#define IFLA_VXLAN_L2MISS 13
#define IFLA_VXLAN_L3MISS 14
#define IFLA_VXLAN_PORT 15
#define IFLA_VXLAN_GROUP6 16
#define IFLA_VXLAN_LOCAL6 17
#undef IFLA_VXLAN_MAX
#define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6
static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_ID] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP6] = { .type = NLA_UNSPEC,
.minlen = sizeof (struct in6_addr) },
[IFLA_VXLAN_LINK] = { .type = NLA_U32 },
[IFLA_VXLAN_LOCAL] = { .type = NLA_U32 },
[IFLA_VXLAN_LOCAL6] = { .type = NLA_UNSPEC,
.minlen = sizeof (struct in6_addr) },
[IFLA_VXLAN_TOS] = { .type = NLA_U8 },
[IFLA_VXLAN_TTL] = { .type = NLA_U8 },
[IFLA_VXLAN_LEARNING] = { .type = NLA_U8 },
[IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
[IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
[IFLA_VXLAN_PORT_RANGE] = { .type = NLA_UNSPEC,
.minlen = sizeof (struct ifla_vxlan_port_range) },
[IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
[IFLA_VXLAN_RSC] = { .type = NLA_U8 },
[IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
[IFLA_VXLAN_L3MISS] = { .type = NLA_U8 },
[IFLA_VXLAN_PORT] = { .type = NLA_U16 },
};
static int
vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
{
NMPlatformVxlanProperties *props = parser_data;
struct nlattr *tb[IFLA_VXLAN_MAX + 1];
struct ifla_vxlan_port_range *range;
int err;
err = nla_parse_nested (tb, IFLA_VXLAN_MAX, info_data,
(struct nla_policy *) vxlan_info_policy);
if (err < 0)
return err;
memset (props, 0, sizeof (*props));
props->parent_ifindex = tb[IFLA_VXLAN_LINK] ? nla_get_u32 (tb[IFLA_VXLAN_LINK]) : 0;
props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]);
if (tb[IFLA_VXLAN_GROUP])
props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]);
if (tb[IFLA_VXLAN_LOCAL])
props->local = nla_get_u32 (tb[IFLA_VXLAN_LOCAL]);
if (tb[IFLA_VXLAN_GROUP6])
memcpy (&props->group6, nla_data (tb[IFLA_VXLAN_GROUP6]), sizeof (props->group6));
if (tb[IFLA_VXLAN_LOCAL6])
memcpy (&props->local6, nla_data (tb[IFLA_VXLAN_LOCAL6]), sizeof (props->local6));
props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]);
props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]);
props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]);
props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]);
props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]);
range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]);
props->src_port_min = range->low;
props->src_port_max = range->high;
props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]);
props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]);
props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]);
props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]);
props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]);
return 0;
}
static gboolean
vxlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformVxlanProperties *props)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
int err;
err = nm_rtnl_link_parse_info_data (priv->nlh, ifindex,
vxlan_info_data_parser, props);
if (err != 0) {
warning ("(%s) could not read properties: %s",
link_get_name (platform, ifindex), nl_geterror (err));
}
return (err == 0);
}
static const struct nla_policy gre_info_policy[IFLA_GRE_MAX + 1] = {
[IFLA_GRE_LINK] = { .type = NLA_U32 },
[IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
......@@ -3185,6 +3299,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->veth_get_properties = veth_get_properties;
platform_class->tun_get_properties = tun_get_properties;
platform_class->macvlan_get_properties = macvlan_get_properties;
platform_class->vxlan_get_properties = vxlan_get_properties;
platform_class->gre_get_properties = gre_get_properties;
platform_class->ip4_address_get_all = ip4_address_get_all;
......
......@@ -1178,6 +1178,17 @@ nm_platform_macvlan_get_properties (int ifindex, NMPlatformMacvlanProperties *pr
return klass->macvlan_get_properties (platform, ifindex, props);
}
gboolean
nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanProperties *props)
{
reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (props != NULL, FALSE);
return klass->vxlan_get_properties (platform, ifindex, props);
}
gboolean
nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props)
{
......
......@@ -104,6 +104,7 @@ typedef enum {
NM_LINK_TYPE_TUN,
NM_LINK_TYPE_VETH,
NM_LINK_TYPE_VLAN,
NM_LINK_TYPE_VXLAN,
/* Software types with slaves */
NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
......@@ -214,6 +215,27 @@ typedef struct {
gboolean no_promisc;
} NMPlatformMacvlanProperties;
typedef struct {
int parent_ifindex;
guint32 id;
in_addr_t group;
in_addr_t local;
struct in6_addr group6;
struct in6_addr local6;
guint8 tos;
guint8 ttl;
gboolean learning;
guint32 ageing;
guint32 limit;
guint16 dst_port;
guint16 src_port_min;
guint16 src_port_max;
gboolean proxy;
gboolean rsc;
gboolean l2miss;
gboolean l3miss;
} NMPlatformVxlanProperties;
typedef struct {
int parent_ifindex;
guint16 input_flags;
......@@ -317,6 +339,7 @@ typedef struct {
gboolean (*veth_get_properties) (NMPlatform *, int ifindex, NMPlatformVethProperties *properties);
gboolean (*tun_get_properties) (NMPlatform *, int ifindex, NMPlatformTunProperties *properties);
gboolean (*macvlan_get_properties) (NMPlatform *, int ifindex, NMPlatformMacvlanProperties *props);
gboolean (*vxlan_get_properties) (NMPlatform *, int ifindex, NMPlatformVxlanProperties *props);
gboolean (*gre_get_properties) (NMPlatform *, int ifindex, NMPlatformGreProperties *props);
GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex);
......@@ -445,6 +468,7 @@ gboolean nm_platform_infiniband_partition_add (int parent, int p_key);
gboolean nm_platform_veth_get_properties (int ifindex, NMPlatformVethProperties *properties);
gboolean nm_platform_tun_get_properties (int ifindex, NMPlatformTunProperties *properties);
gboolean nm_platform_macvlan_get_properties (int ifindex, NMPlatformMacvlanProperties *props);
gboolean nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanProperties *props);
gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props);
GArray *nm_platform_ip4_address_get_all (int ifindex);
......
......@@ -403,6 +403,53 @@ do_macvlan_get_properties (char **argv)
return TRUE;
}
static gboolean
do_vxlan_get_properties (char **argv)
{
int ifindex = parse_ifindex (*argv++);
NMPlatformVxlanProperties props;
char addrstr[INET6_ADDRSTRLEN];
if (!nm_platform_vxlan_get_properties (ifindex, &props))
return FALSE;
printf ("parent-ifindex: %u\n", props.parent_ifindex);
printf ("id: %u\n", props.id);
if (props.group)
inet_ntop (AF_INET, &props.group, addrstr, sizeof (addrstr));
else if (props.group6.s6_addr[0])
inet_ntop (AF_INET6, &props.group6, addrstr, sizeof (addrstr));
else
strcpy (addrstr, "-");
printf ("group: %s\n", addrstr);
if (props.local)
inet_ntop (AF_INET, &props.local, addrstr, sizeof (addrstr));
else if (props.local6.s6_addr[0])
inet_ntop (AF_INET6, &props.local6, addrstr, sizeof (addrstr));
else
strcpy (addrstr, "-");
printf ("local: %s\n", addrstr);
printf ("tos: %u\n", props.tos);
printf ("ttl: %u\n", props.ttl);
printf ("learning: ");
print_boolean (props.learning);
printf ("ageing: %u\n", props.ageing);
printf ("limit: %u\n", props.limit);
printf ("dst-port: %u\n", props.dst_port);
printf ("src-port-min: %u\n", props.src_port_min);
printf ("src-port-max: %u\n", props.src_port_max);
printf ("proxy: ");
print_boolean (props.proxy);
printf ("rsc: ");
print_boolean (props.rsc);
printf ("l2miss: ");
print_boolean (props.l2miss);
printf ("l3miss: ");
print_boolean (props.l3miss);
return TRUE;
}
static gboolean
do_gre_get_properties (char **argv)
{
......@@ -762,6 +809,8 @@ static const command_t commands[] = {
"<ifname/ifindex>" },
{ "macvlan-get-properties", "get macvlan properties", do_macvlan_get_properties, 1,
"<ifname/ifindex>" },
{ "vxlan-get-properties", "get vxlan properties", do_vxlan_get_properties, 1,
"<ifname/ifindex>" },
{ "gre-get-properties", "get gre properties", do_gre_get_properties, 1,
"<ifname/ifindex>" },
{ "ip4-address-get-all", "print all IPv4 addresses", do_ip4_address_get_all, 1, "<ifname/ifindex>" },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment