Commit 4c2862b9 authored by Beniamino Galvani's avatar Beniamino Galvani

platform: add gretap tunnels support

Add platform support for GRETAP tunnels (Virtual L2 tunnel interface
GRE over IPv4) partially reusing the existing GRE code.
parent cdad8c6d
......@@ -194,6 +194,7 @@ typedef enum {
NMP_OBJECT_TYPE_TFILTER,
NMP_OBJECT_TYPE_LNK_GRE,
NMP_OBJECT_TYPE_LNK_GRETAP,
NMP_OBJECT_TYPE_LNK_INFINIBAND,
NMP_OBJECT_TYPE_LNK_IP6TNL,
NMP_OBJECT_TYPE_LNK_IPIP,
......
......@@ -1072,15 +1072,23 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data)
int err;
NMPObject *obj;
NMPlatformLnkGre *props;
gboolean is_tap;
if (!info_data || g_strcmp0 (kind, "gre"))
if (!info_data || !kind)
return NULL;
if (nm_streq (kind, "gretap"))
is_tap = TRUE;
else if (nm_streq (kind, "gre"))
is_tap = FALSE;
else
return NULL;
err = nla_parse_nested (tb, IFLA_GRE_MAX, info_data, policy);
if (err < 0)
return NULL;
obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_GRE, NULL);
obj = nmp_object_new (is_tap ? NMP_OBJECT_TYPE_LNK_GRETAP : NMP_OBJECT_TYPE_LNK_GRE, NULL);
props = &obj->lnk_gre;
props->parent_ifindex = tb[IFLA_GRE_LINK] ? nla_get_u32 (tb[IFLA_GRE_LINK]) : 0;
......@@ -1093,6 +1101,7 @@ _parse_lnk_gre (const char *kind, struct nlattr *info_data)
props->tos = tb[IFLA_GRE_TOS] ? nla_get_u8 (tb[IFLA_GRE_TOS]) : 0;
props->ttl = tb[IFLA_GRE_TTL] ? nla_get_u8 (tb[IFLA_GRE_TTL]) : 0;
props->path_mtu_discovery = !tb[IFLA_GRE_PMTUDISC] || !!nla_get_u8 (tb[IFLA_GRE_PMTUDISC]);
props->is_tap = is_tap;
return obj;
}
......@@ -1852,6 +1861,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
switch (obj->link.type) {
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
lnk_data = _parse_lnk_gre (nl_info_kind, nl_info_data);
break;
case NM_LINK_TYPE_INFINIBAND:
......@@ -3995,6 +4005,7 @@ cache_on_change (NMPlatform *platform,
if ( !obj_new->_link.netlink.lnk
&& NM_IN_SET (obj_new->link.type, NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_IP6TNL,
NM_LINK_TYPE_INFINIBAND,
NM_LINK_TYPE_MACVLAN,
......@@ -5330,7 +5341,7 @@ link_gre_add (NMPlatform *platform,
if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO)))
goto nla_put_failure;
NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "gre");
NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, props->is_tap ? "gretap" : "gre");
if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA)))
goto nla_put_failure;
......@@ -5350,7 +5361,9 @@ link_gre_add (NMPlatform *platform,
nla_nest_end (nlmsg, data);
nla_nest_end (nlmsg, info);
return do_add_link_with_lookup (platform, NM_LINK_TYPE_GRE, name, nlmsg, out_link);
return do_add_link_with_lookup (platform,
props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE,
name, nlmsg, out_link);
nla_put_failure:
g_return_val_if_reached (FALSE);
}
......
......@@ -1854,6 +1854,12 @@ nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLin
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRE, out_link);
}
const NMPlatformLnkGre *
nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_GRETAP, out_link);
}
const NMPlatformLnkInfiniband *
nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
......@@ -2385,7 +2391,7 @@ nm_platform_link_gre_add (NMPlatform *self,
g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG);
g_return_val_if_fail (name, NM_PLATFORM_ERROR_BUG);
plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_GRE, out_link);
plerr = _link_add_check_existing (self, name, props->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE, out_link);
if (plerr != NM_PLATFORM_ERROR_SUCCESS)
return plerr;
......@@ -5055,7 +5061,7 @@ nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len
return buf;
g_snprintf (buf, len,
"gre"
lnk->is_tap ? "gretap" : "gre"
"%s" /* remote */
"%s" /* local */
"%s" /* parent_ifindex */
......@@ -5942,7 +5948,8 @@ nm_platform_lnk_gre_hash_update (const NMPlatformLnkGre *obj, NMHashState *h)
obj->output_key,
obj->ttl,
obj->tos,
(bool) obj->path_mtu_discovery);
(bool) obj->path_mtu_discovery,
(bool) obj->is_tap);
}
int
......@@ -5959,6 +5966,7 @@ nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b)
NM_CMP_FIELD (a, b, ttl);
NM_CMP_FIELD (a, b, tos);
NM_CMP_FIELD_BOOL (a, b, path_mtu_discovery);
NM_CMP_FIELD_BOOL (a, b, is_tap);
return 0;
}
......
......@@ -618,6 +618,7 @@ typedef struct {
guint8 ttl;
guint8 tos;
bool path_mtu_discovery:1;
bool is_tap:1;
} NMPlatformLnkGre;
typedef struct {
......@@ -1198,6 +1199,7 @@ char *nm_platform_sysctl_slave_get_option (NMPlatform *self, int ifindex, const
const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link);
const NMPlatformLnkGre *nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGre *nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkIpIp *nm_platform_link_get_lnk_ipip (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkInfiniband *nm_platform_link_get_lnk_infiniband (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
......
......@@ -2712,6 +2712,17 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp,
},
[NMP_OBJECT_TYPE_LNK_GRETAP - 1] = {
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_GRETAP,
.sizeof_data = sizeof (NMPObjectLnkGre),
.sizeof_public = sizeof (NMPlatformLnkGre),
.obj_type_name = "gretap",
.lnk_link_type = NM_LINK_TYPE_GRETAP,
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_gre_to_string,
.cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update,
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp,
},
[NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = {
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND,
......
......@@ -1243,21 +1243,29 @@ nmtstp_link_gre_add (NMPlatform *platform,
const NMPlatformLink *pllink = NULL;
gboolean success;
char buffer[INET_ADDRSTRLEN];
NMLinkType link_type;
g_assert (nm_utils_is_valid_iface_name (name, NULL));
external_command = nmtstp_run_command_check_external (external_command);
link_type = lnk->is_tap ? NM_LINK_TYPE_GRETAP : NM_LINK_TYPE_GRE;
_init_platform (&platform, external_command);
if (external_command) {
gs_free char *dev = NULL;
char *obj, *type;
if (lnk->parent_ifindex)
dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (platform, lnk->parent_ifindex));
success = !nmtstp_run_command ("ip tunnel add %s mode gre %s local %s remote %s ttl %u tos %02x %s",
obj = lnk->is_tap ? "link" : "tunnel";
type = lnk->is_tap ? "type gretap" : "mode gre";
success = !nmtstp_run_command ("ip %s add %s %s %s local %s remote %s ttl %u tos %02x %s",
obj,
name,
type,
dev ?: "",
nm_utils_inet4_ntop (lnk->local, NULL),
nm_utils_inet4_ntop (lnk->remote, buffer),
......@@ -1265,11 +1273,11 @@ nmtstp_link_gre_add (NMPlatform *platform,
lnk->tos,
lnk->path_mtu_discovery ? "pmtudisc" : "nopmtudisc");
if (success)
pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_GRE, 100);
pllink = nmtstp_assert_wait_for_link (platform, name, link_type, 100);
} else
success = nm_platform_link_gre_add (platform, name, lnk, &pllink) == NM_PLATFORM_ERROR_SUCCESS;
_assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_GRE);
_assert_pllink (platform, success, pllink, name, link_type);
return pllink;
}
......
......@@ -699,6 +699,7 @@ test_software_detect (gconstpointer user_data)
guint i_step;
const gboolean ext = test_data->external_command;
NMPlatformLnkTun lnk_tun;
NMPlatformLnkGre lnk_gre = { };
nm_auto_close int tun_fd = -1;
nmtstp_run_command_check ("ip link add %s type dummy", PARENT_NAME);
......@@ -706,7 +707,6 @@ test_software_detect (gconstpointer user_data)
switch (test_data->link_type) {
case NM_LINK_TYPE_GRE: {
NMPlatformLnkGre lnk_gre = { };
gboolean gracefully_skip = FALSE;
lnk_gre.local = nmtst_inet4_from_string ("192.168.233.204");
......@@ -730,6 +730,31 @@ test_software_detect (gconstpointer user_data)
}
break;
}
case NM_LINK_TYPE_GRETAP: {
gboolean gracefully_skip = FALSE;
lnk_gre.local = nmtst_inet4_from_string ("192.168.1.133");
lnk_gre.remote = nmtst_inet4_from_string ("172.168.101.2");
lnk_gre.parent_ifindex = ifindex_parent;
lnk_gre.ttl = 39;
lnk_gre.tos = 12;
lnk_gre.path_mtu_discovery = FALSE;
lnk_gre.is_tap = TRUE;
if (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "gretap0")) {
/* Seems that the ip_gre module is not loaded... try to load it. */
gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip_gre", NULL) != 0;
}
if (!nmtstp_link_gre_add (NULL, ext, DEVICE_NAME, &lnk_gre)) {
if (gracefully_skip) {
g_test_skip ("Cannot create gretap tunnel because of missing ip_gre module (modprobe ip_gre)");
goto out_delete_parent;
}
g_error ("Failed adding GRETAP tunnel");
}
break;
}
case NM_LINK_TYPE_IPIP: {
NMPlatformLnkIpIp lnk_ipip = { };
gboolean gracefully_skip = FALSE;
......@@ -970,16 +995,15 @@ test_software_detect (gconstpointer user_data)
const NMPlatformLnkGre *plnk = &lnk->lnk_gre;
g_assert (plnk == nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL));
g_assert_cmpint (plnk->parent_ifindex, ==, ifindex_parent);
g_assert_cmpint (plnk->input_flags, ==, 0);
g_assert_cmpint (plnk->output_flags, ==, 0);
g_assert_cmpint (plnk->input_key, ==, 0);
g_assert_cmpint (plnk->output_key, ==, 0);
nmtst_assert_ip4_address (plnk->local, "192.168.233.204");
nmtst_assert_ip4_address (plnk->remote, "172.168.10.25");
g_assert_cmpint (plnk->ttl, ==, 174);
g_assert_cmpint (plnk->tos, ==, 37);
g_assert_cmpint (plnk->path_mtu_discovery, ==, TRUE);
g_assert (nm_platform_lnk_gre_cmp (plnk, &lnk_gre) == 0);
break;
}
case NM_LINK_TYPE_GRETAP: {
const NMPlatformLnkGre *plnk = &lnk->lnk_gre;
g_assert (plnk == nm_platform_link_get_lnk_gretap (NM_PLATFORM_GET, ifindex, NULL));
g_assert (nm_platform_lnk_gre_cmp (plnk, &lnk_gre) == 0);
break;
}
case NM_LINK_TYPE_IP6TNL: {
......@@ -2641,6 +2665,7 @@ _nmtstp_setup_tests (void)
g_test_add_func ("/link/external", test_external);
test_software_detect_add ("/link/software/detect/gre", NM_LINK_TYPE_GRE, 0);
test_software_detect_add ("/link/software/detect/gretap", NM_LINK_TYPE_GRETAP, 0);
test_software_detect_add ("/link/software/detect/ip6tnl/0", NM_LINK_TYPE_IP6TNL, 0);
test_software_detect_add ("/link/software/detect/ip6tnl/1", NM_LINK_TYPE_IP6TNL, 1);
test_software_detect_add ("/link/software/detect/ipip", NM_LINK_TYPE_IPIP, 0);
......
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