From 80c93b0e5e1554fe894d5e94c59ebb29b702da42 Mon Sep 17 00:00:00 2001 From: Sayed Shah Date: Thu, 6 Aug 2020 16:52:16 -0400 Subject: [PATCH] platform: add support for configuring bridge settings via netlink (2) NMDeviceBridge is currently using sysfs. The plan is to use netlink in in the future. https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/601 --- libnm-core/nm-core-internal.h | 8 ++-- src/devices/nm-device-bridge.c | 30 +++++++++++--- src/platform/nm-linux-platform.c | 52 ++++++++++++++++++++++-- src/platform/nm-platform.c | 68 +++++++++++++++++++++++++++++--- src/platform/nm-platform.h | 11 ++++++ src/platform/tests/test-common.c | 15 ++++++- src/platform/tests/test-link.c | 39 ++++++++++++++---- 7 files changed, 194 insertions(+), 29 deletions(-) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index b06ba7828..416dca13a 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -80,24 +80,24 @@ /* IEEE 802.1D-1998 timer values */ #define NM_BRIDGE_HELLO_TIME_MIN 1u #define NM_BRIDGE_HELLO_TIME_DEF 2u -#define NM_BRIDGE_HELLO_TIME_MAX 10u #define NM_BRIDGE_HELLO_TIME_DEF_SYS (NM_BRIDGE_HELLO_TIME_DEF * 100u) +#define NM_BRIDGE_HELLO_TIME_MAX 10u #define NM_BRIDGE_FORWARD_DELAY_MIN 2u #define NM_BRIDGE_FORWARD_DELAY_DEF 15u -#define NM_BRIDGE_FORWARD_DELAY_MAX 30u #define NM_BRIDGE_FORWARD_DELAY_DEF_SYS (NM_BRIDGE_FORWARD_DELAY_DEF * 100u) +#define NM_BRIDGE_FORWARD_DELAY_MAX 30u #define NM_BRIDGE_MAX_AGE_MIN 6u #define NM_BRIDGE_MAX_AGE_DEF 20u -#define NM_BRIDGE_MAX_AGE_MAX 40u #define NM_BRIDGE_MAX_AGE_DEF_SYS (NM_BRIDGE_MAX_AGE_DEF * 100u) +#define NM_BRIDGE_MAX_AGE_MAX 40u /* IEEE 802.1D-1998 Table 7.4 */ #define NM_BRIDGE_AGEING_TIME_MIN 0u #define NM_BRIDGE_AGEING_TIME_DEF 300u -#define NM_BRIDGE_AGEING_TIME_MAX 1000000u #define NM_BRIDGE_AGEING_TIME_DEF_SYS (NM_BRIDGE_AGEING_TIME_DEF * 100u) +#define NM_BRIDGE_AGEING_TIME_MAX 1000000u #define NM_BRIDGE_PORT_PRIORITY_MIN 0u #define NM_BRIDGE_PORT_PRIORITY_DEF 32u diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index dd41a0590..4f5a68e6a 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -232,6 +232,16 @@ from_sysfs_multicast_router (const char *value, GValue *out) /*****************************************************************************/ +#define _DEFAULT_IF_ZERO(val, def_val) \ + ({ \ + typeof (val) _val = (val); \ + typeof (val) _def_val = (def_val); \ + \ + (_val == 0) \ + ? _def_val \ + : _val; \ + }) + typedef struct { const char *name; const char *sysname; @@ -302,7 +312,6 @@ static const Option master_options[] = { OPTION (NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, "group_fwd_mask", OPTION_TYPE_INT (0, 0xFFFF, 0), - .default_if_zero = TRUE, ), OPTION (NM_SETTING_BRIDGE_MULTICAST_HASH_MAX, "hash_max", @@ -1018,10 +1027,21 @@ create_and_realize (NMDevice *device, } props = (NMPlatformLnkBridge) { - .forward_delay = nm_setting_bridge_get_forward_delay (s_bridge) * 100u, - .hello_time = nm_setting_bridge_get_hello_time (s_bridge) * 100u, - .max_age = nm_setting_bridge_get_max_age (s_bridge) * 100u, - .ageing_time = nm_setting_bridge_get_ageing_time (s_bridge) * 100u, + .stp_state = nm_setting_bridge_get_stp (s_bridge), + .forward_delay = _DEFAULT_IF_ZERO (nm_setting_bridge_get_forward_delay (s_bridge) * 100u, NM_BRIDGE_FORWARD_DELAY_DEF_SYS), + .hello_time = _DEFAULT_IF_ZERO (nm_setting_bridge_get_hello_time (s_bridge) * 100u, NM_BRIDGE_HELLO_TIME_DEF_SYS), + .max_age = _DEFAULT_IF_ZERO (nm_setting_bridge_get_max_age (s_bridge) * 100u, NM_BRIDGE_MAX_AGE_DEF_SYS), + .ageing_time = _DEFAULT_IF_ZERO (nm_setting_bridge_get_ageing_time (s_bridge) * 100u, NM_BRIDGE_AGEING_TIME_DEF_SYS), + .priority = nm_setting_bridge_get_priority (s_bridge), + .group_fwd_mask = nm_setting_bridge_get_group_forward_mask (s_bridge), + .mcast_last_member_count = nm_setting_bridge_get_multicast_last_member_count (s_bridge), + .mcast_last_member_interval = nm_setting_bridge_get_multicast_last_member_interval (s_bridge), + .mcast_membership_interval = nm_setting_bridge_get_multicast_membership_interval (s_bridge), + .mcast_querier_interval = nm_setting_bridge_get_multicast_querier_interval (s_bridge), + .mcast_query_interval = nm_setting_bridge_get_multicast_query_interval (s_bridge), + .mcast_query_response_interval = nm_setting_bridge_get_multicast_query_response_interval (s_bridge), + .mcast_startup_query_count = nm_setting_bridge_get_multicast_startup_query_count (s_bridge), + .mcast_startup_query_interval = nm_setting_bridge_get_multicast_startup_query_interval (s_bridge), }; r = nm_platform_link_bridge_add (nm_device_get_platform (device), diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index d1d2ef905..a5b7b710a 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1301,10 +1301,21 @@ static NMPObject * _parse_lnk_bridge (const char *kind, struct nlattr *info_data) { static const struct nla_policy policy[] = { - [IFLA_BR_FORWARD_DELAY] = { .type = NLA_U32 }, - [IFLA_BR_HELLO_TIME] = { .type = NLA_U32 }, - [IFLA_BR_MAX_AGE] = { .type = NLA_U32 }, - [IFLA_BR_AGEING_TIME] = { .type = NLA_U32 }, + [IFLA_BR_STP_STATE] = { .type = NLA_U32 }, + [IFLA_BR_FORWARD_DELAY] = { .type = NLA_U32 }, + [IFLA_BR_HELLO_TIME] = { .type = NLA_U32 }, + [IFLA_BR_MAX_AGE] = { .type = NLA_U32 }, + [IFLA_BR_AGEING_TIME] = { .type = NLA_U32 }, + [IFLA_BR_PRIORITY] = { .type = NLA_U16 }, + [IFLA_BR_GROUP_FWD_MASK] = { .type = NLA_U16 }, + [IFLA_BR_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 }, + [IFLA_BR_MCAST_LAST_MEMBER_INTVL] = { .type = NLA_U64 }, + [IFLA_BR_MCAST_MEMBERSHIP_INTVL] = { .type = NLA_U64 }, + [IFLA_BR_MCAST_QUERIER_INTVL] = { .type = NLA_U64 }, + [IFLA_BR_MCAST_QUERY_INTVL] = { .type = NLA_U64 }, + [IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 }, + [IFLA_BR_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 }, + [IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 }, }; NMPlatformLnkBridge *props; struct nlattr *tb[G_N_ELEMENTS (policy)]; @@ -1321,6 +1332,8 @@ _parse_lnk_bridge (const char *kind, struct nlattr *info_data) props = &obj->lnk_bridge; + if (tb[IFLA_BR_STP_STATE]) + props->stp_state = !!nla_get_u32 (tb[IFLA_BR_STP_STATE]); if (tb[IFLA_BR_FORWARD_DELAY]) props->forward_delay = nla_get_u32 (tb[IFLA_BR_FORWARD_DELAY]); if (tb[IFLA_BR_HELLO_TIME]) @@ -1329,6 +1342,26 @@ _parse_lnk_bridge (const char *kind, struct nlattr *info_data) props->max_age = nla_get_u32 (tb[IFLA_BR_MAX_AGE]); if (tb[IFLA_BR_AGEING_TIME]) props->ageing_time = nla_get_u32 (tb[IFLA_BR_AGEING_TIME]); + if (tb[IFLA_BR_PRIORITY]) + props->priority = nla_get_u16 (tb[IFLA_BR_PRIORITY]); + if (tb[IFLA_BR_GROUP_FWD_MASK]) + props->group_fwd_mask = nla_get_u16 (tb[IFLA_BR_GROUP_FWD_MASK]); + if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]) + props->mcast_last_member_count = nla_get_u32 (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]); + if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]) + props->mcast_last_member_interval = nla_get_u64 (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]); + if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]) + props->mcast_membership_interval = nla_get_u64 (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]); + if (tb[IFLA_BR_MCAST_QUERIER_INTVL]) + props->mcast_querier_interval = nla_get_u64 (tb[IFLA_BR_MCAST_QUERIER_INTVL]); + if (tb[IFLA_BR_MCAST_QUERY_INTVL]) + props->mcast_query_interval = nla_get_u64 (tb[IFLA_BR_MCAST_QUERY_INTVL]); + if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]) + props->mcast_query_response_interval = nla_get_u64 (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]); + if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]) + props->mcast_startup_query_count = nla_get_u32 (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]); + if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) + props->mcast_startup_query_interval = nla_get_u64 (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]); return obj; } @@ -4003,10 +4036,21 @@ _nl_msg_new_link_set_linkinfo (struct nl_msg *msg, if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) goto nla_put_failure; + NLA_PUT_U32 (msg, IFLA_BR_STP_STATE, !!props->stp_state); NLA_PUT_U32 (msg, IFLA_BR_FORWARD_DELAY, props->forward_delay); NLA_PUT_U32 (msg, IFLA_BR_HELLO_TIME, props->hello_time); NLA_PUT_U32 (msg, IFLA_BR_MAX_AGE, props->max_age); NLA_PUT_U32 (msg, IFLA_BR_AGEING_TIME, props->ageing_time); + NLA_PUT_U16 (msg, IFLA_BR_PRIORITY, props->priority); + NLA_PUT_U16 (msg, IFLA_BR_GROUP_FWD_MASK, props->group_fwd_mask); + NLA_PUT_U32 (msg, IFLA_BR_MCAST_LAST_MEMBER_CNT, props->mcast_last_member_count); + NLA_PUT_U64 (msg, IFLA_BR_MCAST_LAST_MEMBER_INTVL, props->mcast_last_member_interval); + NLA_PUT_U64 (msg, IFLA_BR_MCAST_MEMBERSHIP_INTVL, props->mcast_membership_interval); + NLA_PUT_U64 (msg, IFLA_BR_MCAST_QUERIER_INTVL, props->mcast_querier_interval); + NLA_PUT_U64 (msg, IFLA_BR_MCAST_QUERY_INTVL, props->mcast_query_interval); + NLA_PUT_U64 (msg, IFLA_BR_MCAST_QUERY_RESPONSE_INTVL, props->mcast_query_response_interval); + NLA_PUT_U32 (msg, IFLA_BR_MCAST_STARTUP_QUERY_CNT, props->mcast_startup_query_count); + NLA_PUT_U64 (msg, IFLA_BR_MCAST_STARTUP_QUERY_INTVL, props->mcast_startup_query_interval); break; } case NM_LINK_TYPE_VLAN: { diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index f42bb9bc6..be2b5b740 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -5383,10 +5383,21 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) } const NMPlatformLnkBridge nm_platform_lnk_bridge_default = { - .forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF_SYS, - .hello_time = NM_BRIDGE_HELLO_TIME_DEF_SYS, - .max_age = NM_BRIDGE_MAX_AGE_DEF_SYS, - .ageing_time = NM_BRIDGE_AGEING_TIME_DEF_SYS, + .stp_state = FALSE, + .forward_delay = NM_BRIDGE_FORWARD_DELAY_DEF_SYS, + .hello_time = NM_BRIDGE_HELLO_TIME_DEF_SYS, + .max_age = NM_BRIDGE_MAX_AGE_DEF_SYS, + .ageing_time = NM_BRIDGE_AGEING_TIME_DEF_SYS, + .priority = NM_BRIDGE_PRIORITY_DEF, + .group_fwd_mask = 0, + .mcast_last_member_count = NM_BRIDGE_MULTICAST_LAST_MEMBER_COUNT_DEF, + .mcast_last_member_interval = NM_BRIDGE_MULTICAST_LAST_MEMBER_INTERVAL_DEF, + .mcast_membership_interval = NM_BRIDGE_MULTICAST_MEMBERSHIP_INTERVAL_DEF, + .mcast_querier_interval = NM_BRIDGE_MULTICAST_QUERIER_INTERVAL_DEF, + .mcast_query_interval = NM_BRIDGE_MULTICAST_QUERY_INTERVAL_DEF, + .mcast_query_response_interval = NM_BRIDGE_MULTICAST_QUERY_RESPONSE_INTERVAL_DEF, + .mcast_startup_query_count = NM_BRIDGE_MULTICAST_STARTUP_QUERY_COUNT_DEF, + .mcast_startup_query_interval = NM_BRIDGE_MULTICAST_STARTUP_QUERY_INTERVAL_DEF, }; const char * @@ -5400,11 +5411,33 @@ nm_platform_lnk_bridge_to_string (const NMPlatformLnkBridge *lnk, char *buf, gsi " hello_time %u" " max_age %u" " ageing_time %u" + " stp_state %d" + " priority %u" + " group_fwd_mask %#x" + " mcast_last_member_count %u" + " mcast_startup_query_count %u" + " mcast_last_member_interval %"G_GUINT64_FORMAT"" + " mcast_membership_interval %"G_GUINT64_FORMAT"" + " mcast_querier_interval %"G_GUINT64_FORMAT"" + " mcast_query_interval %"G_GUINT64_FORMAT"" + " mcast_query_response_interval %"G_GUINT64_FORMAT"" + " mcast_startup_query_interval %"G_GUINT64_FORMAT"" "", lnk->forward_delay, lnk->hello_time, lnk->max_age, - lnk->ageing_time); + lnk->ageing_time, + (int) lnk->stp_state, + lnk->priority, + lnk->group_fwd_mask, + lnk->mcast_last_member_count, + lnk->mcast_startup_query_count, + lnk->mcast_last_member_interval, + lnk->mcast_membership_interval, + lnk->mcast_querier_interval, + lnk->mcast_query_interval, + lnk->mcast_query_response_interval, + lnk->mcast_startup_query_interval); return buf; } @@ -6901,20 +6934,43 @@ void nm_platform_lnk_bridge_hash_update (const NMPlatformLnkBridge *obj, NMHashState *h) { nm_hash_update_vals (h, + (bool) obj->stp_state, obj->forward_delay, obj->hello_time, obj->max_age, - obj->ageing_time); + obj->ageing_time, + obj->priority, + obj->group_fwd_mask, + obj->mcast_last_member_count, + obj->mcast_last_member_interval, + obj->mcast_membership_interval, + obj->mcast_querier_interval, + obj->mcast_query_interval, + obj->mcast_query_response_interval, + obj->mcast_startup_query_count, + obj->mcast_startup_query_interval); } int nm_platform_lnk_bridge_cmp (const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b) { NM_CMP_SELF (a, b); + NM_CMP_FIELD_BOOL (a, b, stp_state); NM_CMP_FIELD (a, b, forward_delay); NM_CMP_FIELD (a, b, hello_time); NM_CMP_FIELD (a, b, max_age); NM_CMP_FIELD (a, b, ageing_time); + NM_CMP_FIELD (a, b, priority); + NM_CMP_FIELD (a, b, group_fwd_mask); + NM_CMP_FIELD (a, b, mcast_last_member_count); + NM_CMP_FIELD (a, b, mcast_last_member_interval); + NM_CMP_FIELD (a, b, mcast_membership_interval); + NM_CMP_FIELD (a, b, mcast_querier_interval); + NM_CMP_FIELD (a, b, mcast_query_interval); + NM_CMP_FIELD (a, b, mcast_query_response_interval); + NM_CMP_FIELD (a, b, mcast_startup_query_count); + NM_CMP_FIELD (a, b, mcast_startup_query_interval); + return 0; } diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index eb4379cbc..a3bde1b7f 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -763,10 +763,21 @@ typedef struct { } NMPlatformBridgeVlan; typedef struct { + bool stp_state:1; guint32 forward_delay; guint32 hello_time; guint32 max_age; guint32 ageing_time; + guint16 priority; + guint16 group_fwd_mask; + guint32 mcast_last_member_count; + guint64 mcast_last_member_interval; + guint64 mcast_membership_interval; + guint64 mcast_querier_interval; + guint64 mcast_query_interval; + guint64 mcast_query_response_interval; + guint32 mcast_startup_query_count; + guint64 mcast_startup_query_interval; } NMPlatformLnkBridge; extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default; diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 13e93e7c9..47f9cbee5 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1190,12 +1190,23 @@ nmtstp_link_bridge_add (NMPlatform *platform, _init_platform (&platform, external_command); if (external_command) { - r = nmtstp_run_command ("ip link add %s type bridge forward_delay %u hello_time %u max_age %u ageing_time %u", + r = nmtstp_run_command ("ip link add %s type bridge forward_delay %u hello_time %u max_age %u ageing_time %u stp_state %d priority %u group_fwd_mask %#x mcast_last_member_count %u mcast_startup_query_count %u mcast_last_member_interval %"G_GUINT64_FORMAT" mcast_membership_interval %"G_GUINT64_FORMAT" mcast_querier_interval %"G_GUINT64_FORMAT" mcast_query_interval %"G_GUINT64_FORMAT" mcast_query_response_interval %"G_GUINT64_FORMAT" mcast_startup_query_interval %"G_GUINT64_FORMAT"", name, lnk->forward_delay, lnk->hello_time, lnk->max_age, - lnk->ageing_time); + lnk->ageing_time, + (int) lnk->stp_state, + lnk->priority, + lnk->group_fwd_mask, + lnk->mcast_last_member_count, + lnk->mcast_startup_query_count, + lnk->mcast_last_member_interval, + lnk->mcast_membership_interval, + lnk->mcast_querier_interval, + lnk->mcast_query_interval, + lnk->mcast_query_response_interval, + lnk->mcast_startup_query_interval); g_assert_cmpint (r, ==, 0); pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_BRIDGE, 100); } diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 6ce025e87..3927a3043 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -965,10 +965,21 @@ test_software_detect (gconstpointer user_data) NMPlatformLnkBridge lnk_bridge = { }; gboolean not_supported; - lnk_bridge.forward_delay = 1560; - lnk_bridge.hello_time = 150; - lnk_bridge.max_age = 2100; - lnk_bridge.ageing_time = 2200; + lnk_bridge.stp_state = TRUE; + lnk_bridge.forward_delay = 1560; + lnk_bridge.hello_time = 150; + lnk_bridge.max_age = 2100; + lnk_bridge.ageing_time = 2200; + lnk_bridge.priority = 22; + lnk_bridge.group_fwd_mask = 8; + lnk_bridge.mcast_last_member_count = 2; + lnk_bridge.mcast_last_member_interval = 5000; + lnk_bridge.mcast_membership_interval = 25000; + lnk_bridge.mcast_querier_interval = 26000; + lnk_bridge.mcast_query_interval = 12000; + lnk_bridge.mcast_query_response_interval = 5200; + lnk_bridge.mcast_startup_query_count = 3; + lnk_bridge.mcast_startup_query_interval = 3000; if (!nmtstp_link_bridge_add (NULL, ext, DEVICE_NAME, &lnk_bridge, ¬_supported)) { if (not_supported) { @@ -1348,10 +1359,22 @@ test_software_detect (gconstpointer user_data) const NMPlatformLnkBridge *plnk = &lnk->lnk_bridge; g_assert (plnk == nm_platform_link_get_lnk_bridge (NM_PLATFORM_GET, ifindex, NULL)); - g_assert_cmpint (plnk->forward_delay, ==, 1560); - g_assert_cmpint (plnk->hello_time , ==, 150); - g_assert_cmpint (plnk->max_age , ==, 2100); - g_assert_cmpint (plnk->ageing_time , ==, 2200); + g_assert_cmpint (plnk->stp_state , ==, TRUE); + g_assert_cmpint (plnk->forward_delay , ==, 1560); + g_assert_cmpint (plnk->hello_time , ==, 150); + g_assert_cmpint (plnk->max_age , ==, 2100); + g_assert_cmpint (plnk->ageing_time , ==, 2200); + g_assert_cmpint (plnk->priority , ==, 22); + g_assert_cmpint (plnk->group_fwd_mask , ==, 8); + g_assert_cmpint (plnk->mcast_last_member_count , ==, 2); + g_assert_cmpint (plnk->mcast_last_member_interval , ==, 5000); + g_assert_cmpint (plnk->mcast_membership_interval , ==, 25000); + g_assert_cmpint (plnk->mcast_querier_interval , ==, 26000); + g_assert_cmpint (plnk->mcast_query_interval , ==, 12000); + g_assert_cmpint (plnk->mcast_query_response_interval , ==, 5200); + g_assert_cmpint (plnk->mcast_startup_query_count , ==, 3); + g_assert_cmpint (plnk->mcast_startup_query_interval , ==, 3000); + break; } case NM_LINK_TYPE_GRE: {