platform: add NMPGenlFamilyType enum for generic netlink types

The genl types that we care about are well known. Add an enum
for them, so we can do a lookup by index.

To kernel, the corresponding names (like "wireguard") are also well
known. However, the family-id, that we need when using genl are
allocated dynamically. So we need to lookup the family-id, and by having
an enum for the genl type, we can do so generically.
This commit is contained in:
Thomas Haller
2022-07-07 12:55:50 +02:00
parent 9ef02ef7d0
commit 3b58404712
3 changed files with 149 additions and 0 deletions

View File

@@ -788,6 +788,64 @@ test_route_type_is_nodev(void)
/*****************************************************************************/
static void
test_nmp_genl_family_type_from_name(void)
{
int n_run;
int i;
for (i = 0; i < (int) _NMP_GENL_FAMILY_TYPE_NUM; i++) {
const char *name = nmp_genl_family_infos[i].name;
g_assert(name);
if (i > 0)
g_assert_cmpint(strcmp(nmp_genl_family_infos[i - 1].name, name), <, 0);
}
g_assert_cmpint(nmp_genl_family_type_from_name("ethtool"), ==, NMP_GENL_FAMILY_TYPE_ETHTOOL);
g_assert_cmpint(nmp_genl_family_type_from_name("mptcp_pm"), ==, NMP_GENL_FAMILY_TYPE_MPTCP_PM);
g_assert_cmpint(nmp_genl_family_type_from_name("nl80211"), ==, NMP_GENL_FAMILY_TYPE_NL80211);
g_assert_cmpint(nmp_genl_family_type_from_name("nl802154"), ==, NMP_GENL_FAMILY_TYPE_NL802154);
g_assert_cmpint(nmp_genl_family_type_from_name("wireguard"),
==,
NMP_GENL_FAMILY_TYPE_WIREGUARD);
g_assert_cmpint(nmp_genl_family_type_from_name(NULL), ==, _NMP_GENL_FAMILY_TYPE_NONE);
g_assert_cmpint(nmp_genl_family_type_from_name("a"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
g_assert_cmpint(nmp_genl_family_type_from_name("wireguara"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
g_assert_cmpint(nmp_genl_family_type_from_name("wireguarb"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
g_assert_cmpint(nmp_genl_family_type_from_name(""), ==, _NMP_GENL_FAMILY_TYPE_NONE);
g_assert_cmpint(nmp_genl_family_type_from_name("z"), ==, _NMP_GENL_FAMILY_TYPE_NONE);
for (n_run = 0; n_run < 20; n_run++) {
for (i = 0; i < (int) _NMP_GENL_FAMILY_TYPE_NUM; i++) {
const char *cname = nmp_genl_family_infos[i].name;
const int ch_idx = nmtst_get_rand_uint() % strlen(cname);
char name[200];
char ch;
gsize l;
l = g_strlcpy(name, cname, sizeof(name));
g_assert_cmpint(l, <, sizeof(name));
if (n_run == 0) {
g_assert_cmpint(nmp_genl_family_type_from_name(cname), ==, i);
g_assert_cmpint(nmp_genl_family_type_from_name(name), ==, i);
}
/* randomly change one character in the name. Such a name becomes invalid.
* There are no two valid names which only differ by one characters. */
do {
ch = nmtst_get_rand_uint() % 256;
} while (cname[ch_idx] == ch);
name[ch_idx] = ch;
g_assert_cmpint(nmp_genl_family_type_from_name(name), ==, _NMP_GENL_FAMILY_TYPE_NONE);
}
}
}
/*****************************************************************************/
NMTST_DEFINE();
int
@@ -808,6 +866,8 @@ main(int argc, char **argv)
GINT_TO_POINTER(2),
test_platform_ip_address_pretty_sort_cmp);
g_test_add_func("/general/test_route_type_is_nodev", test_route_type_is_nodev);
g_test_add_func("/nm-platform/test_nmp_genl_family_type_from_name",
test_nmp_genl_family_type_from_name);
return g_test_run();
}

View File

@@ -395,6 +395,76 @@ _nm_platform_kernel_support_init(NMPlatformKernelSupportType type, int value)
/*****************************************************************************/
const NMPGenlFamilyInfo nmp_genl_family_infos[_NMP_GENL_FAMILY_TYPE_NUM] = {
[NMP_GENL_FAMILY_TYPE_ETHTOOL] =
{
.name = "ethtool",
},
[NMP_GENL_FAMILY_TYPE_MPTCP_PM] =
{
.name = "mptcp_pm",
},
[NMP_GENL_FAMILY_TYPE_NL80211] =
{
.name = "nl80211",
},
[NMP_GENL_FAMILY_TYPE_NL802154] =
{
.name = "nl802154",
},
[NMP_GENL_FAMILY_TYPE_WIREGUARD] =
{
.name = "wireguard",
},
};
NMPGenlFamilyType
nmp_genl_family_type_from_name(const char *name)
{
int imin, imax, imid;
if (NM_MORE_ASSERT_ONCE(50)) {
int i;
for (i = 0; i < (int) G_N_ELEMENTS(nmp_genl_family_infos); i++) {
nm_assert(nmp_genl_family_infos[i].name);
if (i > 0)
nm_assert(strcmp(nmp_genl_family_infos[i - 1].name, nmp_genl_family_infos[i].name)
< 0);
}
}
if (!name)
goto out;
imin = 0;
imax = G_N_ELEMENTS(nmp_genl_family_infos) - 1;
imid = imax / 2;
while (TRUE) {
int c;
c = strcmp(nmp_genl_family_infos[imid].name, name);
if (c == 0)
return (NMPGenlFamilyType) imid;
if (c < 0)
imin = imid + 1;
else
imax = imid - 1;
if (imin > imax)
break;
imid = (imax + imin) / 2;
}
out:
return _NMP_GENL_FAMILY_TYPE_NONE;
}
/*****************************************************************************/
/**
* nm_platform_process_events:
* @self: platform instance

View File

@@ -1103,6 +1103,25 @@ nm_platform_kernel_support_get(NMPlatformKernelSupportType type)
return nm_platform_kernel_support_get_full(type, TRUE) != NM_OPTION_BOOL_FALSE;
}
typedef enum {
NMP_GENL_FAMILY_TYPE_ETHTOOL,
NMP_GENL_FAMILY_TYPE_MPTCP_PM,
NMP_GENL_FAMILY_TYPE_NL80211,
NMP_GENL_FAMILY_TYPE_NL802154,
NMP_GENL_FAMILY_TYPE_WIREGUARD,
_NMP_GENL_FAMILY_TYPE_NUM,
_NMP_GENL_FAMILY_TYPE_NONE = _NMP_GENL_FAMILY_TYPE_NUM,
} NMPGenlFamilyType;
typedef struct {
const char *name;
} NMPGenlFamilyInfo;
extern const NMPGenlFamilyInfo nmp_genl_family_infos[_NMP_GENL_FAMILY_TYPE_NUM];
NMPGenlFamilyType nmp_genl_family_type_from_name(const char *name);
/*****************************************************************************/
struct _NMPlatformPrivate;