br_cfm_cc_config_set() enables existing peers before storing the new
CC configuration. The receive timer therefore starts with the previous
expected interval, delaying CCM loss detection when enabling CC with a
shorter interval. For example, disabling CC at 1s and re-enabling it at
100ms schedules the first check after 250ms instead of 25ms, before
rounding to jiffies.

Save the disabled-to-enabled transition and store the new configuration
before enabling peers. Keep cancellation on disable before replacing
the configuration.

Fixes: dc32cbb3dbd7 ("bridge: cfm: Kernel space implementation of CFM. CCM 
frame RX added.")
Signed-off-by: Baek Kyu, Kim <[email protected]>
---
On the combined v2 kernel under ARM64 QEMU/KVM, all 8 CC interval and
transition checks passed with bridge/veth and netlink configuration.

 net/bridge/br_cfm.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/net/bridge/br_cfm.c b/net/bridge/br_cfm.c
index 9dcc97d63a6f..28b40dbf4073 100644
--- a/net/bridge/br_cfm.c
+++ b/net/bridge/br_cfm.c
@@ -634,6 +634,7 @@ int br_cfm_cc_config_set(struct net_bridge *br,
 {
        struct br_cfm_peer_mep *peer_mep;
        struct br_cfm_mep *mep;
+       bool enable;
 
        ASSERT_RTNL();
 
@@ -648,17 +649,20 @@ int br_cfm_cc_config_set(struct net_bridge *br,
        if (memcmp(config, &mep->cc_config, sizeof(*config)) == 0)
                return 0;
 
-       if (config->enable && !mep->cc_config.enable)
-               /* CC is enabled */
-               hlist_for_each_entry(peer_mep, &mep->peer_mep_list, head)
-                       cc_peer_enable(peer_mep);
-
        if (!config->enable && mep->cc_config.enable)
                /* CC is disabled */
                hlist_for_each_entry(peer_mep, &mep->peer_mep_list, head)
                        cc_peer_disable(peer_mep);
 
+       enable = config->enable && !mep->cc_config.enable;
+
        mep->cc_config = *config;
+
+       if (enable)
+               /* CC is enabled */
+               hlist_for_each_entry(peer_mep, &mep->peer_mep_list, head)
+                       cc_peer_enable(peer_mep);
+
        mep->ccm_rx_snumber = 0;
        mep->ccm_tx_snumber = 1;
 
-- 
2.55.0


Reply via email to