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
This commit is contained in:
Sayed Shah 2020-08-06 16:52:16 -04:00 committed by Thomas Haller
parent d9568ca3ee
commit 80c93b0e5e
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
7 changed files with 194 additions and 29 deletions

View file

@ -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

View file

@ -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),

View file

@ -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: {

View file

@ -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;
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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, &not_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: {