platform: add support for GENEVE tunnels

GENEVE (Generic Network Virtualization Encapsulation) is a network
tunneling protocol that provides a flexible encapsulation format for
overlay networks. It uses UDP as the transport protocol and supports
variable-length metadata in the tunnel header.

This patch adds GENEVE tunnel to NM's platform layer:

- Add platform API functions (nm_platform_link_geneve_add,
  nm_platform_link_get_lnk_geneve)

- Netlink message parsing for the following attributes:
  * IFLA_GENEVE_ID - VNI (Virtual Network Identifier)
  IPv4 and IPv6 remote
  * IFLA_GENEVE_REMOTE
  * IFLA_GENEVE_REMOTE6
  TTL, TOS, and DF flags
  * IFLA_GENEVE_TTL
  * IFLA_GENEVE_TOS
  * IFLA_GENEVE_DF
  UDP destination port
  * IFLA_GENEVE_PORT

- Add test cases for GENEVE tunnel creation and detection with two test
  modes covering IPv4 and IPv6.

The implementation tries to follow the same patterns as other tunnel
types (GRE, VXLAN, etc.) and integrates with the existing platform
abstraction layer.
This commit is contained in:
Rahul Rajesh 2026-01-22 17:09:48 -05:00
parent ad78bd8570
commit 29c8bbe21a
11 changed files with 332 additions and 6 deletions

View file

@ -2393,6 +2393,61 @@ nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *na
return pllink;
}
const NMPlatformLink *
nmtstp_link_geneve_add(NMPlatform *platform,
int external_command,
const char *name,
const NMPlatformLnkGeneve *lnk)
{
const NMPlatformLink *pllink = NULL;
int success;
g_assert(nm_utils_ifname_valid_kernel(name, NULL));
g_assert(lnk->remote || !IN6_IS_ADDR_UNSPECIFIED(&lnk->remote6));
external_command = nmtstp_run_command_check_external(external_command);
_init_platform(&platform, external_command);
if (external_command) {
char remote[NM_INET_ADDRSTRLEN];
char remote6[NM_INET_ADDRSTRLEN];
char str_ttl[30];
if (lnk->remote)
nm_inet4_ntop(lnk->remote, remote);
else
remote[0] = '\0';
if (memcmp(&lnk->remote6, &in6addr_any, sizeof(in6addr_any)))
nm_inet6_ntop(&lnk->remote6, remote6);
else
remote6[0] = '\0';
success = !nmtstp_run_command(
"ip link add %s type geneve id %u remote %s %s tos %02x dstport %u%s",
name,
lnk->id,
remote[0] ? remote : remote6,
lnk->ttl > 0 ? nm_sprintf_buf(str_ttl, "ttl %u", lnk->ttl & 0xff)
: lnk->ttl == 0 ? "ttl auto"
: "ttl inherit",
lnk->tos,
lnk->dst_port,
lnk->df == 1 ? " df set "
: lnk->df == 2 ? " df inherit "
: "");
if (success)
pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_GENEVE, 100);
} else
success = NMTST_NM_ERR_SUCCESS(nm_platform_link_geneve_add(platform, name, lnk, &pllink));
_assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_GENEVE);
return pllink;
}
const NMPlatformLink *
nmtstp_link_gre_add(NMPlatform *platform,
int external_command,
@ -3024,8 +3079,6 @@ nmtstp_link_vxlan_add(NMPlatform *platform,
return pllink;
}
/*****************************************************************************/
const NMPlatformLink *
nmtstp_link_get_typed(NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type)
{

View file

@ -474,6 +474,10 @@ const NMPlatformLink *nmtstp_link_veth_add(NMPlatform *platform,
const char *peer);
const NMPlatformLink *
nmtstp_link_dummy_add(NMPlatform *platform, int external_command, const char *name);
const NMPlatformLink *nmtstp_link_geneve_add(NMPlatform *platform,
int external_command,
const char *name,
const NMPlatformLnkGeneve *lnk);
const NMPlatformLink *nmtstp_link_gre_add(NMPlatform *platform,
int external_command,
const char *name,

View file

@ -1388,10 +1388,11 @@ test_software_detect(gconstpointer user_data)
const gboolean ext = test_data->external_command;
NMPlatformLnkBridge lnk_bridge = {};
NMPlatformLnkTun lnk_tun;
NMPlatformLnkGre lnk_gre = {};
NMPlatformLnkVti lnk_vti = {};
NMPlatformLnkVti6 lnk_vti6 = {};
nm_auto_close int tun_fd = -1;
NMPlatformLnkGeneve lnk_geneve = {};
NMPlatformLnkGre lnk_gre = {};
NMPlatformLnkVti lnk_vti = {};
NMPlatformLnkVti6 lnk_vti6 = {};
nm_auto_close int tun_fd = -1;
gboolean module_loaded;
nmtstp_run_command_check("ip link add %s type dummy", PARENT_NAME);
@ -1434,6 +1435,31 @@ test_software_detect(gconstpointer user_data)
g_error("Failed adding Bridge interface");
break;
case NM_LINK_TYPE_GENEVE:
{
switch (test_data->test_mode) {
case 0:
lnk_geneve.id = 42;
lnk_geneve.remote = nmtst_inet4_from_string("192.168.1.100");
lnk_geneve.ttl = 64;
lnk_geneve.tos = 0;
lnk_geneve.dst_port = 6081;
lnk_geneve.df = 0;
break;
case 1:
lnk_geneve.id = 12345;
lnk_geneve.remote6 = nmtst_inet6_from_string("2001:db8::1");
lnk_geneve.ttl = 128;
lnk_geneve.tos = 16;
lnk_geneve.dst_port = 6082;
lnk_geneve.df = 1;
break;
}
g_assert(nmtstp_link_geneve_add(NULL, ext, DEVICE_NAME, &lnk_geneve));
break;
}
case NM_LINK_TYPE_GRE:
module_loaded = nmtstp_ensure_module("ip_gre");
@ -2208,6 +2234,34 @@ test_software_detect(gconstpointer user_data)
}
break;
}
case NM_LINK_TYPE_GENEVE:
{
const NMPlatformLnkGeneve *plnk = &lnk->lnk_geneve;
g_assert(plnk == nm_platform_link_get_lnk_geneve(NM_PLATFORM_GET, ifindex, NULL));
switch (test_data->test_mode) {
case 0:
g_assert_cmpint(plnk->id, ==, 42);
nmtst_assert_ip4_address(plnk->remote, "192.168.1.100");
nmtst_assert_ip6_address(&plnk->remote6, "::");
g_assert_cmpint(plnk->ttl, ==, 64);
g_assert_cmpint(plnk->tos, ==, 0);
g_assert_cmpint(plnk->dst_port, ==, 6081);
g_assert_cmpint(plnk->df, ==, 0);
break;
case 1:
g_assert_cmpint(plnk->id, ==, 12345);
nmtst_assert_ip4_address(plnk->remote, "0.0.0.0");
nmtst_assert_ip6_address(&plnk->remote6, "2001:db8::1");
g_assert_cmpint(plnk->ttl, ==, 128);
g_assert_cmpint(plnk->tos, ==, 16);
g_assert_cmpint(plnk->dst_port, ==, 6082);
g_assert_cmpint(plnk->df, ==, 1);
break;
}
break;
}
case NM_LINK_TYPE_WIREGUARD:
{
const NMPlatformLnkWireGuard *plnk = &lnk->lnk_wireguard;
@ -4143,6 +4197,8 @@ _nmtstp_setup_tests(void)
g_test_add_func("/link/external", test_external);
test_software_detect_add("/link/software/detect/bridge", NM_LINK_TYPE_BRIDGE, 0);
test_software_detect_add("/link/software/detect/geneve/0", NM_LINK_TYPE_GENEVE, 0);
test_software_detect_add("/link/software/detect/geneve/1", NM_LINK_TYPE_GENEVE, 1);
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);

View file

@ -130,6 +130,7 @@ typedef enum {
#define _NM_LINK_TYPE_SW_FIRST NM_LINK_TYPE_BNEP
NM_LINK_TYPE_BNEP, /* Bluetooth Ethernet emulation */
NM_LINK_TYPE_DUMMY,
NM_LINK_TYPE_GENEVE,
NM_LINK_TYPE_GRE,
NM_LINK_TYPE_GRETAP,
NM_LINK_TYPE_IFB,

View file

@ -862,6 +862,7 @@ static const LinkDesc link_descs[] = {
[NM_LINK_TYPE_BNEP] = {"bluetooth", NULL, "bluetooth"},
[NM_LINK_TYPE_DUMMY] = {"dummy", "dummy", NULL},
[NM_LINK_TYPE_GENEVE] = {"geneve", "geneve", "geneve"},
[NM_LINK_TYPE_GRE] = {"gre", "gre", NULL},
[NM_LINK_TYPE_GRETAP] = {"gretap", "gretap", NULL},
[NM_LINK_TYPE_IFB] = {"ifb", "ifb", NULL},
@ -909,6 +910,7 @@ _link_type_from_rtnl_type(const char *name)
NM_LINK_TYPE_BOND, /* "bond" */
NM_LINK_TYPE_BRIDGE, /* "bridge" */
NM_LINK_TYPE_DUMMY, /* "dummy" */
NM_LINK_TYPE_GENEVE, /* "geneve" */
NM_LINK_TYPE_GRE, /* "gre" */
NM_LINK_TYPE_GRETAP, /* "gretap" */
NM_LINK_TYPE_HSR, /* "hsr" */
@ -987,6 +989,7 @@ _link_type_from_devtype(const char *name)
NM_LINK_TYPE_BNEP, /* "bluetooth" */
NM_LINK_TYPE_BOND, /* "bond" */
NM_LINK_TYPE_BRIDGE, /* "bridge" */
NM_LINK_TYPE_GENEVE, /* "geneve" */
NM_LINK_TYPE_HSR, /* "hsr" */
NM_LINK_TYPE_PPP, /* "ppp" */
NM_LINK_TYPE_VLAN, /* "vlan" */
@ -1856,6 +1859,57 @@ _parse_lnk_gre(const char *kind, struct nlattr *info_data)
/*****************************************************************************/
static NMPObject *
_parse_lnk_geneve(const char *kind, struct nlattr *info_data)
{
static const struct nla_policy policy[] = {
[IFLA_GENEVE_ID] = {.type = NLA_U32},
[IFLA_GENEVE_REMOTE] = {.type = NLA_U32},
[IFLA_GENEVE_REMOTE6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)},
[IFLA_GENEVE_TTL] = {.type = NLA_U8},
[IFLA_GENEVE_TOS] = {.type = NLA_U8},
[IFLA_GENEVE_TTL_INHERIT] = {.type = NLA_U8},
[IFLA_GENEVE_PORT] = {.type = NLA_U16},
[IFLA_GENEVE_DF] = {.type = NLA_U8},
};
struct nlattr *tb[G_N_ELEMENTS(policy)];
NMPObject *obj;
NMPlatformLnkGeneve *props;
if (!info_data || !nm_streq0(kind, "geneve"))
return NULL;
if (nla_parse_nested_arr(tb, info_data, policy) < 0)
return NULL;
obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_GENEVE, NULL);
props = &obj->lnk_geneve;
if (tb[IFLA_GENEVE_ID])
props->id = nla_get_u32(tb[IFLA_GENEVE_ID]);
if (tb[IFLA_GENEVE_REMOTE])
props->remote = nla_get_u32(tb[IFLA_GENEVE_REMOTE]);
if (tb[IFLA_GENEVE_REMOTE6])
props->remote6 = *nla_data_as(struct in6_addr, tb[IFLA_GENEVE_REMOTE6]);
if (tb[IFLA_GENEVE_TTL_INHERIT] && nla_get_u8(tb[IFLA_GENEVE_TTL_INHERIT]))
props->ttl = -1;
else if (tb[IFLA_GENEVE_TTL])
props->ttl = nla_get_u8(tb[IFLA_GENEVE_TTL]);
if (tb[IFLA_GENEVE_TOS])
props->tos = nla_get_u8(tb[IFLA_GENEVE_TOS]);
if (tb[IFLA_GENEVE_PORT])
props->dst_port = ntohs(nla_get_u16(tb[IFLA_GENEVE_PORT]));
if (tb[IFLA_GENEVE_DF])
props->df = nla_get_u8(tb[IFLA_GENEVE_DF]);
return obj;
}
/*****************************************************************************/
static NMPObject *
_parse_lnk_hsr(const char *kind, struct nlattr *info_data)
{
@ -3694,6 +3748,9 @@ _new_from_nl_link(NMPlatform *platform,
case NM_LINK_TYPE_BOND:
lnk_data = _parse_lnk_bond(nl_info_kind, nl_info_data);
break;
case NM_LINK_TYPE_GENEVE:
lnk_data = _parse_lnk_geneve(nl_info_kind, nl_info_data);
break;
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
lnk_data = _parse_lnk_gre(nl_info_kind, nl_info_data);
@ -5182,6 +5239,35 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo
nla_nest_end(msg, info_peer);
break;
}
case NM_LINK_TYPE_GENEVE:
{
const NMPlatformLnkGeneve *props = extra_data;
nm_assert(props);
if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
goto nla_put_failure;
NLA_PUT_U32(msg, IFLA_GENEVE_ID, props->id);
if (props->remote) {
NLA_PUT_U32(msg, IFLA_GENEVE_REMOTE, props->remote);
} else if (!IN6_IS_ADDR_UNSPECIFIED(&props->remote6)) {
NLA_PUT(msg, IFLA_GENEVE_REMOTE6, sizeof(props->remote6), &props->remote6);
}
NLA_PUT_U16(msg, IFLA_GENEVE_PORT, htons(props->dst_port));
if (props->ttl == -1) {
NLA_PUT_U8(msg, IFLA_GENEVE_TTL_INHERIT, 1);
} else {
/* When you want to specify a TTL value,
* don't add TTL_INHERIT to the message */
NLA_PUT_U8(msg, IFLA_GENEVE_TTL, props->ttl & 0xff);
}
NLA_PUT_U8(msg, IFLA_GENEVE_TOS, props->tos);
NLA_PUT_U8(msg, IFLA_GENEVE_DF, props->df);
break;
}
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
{

View file

@ -1388,6 +1388,12 @@ nm_platform_link_add(NMPlatform *self,
case NM_LINK_TYPE_VETH:
nm_sprintf_buf(buf, ", veth-peer \"%s\"", (const char *) extra_data);
break;
case NM_LINK_TYPE_GENEVE:
nm_strbuf_append_str(&buf_p, &buf_len, ", ");
nm_platform_lnk_geneve_to_string((const NMPlatformLnkGeneve *) extra_data,
buf_p,
buf_len);
break;
case NM_LINK_TYPE_GRE:
case NM_LINK_TYPE_GRETAP:
nm_strbuf_append_str(&buf_p, &buf_len, ", ");
@ -2565,6 +2571,12 @@ nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformL
return _link_get_lnk(self, ifindex, NM_LINK_TYPE_BRIDGE, out_link);
}
const NMPlatformLnkGeneve *
nm_platform_link_get_lnk_geneve(NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
return _link_get_lnk(self, ifindex, NM_LINK_TYPE_GENEVE, out_link);
}
const NMPlatformLnkGre *
nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
{
@ -6494,6 +6506,52 @@ nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize le
return buf;
}
const char *
nm_platform_lnk_geneve_to_string(const NMPlatformLnkGeneve *lnk, char *buf, gsize len)
{
char str_remote[NM_INET_ADDRSTRLEN];
char str_remote1[30 + NM_INET_ADDRSTRLEN];
char str_remote6[NM_INET_ADDRSTRLEN];
char str_remote6_1[30 + NM_INET_ADDRSTRLEN];
char str_ttl[30];
char str_tos[30];
char str_id[30];
char str_dstport[30];
if (!nm_utils_to_string_buffer_init_null(lnk, &buf, &len))
return buf;
g_snprintf(
buf,
len,
"geneve"
"%s" /* id */
"%s" /* remote */
"%s" /* remote6 */
"%s" /* dst_port */
"%s" /* ttl */
"%s" /* tos */
"%s" /* df */
"",
lnk->id ? nm_sprintf_buf(str_id, " id %u", lnk->id) : "",
lnk->remote
? nm_sprintf_buf(str_remote, " remote %s", nm_inet4_ntop(lnk->remote, str_remote1))
: "",
!IN6_IS_ADDR_UNSPECIFIED(&lnk->remote6)
? nm_sprintf_buf(str_remote6, " remote %s", nm_inet6_ntop(&lnk->remote6, str_remote6_1))
: "",
lnk->dst_port ? nm_sprintf_buf(str_dstport, " dstport %u", lnk->dst_port) : "",
lnk->ttl > 0 ? nm_sprintf_buf(str_ttl, " ttl %u", lnk->ttl & 0xff)
: lnk->ttl == 0 ? "ttl auto"
: "ttl inherit",
lnk->tos ? (lnk->tos == 1 ? " tos inherit" : nm_sprintf_buf(str_tos, " tos 0x%x", lnk->tos))
: "",
lnk->df == 1 ? " df set "
: lnk->df == 2 ? " df inherit "
: "");
return buf;
}
const char *
nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len)
{
@ -8491,6 +8549,27 @@ nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b)
return 0;
}
void
nm_platform_lnk_geneve_hash_update(const NMPlatformLnkGeneve *obj, NMHashState *h)
{
nm_hash_update_vals(h, obj->id, obj->remote, obj->dst_port, obj->ttl, obj->tos, obj->df);
nm_hash_update_mem(h, &obj->remote6, sizeof(obj->remote6));
}
int
nm_platform_lnk_geneve_cmp(const NMPlatformLnkGeneve *a, const NMPlatformLnkGeneve *b)
{
NM_CMP_SELF(a, b);
NM_CMP_FIELD(a, b, id);
NM_CMP_FIELD(a, b, remote);
NM_CMP_FIELD_MEMCMP(a, b, remote6);
NM_CMP_FIELD(a, b, ttl);
NM_CMP_FIELD(a, b, tos);
NM_CMP_FIELD(a, b, dst_port);
NM_CMP_FIELD(a, b, df);
return 0;
}
void
nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h)
{

View file

@ -835,6 +835,16 @@ typedef struct {
bool use_carrier : 1;
} _nm_alignas(NMPlatformObject) NMPlatformLnkBond;
typedef struct {
struct in6_addr remote6;
in_addr_t remote;
guint32 id;
gint32 ttl;
guint16 dst_port;
guint8 tos;
guint8 df;
} _nm_alignas(NMPlatformObject) NMPlatformLnkGeneve;
typedef struct {
int parent_ifindex;
in_addr_t local;
@ -1858,6 +1868,15 @@ nm_platform_link_vxlan_add(NMPlatform *self,
return nm_platform_link_add(self, NM_LINK_TYPE_VXLAN, name, 0, NULL, 0, 0, props, out_link);
}
static inline int
nm_platform_link_geneve_add(NMPlatform *self,
const char *name,
const NMPlatformLnkGeneve *props,
const NMPlatformLink **out_link)
{
return nm_platform_link_add(self, NM_LINK_TYPE_GENEVE, name, 0, NULL, 0, 0, props, out_link);
}
static inline int
nm_platform_link_6lowpan_add(NMPlatform *self,
const char *name,
@ -2143,6 +2162,8 @@ const NMPlatformLnkBond *
nm_platform_link_get_lnk_bond(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkBridge *
nm_platform_link_get_lnk_bridge(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGeneve *
nm_platform_link_get_lnk_geneve(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGre *
nm_platform_link_get_lnk_gre(NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
const NMPlatformLnkGre *
@ -2482,6 +2503,7 @@ gboolean nm_platform_tc_sync(NMPlatform *self,
const char *nm_platform_link_to_string(const NMPlatformLink *link, char *buf, gsize len);
const char *nm_platform_lnk_bond_to_string(const NMPlatformLnkBond *lnk, char *buf, gsize len);
const char *nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsize len);
const char *nm_platform_lnk_geneve_to_string(const NMPlatformLnkGeneve *lnk, char *buf, gsize len);
const char *nm_platform_lnk_gre_to_string(const NMPlatformLnkGre *lnk, char *buf, gsize len);
const char *nm_platform_lnk_hsr_to_string(const NMPlatformLnkHsr *lnk, char *buf, gsize len);
const char *
@ -2537,6 +2559,7 @@ nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *bu
int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b);
int nm_platform_lnk_bond_cmp(const NMPlatformLnkBond *a, const NMPlatformLnkBond *b);
int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b);
int nm_platform_lnk_geneve_cmp(const NMPlatformLnkGeneve *a, const NMPlatformLnkGeneve *b);
int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b);
int nm_platform_lnk_hsr_cmp(const NMPlatformLnkHsr *a, const NMPlatformLnkHsr *b);
int nm_platform_lnk_infiniband_cmp(const NMPlatformLnkInfiniband *a,
@ -2612,6 +2635,7 @@ void nm_platform_routing_rule_hash_update(const NMPlatformRoutingRule *obj,
NMHashState *h);
void nm_platform_lnk_bond_hash_update(const NMPlatformLnkBond *obj, NMHashState *h);
void nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *h);
void nm_platform_lnk_geneve_hash_update(const NMPlatformLnkGeneve *obj, NMHashState *h);
void nm_platform_lnk_gre_hash_update(const NMPlatformLnkGre *obj, NMHashState *h);
void nm_platform_lnk_hsr_hash_update(const NMPlatformLnkHsr *obj, NMHashState *h);
void nm_platform_lnk_infiniband_hash_update(const NMPlatformLnkInfiniband *obj, NMHashState *h);

View file

@ -166,6 +166,7 @@ typedef enum _nm_packed {
NMP_OBJECT_TYPE_TFILTER,
NMP_OBJECT_TYPE_LNK_BRIDGE,
NMP_OBJECT_TYPE_LNK_GENEVE,
NMP_OBJECT_TYPE_LNK_GRE,
NMP_OBJECT_TYPE_LNK_GRETAP,
NMP_OBJECT_TYPE_LNK_HSR,

View file

@ -3469,6 +3469,18 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_bridge_hash_update,
.cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_bridge_cmp,
},
[NMP_OBJECT_TYPE_LNK_GENEVE - 1] =
{
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
.obj_type = NMP_OBJECT_TYPE_LNK_GENEVE,
.sizeof_data = sizeof(NMPObjectLnkGeneve),
.sizeof_public = sizeof(NMPlatformLnkGeneve),
.obj_type_name = "geneve",
.lnk_link_type = NM_LINK_TYPE_GENEVE,
.cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_lnk_geneve_to_string,
.cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_geneve_hash_update,
.cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_geneve_cmp,
},
[NMP_OBJECT_TYPE_LNK_GRE - 1] =
{
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),

View file

@ -250,6 +250,10 @@ typedef struct {
NMPlatformLnkBond _public;
} NMPObjectLnkBond;
typedef struct {
NMPlatformLnkGeneve _public;
} NMPObjectLnkGeneve;
typedef struct {
NMPlatformLnkGre _public;
} NMPObjectLnkGre;
@ -383,6 +387,9 @@ struct _NMPObject {
NMPlatformLnkBond lnk_bond;
NMPObjectLnkBond _lnk_bond;
NMPlatformLnkGeneve lnk_geneve;
NMPObjectLnkGeneve _lnk_geneve;
NMPlatformLnkGre lnk_gre;
NMPObjectLnkGre _lnk_gre;
@ -543,6 +550,7 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type)
case NMP_OBJECT_TYPE_LNK_BRIDGE:
case NMP_OBJECT_TYPE_LNK_BOND:
case NMP_OBJECT_TYPE_LNK_GENEVE:
case NMP_OBJECT_TYPE_LNK_GRE:
case NMP_OBJECT_TYPE_LNK_GRETAP:
case NMP_OBJECT_TYPE_LNK_HSR:

View file

@ -19,6 +19,7 @@ G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectIP6Route))
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLink));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkBond));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkBridge));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkGeneve));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkGre));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkInfiniband));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPObjectLnkIp6Tnl));
@ -49,6 +50,7 @@ G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformIPXRoute)
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLink));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkBond));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkBridge));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkGeneve));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkGre));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkInfiniband));
G_STATIC_ASSERT(_nm_alignof(NMPlatformObject) == _nm_alignof(NMPlatformLnkIp6Tnl));