[PATCH net-next] net: bridge: cfm: notify userspace on CFM config changes
flat view
WARM2d
From: Abdul Wasey <hidden>
Date: 2026-10-04 04:13:28
Also in:
bridge, lkml
Subsystem:
ethernet bridge, networking [general], the rest · Maintainers:
Nikolay Aleksandrov, Ido Schimmel, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
CFM status changes are sent to userspace by br_cfm_notify(), but config changes are not. br_afspec() calls br_cfm_parse() without the "changed" pointer, so creating a MEP, adding a peer or starting CCM transmission never sends an RTM_NEWLINK. Today the only way to see these changes is to poll RTM_GETLINK with RTEXT_FILTER_CFM_CONFIG. Send one RTM_NEWLINK with RTEXT_FILTER_CFM_CONFIG from br_cfm_parse() once any group in the request has been applied. If a later group in the same request fails, still send it, since the earlier groups already changed the config. br_ifinfo_notify() is not used because it asks for RTEXT_FILTER_BRVLAN_COMPRESSED, so the message would not carry the CFM attributes. This calls br_info_notify() the same way br_cfm_notify() does for status. Signed-off-by: Abdul Wasey <redacted> --- net/bridge/br_cfm_netlink.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/net/bridge/br_cfm_netlink.c b/net/bridge/br_cfm_netlink.c
index 91b9922dc..56309e6f4 100644
--- a/net/bridge/br_cfm_netlink.c
+++ b/net/bridge/br_cfm_netlink.c@@ -382,6 +382,7 @@ int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p, struct nlattr *attr, int cmd, struct netlink_ext_ack *extack) { struct nlattr *tb[IFLA_BRIDGE_CFM_MAX + 1]; + bool changed = false; int err; /* When this function is called for a port then the br pointer is
@@ -399,59 +400,72 @@ int br_cfm_parse(struct net_bridge *br, struct net_bridge_port *p, err = br_mep_create_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CREATE], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_MEP_DELETE]) { err = br_mep_delete_parse(br, tb[IFLA_BRIDGE_CFM_MEP_DELETE], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_MEP_CONFIG]) { err = br_mep_config_parse(br, tb[IFLA_BRIDGE_CFM_MEP_CONFIG], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_CC_CONFIG]) { err = br_cc_config_parse(br, tb[IFLA_BRIDGE_CFM_CC_CONFIG], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD]) { err = br_cc_peer_mep_add_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE]) { err = br_cc_peer_mep_remove_parse(br, tb[IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_CC_RDI]) { err = br_cc_rdi_parse(br, tb[IFLA_BRIDGE_CFM_CC_RDI], extack); if (err) - return err; + goto out; + changed = true; } if (tb[IFLA_BRIDGE_CFM_CC_CCM_TX]) { err = br_cc_ccm_tx_parse(br, tb[IFLA_BRIDGE_CFM_CC_CCM_TX], extack); if (err) - return err; + goto out; + changed = true; } - return 0; +out: + /* Earlier groups may have been applied even if a later one failed */ + if (changed) + br_info_notify(RTM_NEWLINK, br, NULL, RTEXT_FILTER_CFM_CONFIG); + + return err; } int br_cfm_config_fill_info(struct sk_buff *skb, struct net_bridge *br)
--
2.53.0