summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2019-12-05 10:35:25 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2020-01-14 09:49:01 +0100
commit7c73c6a038a15687bfc9d831b97e01596ec3fe9d (patch)
treee6c389fd9111d4272df49baa6817962ce3ecb182
parent89d387f782fb4402c7cc32ef524b741c9cbb90cc (diff)
downloadNetworkManager-7c73c6a038a15687bfc9d831b97e01596ec3fe9d.tar.gz
platform: add VRF support
Add support for creating and parsing VRF links.
-rw-r--r--src/nm-types.h2
-rw-r--r--src/platform/nm-linux-platform.c44
-rw-r--r--src/platform/nm-platform.c39
-rw-r--r--src/platform/nm-platform.h17
-rw-r--r--src/platform/nmp-object.c12
-rw-r--r--src/platform/nmp-object.h7
-rw-r--r--src/platform/tests/test-common.c33
-rw-r--r--src/platform/tests/test-common.h4
-rw-r--r--src/platform/tests/test-link.c16
9 files changed, 174 insertions, 0 deletions
diff --git a/src/nm-types.h b/src/nm-types.h
index 2f1ac2dcd5..43b931dad3 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -160,6 +160,7 @@ typedef enum {
NM_LINK_TYPE_TUN,
NM_LINK_TYPE_VETH,
NM_LINK_TYPE_VLAN,
+ NM_LINK_TYPE_VRF,
NM_LINK_TYPE_VXLAN,
NM_LINK_TYPE_WIREGUARD,
@@ -197,6 +198,7 @@ typedef enum {
NMP_OBJECT_TYPE_LNK_SIT,
NMP_OBJECT_TYPE_LNK_TUN,
NMP_OBJECT_TYPE_LNK_VLAN,
+ NMP_OBJECT_TYPE_LNK_VRF,
NMP_OBJECT_TYPE_LNK_VXLAN,
NMP_OBJECT_TYPE_LNK_WIREGUARD,
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 4fc4a16f21..020db21ecd 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -656,6 +656,7 @@ static const LinkDesc linktypes[] = {
{ NM_LINK_TYPE_TUN, "tun", "tun", NULL },
{ NM_LINK_TYPE_VETH, "veth", "veth", NULL },
{ NM_LINK_TYPE_VLAN, "vlan", "vlan", "vlan" },
+ { NM_LINK_TYPE_VRF, "vrf", "vrf", "vrf" },
{ NM_LINK_TYPE_VXLAN, "vxlan", "vxlan", "vxlan" },
{ NM_LINK_TYPE_WIREGUARD, "wireguard", "wireguard", "wireguard" },
@@ -1754,6 +1755,8 @@ _parse_lnk_vlan (const char *kind, struct nlattr *info_data)
#undef IFLA_VXLAN_MAX
#define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6
+#define IFLA_VRF_TABLE 1
+
/* older kernel header might not contain 'struct ifla_vxlan_port_range'.
* Redefine it. */
struct nm_ifla_vxlan_port_range {
@@ -1848,6 +1851,33 @@ _parse_lnk_vxlan (const char *kind, struct nlattr *info_data)
return obj;
}
+static NMPObject *
+_parse_lnk_vrf (const char *kind, struct nlattr *info_data)
+{
+ static const struct nla_policy policy[] = {
+ [IFLA_VRF_TABLE] = { .type = NLA_U32 },
+ };
+ NMPlatformLnkVrf *props;
+ struct nlattr *tb[G_N_ELEMENTS (policy)];
+ NMPObject *obj;
+
+ if ( !info_data
+ || !nm_streq0 (kind, "vrf"))
+ return NULL;
+
+ if (nla_parse_nested_arr (tb, info_data, policy) < 0)
+ return NULL;
+
+ obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_VRF, NULL);
+
+ props = &obj->lnk_vrf;
+
+ if (tb[IFLA_VRF_TABLE])
+ props->table = nla_get_u32 (tb[IFLA_VRF_TABLE]);
+
+ return obj;
+}
+
/*****************************************************************************/
static gboolean
@@ -2798,6 +2828,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
case NM_LINK_TYPE_VLAN:
lnk_data = _parse_lnk_vlan (nl_info_kind, nl_info_data);
break;
+ case NM_LINK_TYPE_VRF:
+ lnk_data = _parse_lnk_vrf (nl_info_kind, nl_info_data);
+ break;
case NM_LINK_TYPE_VXLAN:
lnk_data = _parse_lnk_vxlan (nl_info_kind, nl_info_data);
break;
@@ -3728,6 +3761,17 @@ _nl_msg_new_link_set_linkinfo (struct nl_msg *msg,
}
break;
}
+ case NM_LINK_TYPE_VRF: {
+ const NMPlatformLnkVrf *props = extra_data;
+
+ nm_assert (extra_data);
+
+ if (!(data = nla_nest_start (msg, IFLA_INFO_DATA)))
+ goto nla_put_failure;
+
+ NLA_PUT_U32 (msg, IFLA_VRF_TABLE, props->table);
+ break;
+ }
case NM_LINK_TYPE_VXLAN: {
const NMPlatformLnkVxlan *props = extra_data;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index fbb5e7e2fa..2065b1818e 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1218,6 +1218,10 @@ nm_platform_link_add (NMPlatform *self,
nm_utils_strbuf_append_str (&buf_p, &buf_len, ", ");
nm_platform_lnk_vlan_to_string ((const NMPlatformLnkVlan *) extra_data, buf_p, buf_len);
break;
+ case NM_LINK_TYPE_VRF:
+ nm_utils_strbuf_append_str (&buf_p, &buf_len, ", ");
+ nm_platform_lnk_vrf_to_string ((const NMPlatformLnkVrf *) extra_data, buf_p, buf_len);
+ break;
case NM_LINK_TYPE_VXLAN:
nm_utils_strbuf_append_str (&buf_p, &buf_len, ", ");
nm_platform_lnk_vxlan_to_string ((const NMPlatformLnkVxlan *) extra_data, buf_p, buf_len);
@@ -2252,6 +2256,12 @@ nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLi
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VLAN, out_link);
}
+const NMPlatformLnkVrf *
+nm_platform_link_get_lnk_vrf (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
+{
+ return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VRF, out_link);
+}
+
const NMPlatformLnkVxlan *
nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
@@ -5485,6 +5495,20 @@ nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize l
}
const char *
+nm_platform_lnk_vrf_to_string (const NMPlatformLnkVrf *lnk, char *buf, gsize len)
+{
+ char *b;
+
+ if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len))
+ return buf;
+
+ b = buf;
+
+ nm_utils_strbuf_append (&b, &len, "table %u", lnk->table);
+ return buf;
+}
+
+const char *
nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len)
{
char str_group[100];
@@ -6851,6 +6875,21 @@ nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b
}
void
+nm_platform_lnk_vrf_hash_update (const NMPlatformLnkVrf *obj, NMHashState *h)
+{
+ nm_hash_update_vals (h,
+ obj->table);
+}
+
+int
+nm_platform_lnk_vrf_cmp (const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b)
+{
+ NM_CMP_SELF (a, b);
+ NM_CMP_FIELD (a, b, table);
+ return 0;
+}
+
+void
nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h)
{
nm_hash_update_vals (h,
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 8d1a3d3865..d18208081a 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -828,6 +828,10 @@ typedef struct {
} NMPlatformLnkVlan;
typedef struct {
+ guint32 table;
+} NMPlatformLnkVrf;
+
+typedef struct {
struct in6_addr group6;
struct in6_addr local6;
in_addr_t group;
@@ -1431,6 +1435,15 @@ nm_platform_link_vlan_add (NMPlatform *self,
}
static inline int
+nm_platform_link_vrf_add (NMPlatform *self,
+ const char *name,
+ const NMPlatformLnkVrf *props,
+ const NMPlatformLink **out_link)
+{
+ return nm_platform_link_add (self, NM_LINK_TYPE_VRF, name, 0, NULL, 0, props, out_link);
+}
+
+static inline int
nm_platform_link_vxlan_add (NMPlatform *self,
const char *name,
const NMPlatformLnkVxlan *props,
@@ -1621,6 +1634,7 @@ const NMPlatformLnkMacvlan *nm_platform_link_get_lnk_macvtap (NMPlatform *self,
const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkTun *nm_platform_link_get_lnk_tun (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkVlan *nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
+const NMPlatformLnkVrf *nm_platform_link_get_lnk_vrf (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkVxlan *nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkWireGuard *nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
@@ -1792,6 +1806,7 @@ const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk,
const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len);
const char *nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len);
const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len);
+const char *nm_platform_lnk_vrf_to_string (const NMPlatformLnkVrf *lnk, char *buf, gsize len);
const char *nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len);
const char *nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len);
const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len);
@@ -1824,6 +1839,7 @@ int nm_platform_lnk_macvlan_cmp (const NMPlatformLnkMacvlan *a, const NMPlatform
int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *b);
int nm_platform_lnk_tun_cmp (const NMPlatformLnkTun *a, const NMPlatformLnkTun *b);
int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b);
+int nm_platform_lnk_vrf_cmp (const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b);
int nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b);
int nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b);
int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b);
@@ -1870,6 +1886,7 @@ void nm_platform_lnk_macvlan_hash_update (const NMPlatformLnkMacvlan *obj, NMHas
void nm_platform_lnk_sit_hash_update (const NMPlatformLnkSit *obj, NMHashState *h);
void nm_platform_lnk_tun_hash_update (const NMPlatformLnkTun *obj, NMHashState *h);
void nm_platform_lnk_vlan_hash_update (const NMPlatformLnkVlan *obj, NMHashState *h);
+void nm_platform_lnk_vrf_hash_update (const NMPlatformLnkVrf *obj, NMHashState *h);
void nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h);
void nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireGuard *obj, NMHashState *h);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 240c1e7d8a..12f90aee1c 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -3336,6 +3336,18 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vlan_hash_update,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp,
},
+ [NMP_OBJECT_TYPE_LNK_VRF - 1] = {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
+ .obj_type = NMP_OBJECT_TYPE_LNK_VRF,
+ .sizeof_data = sizeof (NMPObjectLnkVrf),
+ .sizeof_public = sizeof (NMPlatformLnkVrf),
+ .obj_type_name = "vrf",
+ .lnk_link_type = NM_LINK_TYPE_VRF,
+ .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_vrf_to_string,
+ .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vrf_hash_update,
+ .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vrf_cmp,
+ },
+
[NMP_OBJECT_TYPE_LNK_VXLAN - 1] = {
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_VXLAN,
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index d52cc132d2..1cafc3abf8 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -287,6 +287,10 @@ typedef struct {
} NMPObjectLnkVlan;
typedef struct {
+ NMPlatformLnkVrf _public;
+} NMPObjectLnkVrf;
+
+typedef struct {
NMPlatformLnkVxlan _public;
} NMPObjectLnkVxlan;
@@ -366,6 +370,9 @@ struct _NMPObject {
NMPlatformLnkVlan lnk_vlan;
NMPObjectLnkVlan _lnk_vlan;
+ NMPlatformLnkVrf lnk_vrf;
+ NMPObjectLnkVrf _lnk_vrf;
+
NMPlatformLnkVxlan lnk_vxlan;
NMPObjectLnkVxlan _lnk_vxlan;
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 906deeada6..2fbfb90d4c 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -1586,6 +1586,39 @@ nmtstp_link_tun_add (NMPlatform *platform,
}
const NMPlatformLink *
+nmtstp_link_vrf_add (NMPlatform *platform,
+ gboolean external_command,
+ const char *name,
+ const NMPlatformLnkVrf *lnk)
+{
+ const NMPlatformLink *pllink = NULL;
+ int err;
+ int r;
+
+ g_assert (nm_utils_is_valid_iface_name (name, NULL));
+
+ external_command = nmtstp_run_command_check_external (external_command);
+
+ _init_platform (&platform, external_command);
+
+ if (external_command) {
+ err = nmtstp_run_command ("ip link add %s type vrf table %u",
+ name,
+ lnk->table);
+ if (err == 0)
+ pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VRF, 100);
+ } else {
+ r = nm_platform_link_vrf_add (platform, name, lnk, &pllink);
+ g_assert (NMTST_NM_ERR_SUCCESS (r));
+ g_assert (pllink);
+ }
+
+ g_assert_cmpint (pllink->type, ==, NM_LINK_TYPE_VRF);
+ g_assert_cmpstr (pllink->name, ==, name);
+ return pllink;
+}
+
+const NMPlatformLink *
nmtstp_link_vxlan_add (NMPlatform *platform,
gboolean external_command,
const char *name,
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index 6f5a6cf62b..f392413eca 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -360,6 +360,10 @@ const NMPlatformLink *nmtstp_link_tun_add (NMPlatform *platform,
const char *name,
const NMPlatformLnkTun *lnk,
int *out_fd);
+const NMPlatformLink *nmtstp_link_vrf_add (NMPlatform *platform,
+ gboolean external_command,
+ const char *name,
+ const NMPlatformLnkVrf *lnk);
const NMPlatformLink *nmtstp_link_vxlan_add (NMPlatform *platform,
gboolean external_command,
const char *name,
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 4a54af2a19..2f7a503cee 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -1182,6 +1182,14 @@ test_software_detect (gconstpointer user_data)
case NM_LINK_TYPE_VLAN:
nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1242", DEVICE_NAME, PARENT_NAME);
break;
+ case NM_LINK_TYPE_VRF: {
+ NMPlatformLnkVrf lnk_vrf = { };
+
+ lnk_vrf.table = 9876;
+
+ nmtstp_link_vrf_add (NULL, ext, DEVICE_NAME, &lnk_vrf);
+ break;
+ }
case NM_LINK_TYPE_VXLAN: {
NMPlatformLnkVxlan lnk_vxlan = { };
@@ -1444,6 +1452,13 @@ test_software_detect (gconstpointer user_data)
g_assert_cmpint (plnk->id, ==, 1242);
break;
}
+ case NM_LINK_TYPE_VRF: {
+ const NMPlatformLnkVrf *plnk = &lnk->lnk_vrf;
+
+ g_assert (plnk == nm_platform_link_get_lnk_vrf (NM_PLATFORM_GET, ifindex, NULL));
+ g_assert_cmpint (plnk->table, ==, 9876);
+ break;
+ }
case NM_LINK_TYPE_VXLAN: {
const NMPlatformLnkVxlan *plnk = &lnk->lnk_vxlan;
@@ -3313,6 +3328,7 @@ _nmtstp_setup_tests (void)
test_software_detect_add ("/link/software/detect/sit", NM_LINK_TYPE_SIT, 0);
test_software_detect_add ("/link/software/detect/tun", NM_LINK_TYPE_TUN, 0);
test_software_detect_add ("/link/software/detect/vlan", NM_LINK_TYPE_VLAN, 0);
+ test_software_detect_add ("/link/software/detect/vrf", NM_LINK_TYPE_VRF, 0);
test_software_detect_add ("/link/software/detect/vxlan/0", NM_LINK_TYPE_VXLAN, 0);
test_software_detect_add ("/link/software/detect/vxlan/1", NM_LINK_TYPE_VXLAN, 1);
test_software_detect_add ("/link/software/detect/wireguard/0", NM_LINK_TYPE_WIREGUARD, 0);