parent
9e619dc366
commit
3ad63e35f8
@ -0,0 +1,270 @@
|
||||
From 8f8845484ee74b1934cbd5f0cca997ba0504d543 Mon Sep 17 00:00:00 2001
|
||||
From: Gris Ge <fge@redhat.com>
|
||||
Date: Thu, 8 Feb 2024 23:36:34 +0800
|
||||
Subject: [PATCH] bridge: skip VLAN filtering resetting in reapply if no vlan
|
||||
change changed
|
||||
|
||||
When doing reapply on linux bridge interface, NetworkManager will reset
|
||||
the VLAN filtering and default PVID which cause PVID been readded to all
|
||||
bridge ports regardless they are managed by NetworkManager.
|
||||
|
||||
This is because Linux kernel will re-add PVID to bridge port upon the
|
||||
changes of bridge default-pvid value.
|
||||
|
||||
To fix the issue, this patch introduce netlink parsing code for
|
||||
`vlan_filtering` and `default_pvid` of NMPlatformLnkBridge, and use that
|
||||
to compare desired VLAN filtering settings, skip the reset of VLAN
|
||||
filter if `default_pvid` and `vlan_filtering` are unchanged.
|
||||
|
||||
Signed-off-by: Gris Ge <fge@redhat.com>
|
||||
(cherry picked from commit 02c34d538c6a2b22bd09318496ba104eb43246b4)
|
||||
(cherry picked from commit f990f9b4e4ffb5195fc89c4a8c6f251c0e01b501)
|
||||
(cherry picked from commit c448e225198f7f8851fc01a8394529e7cbe25d4d)
|
||||
---
|
||||
src/core/devices/nm-device-bridge.c | 79 +++++++++++++++++---------
|
||||
src/core/platform/tests/test-link.c | 2 +
|
||||
src/libnm-platform/nm-linux-platform.c | 6 ++
|
||||
src/libnm-platform/nm-platform.c | 13 ++++-
|
||||
src/libnm-platform/nm-platform.h | 2 +
|
||||
5 files changed, 72 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c
|
||||
index 9a45dbf3fc..73effc50b4 100644
|
||||
--- a/src/core/devices/nm-device-bridge.c
|
||||
+++ b/src/core/devices/nm-device-bridge.c
|
||||
@@ -712,7 +712,27 @@ master_update_slave_connection(NMDevice *device,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
-bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge)
|
||||
+is_bridge_pvid_changed(NMDevice *device, NMSettingBridge *s_bridge)
|
||||
+{
|
||||
+ int ifindex = nm_device_get_ifindex(device);
|
||||
+ const NMPlatformLnkBridge *nmp_link_br;
|
||||
+ NMPlatform *platform = nm_device_get_platform(device);
|
||||
+ bool desired_vlan_filtering = nm_setting_bridge_get_vlan_filtering(s_bridge);
|
||||
+ guint16 desired_pvid = nm_setting_bridge_get_vlan_default_pvid(s_bridge);
|
||||
+
|
||||
+ nm_platform_link_refresh(platform, ifindex);
|
||||
+ nmp_link_br = nm_platform_link_get_lnk_bridge(platform, ifindex, NULL);
|
||||
+
|
||||
+ if (nmp_link_br) {
|
||||
+ return desired_vlan_filtering != nmp_link_br->vlan_filtering
|
||||
+ || desired_pvid != nmp_link_br->default_pvid;
|
||||
+ } else {
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge, gboolean is_reapply)
|
||||
{
|
||||
NMDeviceBridge *self = NM_DEVICE_BRIDGE(device);
|
||||
gconstpointer hwaddr;
|
||||
@@ -753,31 +773,37 @@ bridge_set_vlan_options(NMDevice *device, NMSettingBridge *s_bridge)
|
||||
|
||||
self->vlan_configured = TRUE;
|
||||
|
||||
- /* Filtering must be disabled to change the default PVID.
|
||||
- * Clear the default PVID so that we later can force the re-creation of
|
||||
- * default PVID VLANs by writing the option again. */
|
||||
-
|
||||
- nm_platform_link_set_bridge_info(
|
||||
- plat,
|
||||
- ifindex,
|
||||
- &((NMPlatformLinkSetBridgeInfoData){.vlan_filtering_has = TRUE,
|
||||
- .vlan_filtering_val = FALSE,
|
||||
- .vlan_default_pvid_has = TRUE,
|
||||
- .vlan_default_pvid_val = 0}));
|
||||
+ if (!is_reapply || is_bridge_pvid_changed(device, s_bridge)) {
|
||||
+ /* Filtering must be disabled to change the default PVID.
|
||||
+ * Clear the default PVID so that we later can force the re-creation of
|
||||
+ * default PVID VLANs by writing the option again. */
|
||||
|
||||
- /* Clear all existing VLANs */
|
||||
- if (!nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, NULL))
|
||||
- return FALSE;
|
||||
+ if (is_reapply) {
|
||||
+ _LOGD(LOGD_BRIDGE, "default_pvid is changed, resetting bridge VLAN filtering");
|
||||
+ }
|
||||
|
||||
- /* Now set the default PVID. After this point the kernel creates
|
||||
- * a PVID VLAN on each port, including the bridge itself. */
|
||||
- pvid = nm_setting_bridge_get_vlan_default_pvid(s_bridge);
|
||||
- if (pvid) {
|
||||
nm_platform_link_set_bridge_info(
|
||||
plat,
|
||||
ifindex,
|
||||
- &((NMPlatformLinkSetBridgeInfoData){.vlan_default_pvid_has = TRUE,
|
||||
- .vlan_default_pvid_val = pvid}));
|
||||
+ &((NMPlatformLinkSetBridgeInfoData){.vlan_filtering_has = TRUE,
|
||||
+ .vlan_filtering_val = FALSE,
|
||||
+ .vlan_default_pvid_has = TRUE,
|
||||
+ .vlan_default_pvid_val = 0}));
|
||||
+
|
||||
+ /* Clear all existing VLANs */
|
||||
+ if (!nm_platform_link_set_bridge_vlans(plat, ifindex, FALSE, NULL))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /* Now set the default PVID. After this point the kernel creates
|
||||
+ * a PVID VLAN on each port, including the bridge itself. */
|
||||
+ pvid = nm_setting_bridge_get_vlan_default_pvid(s_bridge);
|
||||
+ if (pvid) {
|
||||
+ nm_platform_link_set_bridge_info(
|
||||
+ plat,
|
||||
+ ifindex,
|
||||
+ &((NMPlatformLinkSetBridgeInfoData){.vlan_default_pvid_has = TRUE,
|
||||
+ .vlan_default_pvid_val = pvid}));
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Create VLANs only after setting the default PVID, so that
|
||||
@@ -836,7 +862,7 @@ _platform_lnk_bridge_init_from_setting(NMSettingBridge *s_bridge, NMPlatformLnkB
|
||||
}
|
||||
|
||||
static gboolean
|
||||
-link_config(NMDevice *device, NMConnection *connection)
|
||||
+link_config(NMDevice *device, NMConnection *connection, gboolean is_reapply)
|
||||
{
|
||||
int ifindex = nm_device_get_ifindex(device);
|
||||
NMSettingBridge *s_bridge;
|
||||
@@ -850,7 +876,7 @@ link_config(NMDevice *device, NMConnection *connection)
|
||||
if (nm_platform_link_bridge_change(nm_device_get_platform(device), ifindex, &props) < 0)
|
||||
return FALSE;
|
||||
|
||||
- return bridge_set_vlan_options(device, s_bridge);
|
||||
+ return bridge_set_vlan_options(device, s_bridge, is_reapply);
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
@@ -861,7 +887,7 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
|
||||
connection = nm_device_get_applied_connection(device);
|
||||
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
|
||||
|
||||
- if (!link_config(device, connection)) {
|
||||
+ if (!link_config(device, connection, FALSE)) {
|
||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||
}
|
||||
@@ -1003,7 +1029,7 @@ attach_port(NMDevice *device,
|
||||
s_port = nm_connection_get_setting_bridge_port(connection);
|
||||
|
||||
if (!nm_device_sys_iface_state_is_external(device))
|
||||
- bridge_set_vlan_options(device, s_bridge);
|
||||
+ bridge_set_vlan_options(device, s_bridge, FALSE);
|
||||
|
||||
if (nm_setting_bridge_get_vlan_filtering(s_bridge)) {
|
||||
gs_free const NMPlatformBridgeVlan **plat_vlans = NULL;
|
||||
@@ -1218,8 +1244,7 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
|
||||
/* Make sure bridge_set_vlan_options() called by link_config()
|
||||
* sets vlan_filtering and default_pvid anew. */
|
||||
self->vlan_configured = FALSE;
|
||||
-
|
||||
- link_config(device, con_new);
|
||||
+ link_config(device, con_new, TRUE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c
|
||||
index 8a54ac4853..fdece007bc 100644
|
||||
--- a/src/core/platform/tests/test-link.c
|
||||
+++ b/src/core/platform/tests/test-link.c
|
||||
@@ -1403,6 +1403,8 @@ test_software_detect(gconstpointer user_data)
|
||||
lnk_bridge.mcast_query_interval = 12000;
|
||||
lnk_bridge.mcast_query_response_interval = 5200;
|
||||
lnk_bridge.mcast_startup_query_interval = 3000;
|
||||
+ lnk_bridge.vlan_filtering = FALSE;
|
||||
+ lnk_bridge.default_pvid = 1;
|
||||
|
||||
if (!nmtstp_link_bridge_add(NULL, ext, DEVICE_NAME, &lnk_bridge))
|
||||
g_error("Failed adding Bridge interface");
|
||||
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
|
||||
index 99eab9c784..9b4ac14024 100644
|
||||
--- a/src/libnm-platform/nm-linux-platform.c
|
||||
+++ b/src/libnm-platform/nm-linux-platform.c
|
||||
@@ -1515,6 +1515,8 @@ _parse_lnk_bridge(const char *kind, struct nlattr *info_data)
|
||||
[IFLA_BR_MCAST_QUERY_INTVL] = {.type = NLA_U64},
|
||||
[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = {.type = NLA_U64},
|
||||
[IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = {.type = NLA_U64},
|
||||
+ [IFLA_BR_VLAN_FILTERING] = {.type = NLA_U8},
|
||||
+ [IFLA_BR_VLAN_DEFAULT_PVID] = {.type = NLA_U16},
|
||||
};
|
||||
NMPlatformLnkBridge *props;
|
||||
struct nlattr *tb[G_N_ELEMENTS(policy)];
|
||||
@@ -1585,6 +1587,10 @@ _parse_lnk_bridge(const char *kind, struct nlattr *info_data)
|
||||
props->mcast_query_response_interval = nla_get_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]);
|
||||
if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])
|
||||
props->mcast_startup_query_interval = nla_get_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]);
|
||||
+ if (tb[IFLA_BR_VLAN_FILTERING])
|
||||
+ props->vlan_filtering = !!nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
|
||||
+ if (tb[IFLA_BR_VLAN_DEFAULT_PVID])
|
||||
+ props->default_pvid = nla_get_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]);
|
||||
|
||||
return obj;
|
||||
}
|
||||
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
|
||||
index 041354cf44..3b61375bad 100644
|
||||
--- a/src/libnm-platform/nm-platform.c
|
||||
+++ b/src/libnm-platform/nm-platform.c
|
||||
@@ -6086,7 +6086,8 @@ nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsiz
|
||||
" 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 "",
|
||||
+ " mcast_startup_query_interval %" G_GUINT64_FORMAT " vlan_filtering %d"
|
||||
+ " default_pvid %" G_GUINT16_FORMAT "",
|
||||
lnk->forward_delay,
|
||||
lnk->hello_time,
|
||||
lnk->max_age,
|
||||
@@ -6109,7 +6110,9 @@ nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsiz
|
||||
lnk->mcast_querier_interval,
|
||||
lnk->mcast_query_interval,
|
||||
lnk->mcast_query_response_interval,
|
||||
- lnk->mcast_startup_query_interval);
|
||||
+ lnk->mcast_startup_query_interval,
|
||||
+ lnk->vlan_filtering,
|
||||
+ lnk->default_pvid);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -7978,12 +7981,14 @@ nm_platform_lnk_bridge_hash_update(const NMPlatformLnkBridge *obj, NMHashState *
|
||||
obj->mcast_router,
|
||||
obj->mcast_query_response_interval,
|
||||
obj->mcast_startup_query_interval,
|
||||
+ obj->default_pvid,
|
||||
NM_HASH_COMBINE_BOOLS(guint8,
|
||||
obj->stp_state,
|
||||
obj->mcast_querier,
|
||||
obj->mcast_query_use_ifaddr,
|
||||
obj->mcast_snooping,
|
||||
- obj->vlan_stats_enabled));
|
||||
+ obj->vlan_stats_enabled,
|
||||
+ obj->vlan_filtering));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -8124,6 +8129,8 @@ nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBrid
|
||||
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_interval);
|
||||
+ NM_CMP_FIELD_BOOL(a, b, vlan_filtering);
|
||||
+ NM_CMP_FIELD(a, b, default_pvid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
|
||||
index aeea5c42db..a4410b0a7c 100644
|
||||
--- a/src/libnm-platform/nm-platform.h
|
||||
+++ b/src/libnm-platform/nm-platform.h
|
||||
@@ -765,6 +765,8 @@ typedef struct {
|
||||
bool mcast_snooping : 1;
|
||||
bool stp_state : 1;
|
||||
bool vlan_stats_enabled : 1;
|
||||
+ bool vlan_filtering;
|
||||
+ guint16 default_pvid;
|
||||
} _nm_alignas(NMPlatformObject) NMPlatformLnkBridge;
|
||||
|
||||
extern const NMPlatformLnkBridge nm_platform_lnk_bridge_default;
|
||||
--
|
||||
2.43.0
|
||||
|
Loading…
Reference in new issue