diff options
author | Thomas Haller <thaller@redhat.com> | 2022-07-07 12:55:50 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-07-19 12:33:50 +0200 |
commit | 3b58404712425093b40d36fe52cd6935d8bb94f6 (patch) | |
tree | b26d39c7a8470e22a8300532db5edf5e18b8a77c | |
parent | 9ef02ef7d0e8252a656650bc1426caafec6d906f (diff) | |
download | NetworkManager-3b58404712425093b40d36fe52cd6935d8bb94f6.tar.gz |
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.
-rw-r--r-- | src/core/platform/tests/test-platform-general.c | 60 | ||||
-rw-r--r-- | src/libnm-platform/nm-platform.c | 70 | ||||
-rw-r--r-- | src/libnm-platform/nm-platform.h | 19 |
3 files changed, 149 insertions, 0 deletions
diff --git a/src/core/platform/tests/test-platform-general.c b/src/core/platform/tests/test-platform-general.c index 908ad4dd3e..c18886c96e 100644 --- a/src/core/platform/tests/test-platform-general.c +++ b/src/core/platform/tests/test-platform-general.c @@ -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(); } diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index 50204abc5f..ab21f3f289 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -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 diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index b921a2f562..e940f43b60 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -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; |