From ec582d788c9f05874cedc080da038675d1196b99 Mon Sep 17 00:00:00 2001 From: Sayed Shah Date: Wed, 5 Aug 2020 13:39:12 -0400 Subject: [PATCH 1/2] nmp-object: add space before parentheses --- src/platform/nmp-object.c | 49 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 615c458ab7..2bc7bf6f66 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -3051,7 +3051,7 @@ G_STATIC_ASSERT (AF_UNSPEC == 0); const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { [NMP_OBJECT_TYPE_LINK - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LINK, .sizeof_data = sizeof (NMPObjectLink), .sizeof_public = sizeof (NMPlatformLink), @@ -3076,7 +3076,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_link_cmp, }, [NMP_OBJECT_TYPE_IP4_ADDRESS - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS, .sizeof_data = sizeof (NMPObjectIP4Address), .sizeof_public = sizeof (NMPlatformIP4Address), @@ -3096,7 +3096,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_address_cmp, }, [NMP_OBJECT_TYPE_IP6_ADDRESS - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS, .sizeof_data = sizeof (NMPObjectIP6Address), .sizeof_public = sizeof (NMPlatformIP6Address), @@ -3116,7 +3116,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_address_cmp }, [NMP_OBJECT_TYPE_IP4_ROUTE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_IP4_ROUTE, .sizeof_data = sizeof (NMPObjectIP4Route), .sizeof_public = sizeof (NMPlatformIP4Route), @@ -3136,7 +3136,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip4_route_cmp_full, }, [NMP_OBJECT_TYPE_IP6_ROUTE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_IP6_ROUTE, .sizeof_data = sizeof (NMPObjectIP6Route), .sizeof_public = sizeof (NMPlatformIP6Route), @@ -3156,7 +3156,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_ip6_route_cmp_full, }, [NMP_OBJECT_TYPE_ROUTING_RULE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_ROUTING_RULE, .sizeof_data = sizeof (NMPObjectRoutingRule), .sizeof_public = sizeof (NMPlatformRoutingRule), @@ -3175,7 +3175,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_routing_rule_cmp_full, }, [NMP_OBJECT_TYPE_QDISC - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_QDISC, .sizeof_data = sizeof (NMPObjectQdisc), .sizeof_public = sizeof (NMPlatformQdisc), @@ -3193,7 +3193,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_qdisc_cmp, }, [NMP_OBJECT_TYPE_TFILTER - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_TFILTER, .sizeof_data = sizeof (NMPObjectTfilter), .sizeof_public = sizeof (NMPlatformTfilter), @@ -3211,7 +3211,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_tfilter_cmp, }, [NMP_OBJECT_TYPE_LNK_GRE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_GRE, .sizeof_data = sizeof (NMPObjectLnkGre), .sizeof_public = sizeof (NMPlatformLnkGre), @@ -3222,7 +3222,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp, }, [NMP_OBJECT_TYPE_LNK_GRETAP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_GRETAP, .sizeof_data = sizeof (NMPObjectLnkGre), .sizeof_public = sizeof (NMPlatformLnkGre), @@ -3233,7 +3233,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp, }, [NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_INFINIBAND, .sizeof_data = sizeof (NMPObjectLnkInfiniband), .sizeof_public = sizeof (NMPlatformLnkInfiniband), @@ -3244,7 +3244,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_infiniband_cmp, }, [NMP_OBJECT_TYPE_LNK_IP6TNL - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_IP6TNL, .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), @@ -3255,7 +3255,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, }, [NMP_OBJECT_TYPE_LNK_IP6GRE - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRE, .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), @@ -3266,7 +3266,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, }, [NMP_OBJECT_TYPE_LNK_IP6GRETAP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_IP6GRETAP, .sizeof_data = sizeof (NMPObjectLnkIp6Tnl), .sizeof_public = sizeof (NMPlatformLnkIp6Tnl), @@ -3277,7 +3277,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp, }, [NMP_OBJECT_TYPE_LNK_IPIP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_IPIP, .sizeof_data = sizeof (NMPObjectLnkIpIp), .sizeof_public = sizeof (NMPlatformLnkIpIp), @@ -3288,7 +3288,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ipip_cmp, }, [NMP_OBJECT_TYPE_LNK_MACSEC - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_MACSEC, .sizeof_data = sizeof (NMPObjectLnkMacsec), .sizeof_public = sizeof (NMPlatformLnkMacsec), @@ -3299,7 +3299,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macsec_cmp, }, [NMP_OBJECT_TYPE_LNK_MACVLAN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_MACVLAN, .sizeof_data = sizeof (NMPObjectLnkMacvlan), .sizeof_public = sizeof (NMPlatformLnkMacvlan), @@ -3310,7 +3310,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp, }, [NMP_OBJECT_TYPE_LNK_MACVTAP - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_MACVTAP, .sizeof_data = sizeof (NMPObjectLnkMacvtap), .sizeof_public = sizeof (NMPlatformLnkMacvlan), @@ -3321,7 +3321,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_macvlan_cmp, }, [NMP_OBJECT_TYPE_LNK_SIT - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_SIT, .sizeof_data = sizeof (NMPObjectLnkSit), .sizeof_public = sizeof (NMPlatformLnkSit), @@ -3332,7 +3332,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_sit_cmp, }, [NMP_OBJECT_TYPE_LNK_TUN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_TUN, .sizeof_data = sizeof (NMPObjectLnkTun), .sizeof_public = sizeof (NMPlatformLnkTun), @@ -3343,7 +3343,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_tun_cmp, }, [NMP_OBJECT_TYPE_LNK_VLAN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_VLAN, .sizeof_data = sizeof (NMPObjectLnkVlan), .sizeof_public = sizeof (NMPlatformLnkVlan), @@ -3359,7 +3359,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp, }, [NMP_OBJECT_TYPE_LNK_VRF - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_VRF, .sizeof_data = sizeof (NMPObjectLnkVrf), .sizeof_public = sizeof (NMPlatformLnkVrf), @@ -3369,9 +3369,8 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vrf_hash_update, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vrf_cmp, }, - [NMP_OBJECT_TYPE_LNK_VXLAN - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_VXLAN, .sizeof_data = sizeof (NMPObjectLnkVxlan), .sizeof_public = sizeof (NMPlatformLnkVxlan), @@ -3382,7 +3381,7 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vxlan_cmp, }, [NMP_OBJECT_TYPE_LNK_WIREGUARD - 1] = { - .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_WIREGUARD, .sizeof_data = sizeof (NMPObjectLnkWireGuard), .sizeof_public = sizeof (NMPlatformLnkWireGuard), From adf04202583ed649327e24991c885374e335f9c2 Mon Sep 17 00:00:00 2001 From: Sayed Shah Date: Wed, 5 Aug 2020 13:46:28 -0400 Subject: [PATCH 2/2] platform: add support for configuring bridge settings via netlink NMDeviceBridge is currently using sysfs. The plan is to use netlink in in the future --- libnm-core/nm-core-internal.h | 4 +++ src/devices/nm-device-bridge.c | 9 +++++ src/nm-types.h | 1 + src/platform/nm-fake-platform.c | 8 +++++ src/platform/nm-linux-platform.c | 55 ++++++++++++++++++++++++++++++ src/platform/nm-platform.c | 57 ++++++++++++++++++++++++++++++++ src/platform/nm-platform.h | 16 ++++++++- src/platform/nmp-object.c | 11 ++++++ src/platform/nmp-object.h | 8 +++++ src/platform/tests/test-common.c | 36 ++++++++++++++++++++ src/platform/tests/test-common.h | 5 +++ src/platform/tests/test-link.c | 50 ++++++++++++++++++++++++++-- 12 files changed, 256 insertions(+), 4 deletions(-) diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 76eed31f05..b06ba78286 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -81,19 +81,23 @@ #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_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_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) /* 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_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 544e66140c..dd41a0590a 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -988,6 +988,7 @@ create_and_realize (NMDevice *device, const char *hwaddr; gs_free char *hwaddr_cloned = NULL; guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX]; + NMPlatformLnkBridge props; int r; nm_assert (iface); @@ -1016,10 +1017,18 @@ 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, + }; + r = nm_platform_link_bridge_add (nm_device_get_platform (device), iface, hwaddr ? mac_address : NULL, hwaddr ? ETH_ALEN : 0, + &props, out_plink); if (r < 0) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, diff --git a/src/nm-types.h b/src/nm-types.h index b3530f5bfb..f91bc2d0e0 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -221,6 +221,7 @@ typedef enum { NMP_OBJECT_TYPE_TFILTER, + NMP_OBJECT_TYPE_LNK_BRIDGE, NMP_OBJECT_TYPE_LNK_GRE, NMP_OBJECT_TYPE_LNK_GRETAP, NMP_OBJECT_TYPE_LNK_INFINIBAND, diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index d9cf2de542..908d3bdb2a 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -309,6 +309,14 @@ link_add (NMPlatform *platform, g_assert ((parent != 0) == NM_IN_SET (type, NM_LINK_TYPE_VLAN)); switch (type) { + case NM_LINK_TYPE_BRIDGE: { + const NMPlatformLnkBridge *props = extra_data; + + g_assert (props); + + dev_lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_BRIDGE, props); + break; + } case NM_LINK_TYPE_VETH: veth_peer = extra_data; g_assert (veth_peer); diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index ddb4794361..d1d2ef905e 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1297,6 +1297,44 @@ _parse_af_inet6 (NMPlatform *platform, /*****************************************************************************/ +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 }, + }; + NMPlatformLnkBridge *props; + struct nlattr *tb[G_N_ELEMENTS (policy)]; + NMPObject *obj; + + if ( !info_data + || !nm_streq0 (kind, "bridge")) + return NULL; + + if (nla_parse_nested_arr (tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_BRIDGE, NULL); + + props = &obj->lnk_bridge; + + if (tb[IFLA_BR_FORWARD_DELAY]) + props->forward_delay = nla_get_u32 (tb[IFLA_BR_FORWARD_DELAY]); + if (tb[IFLA_BR_HELLO_TIME]) + props->hello_time = nla_get_u32 (tb[IFLA_BR_HELLO_TIME]); + if (tb[IFLA_BR_MAX_AGE]) + 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]); + + return obj; +} + +/***********************************************************************************/ + static NMPObject * _parse_lnk_gre (const char *kind, struct nlattr *info_data) { @@ -2933,6 +2971,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr } switch (obj->link.type) { + case NM_LINK_TYPE_BRIDGE: + lnk_data = _parse_lnk_bridge (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); @@ -3954,6 +3995,20 @@ _nl_msg_new_link_set_linkinfo (struct nl_msg *msg, NLA_PUT_STRING (msg, IFLA_INFO_KIND, kind); switch (link_type) { + case NM_LINK_TYPE_BRIDGE: { + const NMPlatformLnkBridge *props = extra_data; + + nm_assert (extra_data); + + if (!(data = nla_nest_start (msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + 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); + break; + } case NM_LINK_TYPE_VLAN: { const NMPlatformLnkVlan *props = extra_data; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 90dbc94b7b..f42bb9bc64 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1224,6 +1224,10 @@ nm_platform_link_add (NMPlatform *self, buf[0] = '\0'; switch (type) { + case NM_LINK_TYPE_BRIDGE: + nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); + nm_platform_lnk_bridge_to_string ((const NMPlatformLnkBridge *) extra_data, buf_p, buf_len); + break; case NM_LINK_TYPE_VLAN: nm_utils_strbuf_append_str (&buf_p, &buf_len, ", "); nm_platform_lnk_vlan_to_string ((const NMPlatformLnkVlan *) extra_data, buf_p, buf_len); @@ -2203,6 +2207,12 @@ _link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlat return lnk ? &lnk->object : NULL; } +const NMPlatformLnkBridge * +nm_platform_link_get_lnk_bridge (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) +{ + return _link_get_lnk (self, ifindex, NM_LINK_TYPE_BRIDGE, out_link); +} + const NMPlatformLnkGre * nm_platform_link_get_lnk_gre (NMPlatform *self, int ifindex, const NMPlatformLink **out_link) { @@ -5372,6 +5382,32 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len) return buf; } +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, +}; + +const char * +nm_platform_lnk_bridge_to_string (const NMPlatformLnkBridge *lnk, char *buf, gsize len) +{ + if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) + return buf; + + g_snprintf (buf, len, + "forward_delay %u" + " hello_time %u" + " max_age %u" + " ageing_time %u" + "", + lnk->forward_delay, + lnk->hello_time, + lnk->max_age, + lnk->ageing_time); + return buf; +} + const char * nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len) { @@ -6861,6 +6897,27 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b) return 0; } +void +nm_platform_lnk_bridge_hash_update (const NMPlatformLnkBridge *obj, NMHashState *h) +{ + nm_hash_update_vals (h, + obj->forward_delay, + obj->hello_time, + obj->max_age, + obj->ageing_time); +} + +int +nm_platform_lnk_bridge_cmp (const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b) +{ + NM_CMP_SELF (a, b); + 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); + return 0; +} + void nm_platform_lnk_gre_hash_update (const NMPlatformLnkGre *obj, NMHashState *h) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 84dcfbb4aa..eb4379cbc2 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -762,6 +762,15 @@ typedef struct { bool pvid:1; } NMPlatformBridgeVlan; +typedef struct { + guint32 forward_delay; + guint32 hello_time; + guint32 max_age; + guint32 ageing_time; +} NMPlatformLnkBridge; + +extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default; + typedef struct { in_addr_t local; in_addr_t remote; @@ -1453,9 +1462,10 @@ nm_platform_link_bridge_add (NMPlatform *self, const char *name, const void *address, size_t address_len, + const NMPlatformLnkBridge *props, const NMPlatformLink **out_link) { - return nm_platform_link_add (self, NM_LINK_TYPE_BRIDGE, name, 0, address, address_len, NULL, out_link); + return nm_platform_link_add (self, NM_LINK_TYPE_BRIDGE, name, 0, address, address_len, props, out_link); } static inline int @@ -1717,6 +1727,7 @@ gboolean nm_platform_sysctl_slave_set_option (NMPlatform *self, int ifindex, con char *nm_platform_sysctl_slave_get_option (NMPlatform *self, int ifindex, const char *option); const NMPObject *nm_platform_link_get_lnk (NMPlatform *self, int ifindex, NMLinkType link_type, const NMPlatformLink **out_link); +const NMPlatformLnkBridge *nm_platform_link_get_lnk_bridge (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 *nm_platform_link_get_lnk_gretap (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); const NMPlatformLnkIp6Tnl *nm_platform_link_get_lnk_ip6tnl (NMPlatform *self, int ifindex, const NMPlatformLink **out_link); @@ -1941,6 +1952,7 @@ gboolean nm_platform_tfilter_sync (NMPlatform *self, GPtrArray *known_tfilters); const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len); +const char *nm_platform_lnk_bridge_to_string (const NMPlatformLnkBridge *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_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len); const char *nm_platform_lnk_ip6tnl_to_string (const NMPlatformLnkIp6Tnl *lnk, char *buf, gsize len); @@ -1974,6 +1986,7 @@ const char *nm_platform_wireguard_peer_to_string (const struct _NMPWireGuardPeer gsize len); int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b); +int nm_platform_lnk_bridge_cmp (const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b); int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b); int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b); int nm_platform_lnk_ip6tnl_cmp (const NMPlatformLnkIp6Tnl *a, const NMPlatformLnkIp6Tnl *b); @@ -2031,6 +2044,7 @@ void nm_platform_ip6_address_hash_update (const NMPlatformIP6Address *obj, NMHas void nm_platform_ip4_route_hash_update (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h); void nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpType cmp_type, NMHashState *h); void nm_platform_routing_rule_hash_update (const NMPlatformRoutingRule *obj, NMPlatformRoutingRuleCmpType cmp_type, NMHashState *h); +void nm_platform_lnk_bridge_hash_update (const NMPlatformLnkBridge *obj, NMHashState *h); void nm_platform_lnk_gre_hash_update (const NMPlatformLnkGre *obj, NMHashState *h); void nm_platform_lnk_infiniband_hash_update (const NMPlatformLnkInfiniband *obj, NMHashState *h); void nm_platform_lnk_ip6tnl_hash_update (const NMPlatformLnkIp6Tnl *obj, NMHashState *h); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 2bc7bf6f66..80b522da61 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -3210,6 +3210,17 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = { .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_tfilter_hash_update, .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_tfilter_cmp, }, + [NMP_OBJECT_TYPE_LNK_BRIDGE - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), + .obj_type = NMP_OBJECT_TYPE_LNK_BRIDGE, + .sizeof_data = sizeof (NMPObjectLnkBridge), + .sizeof_public = sizeof (NMPlatformLnkBridge), + .obj_type_name = "bridge", + .lnk_link_type = NM_LINK_TYPE_BRIDGE, + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_bridge_to_string, + .cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_bridge_hash_update, + .cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_bridge_cmp, + }, [NMP_OBJECT_TYPE_LNK_GRE - 1] = { .parent = DEDUP_MULTI_OBJ_CLASS_INIT (), .obj_type = NMP_OBJECT_TYPE_LNK_GRE, diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index bf4ff42379..6b37c16133 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -243,6 +243,10 @@ typedef struct { int wireguard_family_id; } NMPObjectLink; +typedef struct { + NMPlatformLnkBridge _public; +} NMPObjectLnkBridge; + typedef struct { NMPlatformLnkGre _public; } NMPObjectLnkGre; @@ -343,6 +347,9 @@ struct _NMPObject { NMPlatformLink link; NMPObjectLink _link; + NMPlatformLnkBridge lnk_bridge; + NMPObjectLnkBridge _lnk_bridge; + NMPlatformLnkGre lnk_gre; NMPObjectLnkGre _lnk_gre; @@ -487,6 +494,7 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type) case NMP_OBJECT_TYPE_TFILTER: + case NMP_OBJECT_TYPE_LNK_BRIDGE: case NMP_OBJECT_TYPE_LNK_GRE: case NMP_OBJECT_TYPE_LNK_GRETAP: case NMP_OBJECT_TYPE_LNK_INFINIBAND: diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 9f6a29bc99..13e93e7c92 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1172,6 +1172,42 @@ nmtstp_ip6_address_del (NMPlatform *platform, } \ } G_STMT_END +const NMPlatformLink * +nmtstp_link_bridge_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkBridge *lnk, + gboolean *out_not_supported) +{ + const NMPlatformLink *pllink = NULL; + int r = 0; + + g_assert (nm_utils_ifname_valid_kernel (name, NULL)); + + NM_SET_OUT (out_not_supported, FALSE); + external_command = nmtstp_run_command_check_external (external_command); + + _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", + name, + lnk->forward_delay, + lnk->hello_time, + lnk->max_age, + lnk->ageing_time); + g_assert_cmpint (r, ==, 0); + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_BRIDGE, 100); + } + + if (!pllink) { + r = nm_platform_link_bridge_add (platform, name, NULL, 0, lnk, &pllink); + } + + _assert_pllink (platform, r == 0, pllink, name, NM_LINK_TYPE_BRIDGE); + + return pllink; +} const NMPlatformLink * nmtstp_link_veth_add (NMPlatform *platform, gboolean external_command, diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index 522c3756d3..38083ae9ea 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -323,6 +323,11 @@ void nmtstp_link_set_updown (NMPlatform *platform, int ifindex, gboolean up); +const NMPlatformLink *nmtstp_link_bridge_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const NMPlatformLnkBridge *lnk, + gboolean *out_not_supported); const NMPlatformLink *nmtstp_link_veth_add (NMPlatform *platform, gboolean external_command, const char *name, diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index d7285c836a..6ce025e878 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -95,7 +95,12 @@ software_add (NMLinkType link_type, const char *name) case NM_LINK_TYPE_DUMMY: return NMTST_NM_ERR_SUCCESS (nm_platform_link_dummy_add (NM_PLATFORM_GET, name, NULL)); case NM_LINK_TYPE_BRIDGE: - return NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, name, NULL, 0, NULL)); + return NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, + name, + NULL, + 0, + &nm_platform_lnk_bridge_default, + NULL)); case NM_LINK_TYPE_BOND: { gboolean bond0_exists = !!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "bond0"); @@ -116,7 +121,12 @@ software_add (NMLinkType link_type, const char *name) /* Don't call link_callback for the bridge interface */ parent_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, PARENT_NAME); - if (NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, PARENT_NAME, NULL, 0, NULL))) + if (NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, + PARENT_NAME, + NULL, + 0, + &nm_platform_lnk_bridge_default, + NULL))) accept_signal (parent_added); free_signal (parent_added); @@ -510,7 +520,12 @@ test_bridge_addr (void) nm_utils_hwaddr_aton ("de:ad:be:ef:00:11", addr, sizeof (addr)); - g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, DEVICE_NAME, addr, sizeof (addr), &plink))); + g_assert (NMTST_NM_ERR_SUCCESS (nm_platform_link_bridge_add (NM_PLATFORM_GET, + DEVICE_NAME, + addr, + sizeof (addr), + &nm_platform_lnk_bridge_default, + &plink))); g_assert (plink); link = *plink; g_assert_cmpstr (link.name, ==, DEVICE_NAME); @@ -946,6 +961,24 @@ test_software_detect (gconstpointer user_data) ifindex_parent = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, PARENT_NAME, NM_LINK_TYPE_DUMMY, 100)->ifindex; switch (test_data->link_type) { + case NM_LINK_TYPE_BRIDGE: { + 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; + + if (!nmtstp_link_bridge_add (NULL, ext, DEVICE_NAME, &lnk_bridge, ¬_supported)) { + if (not_supported) { + g_test_skip ("Cannot create Bridge interface because of missing kernel support"); + goto out_delete_parent; + } + g_error ("Failed adding Bridge interface"); + } + break; + } case NM_LINK_TYPE_GRE: { gboolean gracefully_skip = FALSE; @@ -1311,6 +1344,16 @@ test_software_detect (gconstpointer user_data) g_assert (lnk); switch (test_data->link_type) { + case NM_LINK_TYPE_BRIDGE: { + 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); + break; + } case NM_LINK_TYPE_GRE: { const NMPlatformLnkGre *plnk = &lnk->lnk_gre; @@ -3352,6 +3395,7 @@ _nmtstp_setup_tests (void) if (nmtstp_is_root_test ()) { 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/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);