Repository: telstra/open-kilda
Issue: [Server42] disabling 'server42_flow_rtt' in feature toggle leads to excess rules on a switch with enabled 'server42_flow_rtt'

**Steps to reproduce:**

1. enable `server42_flow_rtt` in feature toggle and on a switch;
2. make sure the switch is valid;
3. disable the `server42_flow_rtt` feature toggle;

**Actual result:**
The switch has the excess server42 rules
```
"excess": [
            -9223372036854775783,
            -9223372036854775782,
            -9223372036854775781
        ],
        "excess-hex": [
            "8000000000000019",
            "800000000000001a",
            "800000000000001b"
        ],
```


**Expected result:**
The switch should be valid after disabling the 'server42_flow_rtt' feature toggle

Changed files:
src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesInstallRequest.java
src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/GetExpectedDefaultRulesRequest.java
src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/IFeatureTogglesCarrier.java
src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesDeleteRequest.java
src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/service/impl/SwitchRuleServiceImpl.java
src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/ISwitchManager.java
src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/fsm/SwitchValidateFsm.java
src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/FeatureTogglesBolt.java
src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FeatureTogglesService.java
src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/kafka/RecordHandler.java
src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/SwitchManager.java
src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/NbWorkerTopology.java

diff --git a/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/GetExpectedDefaultRulesRequest.java b/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/GetExpectedDefaultRulesRequest.java
index cb00cd99b..2cb382c6d 100644
--- a/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/GetExpectedDefaultRulesRequest.java
+++ b/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/GetExpectedDefaultRulesRequest.java
@@ -44,8 +44,11 @@ public class GetExpectedDefaultRulesRequest extends CommandData {
     @JsonProperty("switch_arp")
     private boolean switchArp;
 
-    @JsonProperty("server42_flow_rtt")
-    private boolean server42FlowRtt;
+    @JsonProperty("server42_flow_rtt_feature_toggle")
+    private boolean server42FlowRttFeatureToggle;
+
+    @JsonProperty("server42_flow_rtt_switch_property")
+    private boolean server42FlowRttSwitchProperty;
 
     @JsonProperty("server42_port")
     private Integer server42Port;
@@ -76,7 +79,10 @@ public class GetExpectedDefaultRulesRequest extends CommandData {
                                           @JsonProperty("multi_table") boolean multiTable,
                                           @JsonProperty("switch_lldp") boolean switchLldp,
                                           @JsonProperty("switch_arp") boolean switchArp,
-                                          @JsonProperty("server42_flow_rtt") boolean server42FlowRtt,
+                                          @JsonProperty("server42_flow_rtt_feature_toggle")
+                                                      boolean server42FlowRttFeatureToggle,
+                                          @JsonProperty("server42_flow_rtt_switch_property")
+                                                      boolean server42FlowRttSwitchProperty,
                                           @JsonProperty("server42_port") Integer server42Port,
                                           @JsonProperty("server42_vlan") Integer server42Vlan,
                                           @JsonProperty("server42_mac_address") MacAddress server42MacAddress,
@@ -90,7 +96,8 @@ public class GetExpectedDefaultRulesRequest extends CommandData {
         this.multiTable = multiTable;
         this.switchLldp = switchLldp;
         this.switchArp = switchArp;
-        this.server42FlowRtt = server42FlowRtt;
+        this.server42FlowRttFeatureToggle = server42FlowRttFeatureToggle;
+        this.server42FlowRttSwitchProperty = server42FlowRttSwitchProperty;
         this.server42Port = server42Port;
         this.server42Vlan = server42Vlan;
         this.server42MacAddress = server42MacAddress;
diff --git a/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesDeleteRequest.java b/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesDeleteRequest.java
index a4e544e2b..8dae46093 100644
--- a/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesDeleteRequest.java
+++ b/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesDeleteRequest.java
@@ -58,8 +58,11 @@ public class SwitchRulesDeleteRequest extends CommandData {
     @JsonProperty("switch_arp")
     private boolean switchArp = false;
 
-    @JsonProperty("server42_flow_rtt")
-    private boolean server42FlowRtt = false;
+    @JsonProperty("server42_flow_rtt_feature_toggle")
+    private boolean server42FlowRttFeatureToggle = false;
+
+    @JsonProperty("server42_flow_rtt_switch_property")
+    private boolean server42FlowRttSwitchProperty = false;
 
     @JsonProperty("server42_port")
     private Integer server42Port;
diff --git a/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesInstallRequest.java b/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesInstallRequest.java
index e89d8beab..7d23982d3 100644
--- a/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesInstallRequest.java
+++ b/src-java/floodlight-service/floodlight-api/src/main/java/org/openkilda/messaging/command/switches/SwitchRulesInstallRequest.java
@@ -52,8 +52,11 @@ public class SwitchRulesInstallRequest extends CommandData {
     @JsonProperty("switch_arp")
     private boolean switchArp = false;
 
-    @JsonProperty("server42_flow_rtt")
-    private boolean server42FlowRtt = false;
+    @JsonProperty("server42_flow_rtt_feature_toggle")
+    private boolean server42FlowRttFeatureToggle = false;
+
+    @JsonProperty("server42_flow_rtt_switch_property")
+    private boolean server42FlowRttSwitchProperty = false;
 
     @JsonProperty("server42_port")
     private Integer server42Port;
diff --git a/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/kafka/RecordHandler.java b/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/kafka/RecordHandler.java
index 95d04de40..02876d96b 100644
--- a/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/kafka/RecordHandler.java
+++ b/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/kafka/RecordHandler.java
@@ -756,18 +756,22 @@ class RecordHandler implements Runnable {
                 Integer server42Port = request.getServer42Port();
                 Integer server42Vlan = request.getServer42Vlan();
                 MacAddress server42MacAddress = request.getServer42MacAddress();
-                if (request.isServer42FlowRtt() && server42Port != null && server42Vlan != null
-                        && server42MacAddress != null) {
+
+                if (request.isServer42FlowRttFeatureToggle()) {
                     installedRules.add(
                             processInstallDefaultFlowByCookie(request.getSwitchId(), SERVER_42_TURNING_COOKIE));
-                    installedRules.add(switchManager.installServer42OutputVlanFlow(
-                            dpid, server42Port, server42Vlan, server42MacAddress));
-                    installedRules.add(switchManager.installServer42OutputVxlanFlow(
-                            dpid, server42Port, server42Vlan, server42MacAddress));
-
-                    for (Integer port : request.getServer42FlowRttPorts()) {
-                        installedRules.add(switchManager.installServer42InputFlow(
-                                dpid, server42Port, port, server42MacAddress));
+
+                    if (request.isServer42FlowRttSwitchProperty() && server42Port != null && server42Vlan != null
+                            && server42MacAddress != null) {
+                        installedRules.add(switchManager.installServer42OutputVlanFlow(
+                                dpid, server42Port, server42Vlan, server42MacAddress));
+                        installedRules.add(switchManager.installServer42OutputVxlanFlow(
+                                dpid, server42Port, server42Vlan, server42MacAddress));
+
+                        for (Integer port : request.getServer42FlowRttPorts()) {
+                            installedRules.add(switchManager.installServer42InputFlow(
+                                    dpid, server42Port, port, server42MacAddress));
+                        }
                     }
                 }
             }
@@ -951,7 +955,8 @@ class RecordHandler implements Runnable {
                     removedRules.addAll(switchManager.deleteDefaultRules(dpid, request.getIslPorts(),
                             request.getFlowPorts(), request.getFlowLldpPorts(), request.getFlowArpPorts(),
                             request.getServer42FlowRttPorts(), request.isMultiTable(), request.isSwitchLldp(),
-                            request.isSwitchArp(), request.isServer42FlowRtt()));
+                            request.isSwitchArp(),
+                            request.isServer42FlowRttFeatureToggle() && request.isServer42FlowRttSwitchProperty()));
                 }
             }
 
@@ -1008,16 +1013,19 @@ class RecordHandler implements Runnable {
                 Integer server42Port = request.getServer42Port();
                 Integer server42Vlan = request.getServer42Vlan();
                 MacAddress server42MacAddress = request.getServer42MacAddress();
-                if (request.isServer42FlowRtt() && server42Port != null && server42Vlan != null
-                        && server42MacAddress != null) {
+                if (request.isServer42FlowRttFeatureToggle()) {
                     switchManager.installServer42TurningFlow(dpid);
-                    switchManager.installServer42OutputVlanFlow(
-                            dpid, server42Port, server42Vlan, server42MacAddress);
-                    switchManager.installServer42OutputVxlanFlow(
-                            dpid, server42Port, server42Vlan, server42MacAddress);
 
-                    for (Integer port : request.getServer42FlowRttPorts()) {
-                        switchManager.installServer42InputFlow(dpid, server42Port, port, server42MacAddress);
+                    if (request.isServer42FlowRttSwitchProperty() && server42Port != null && server42Vlan != null
+                            && server42MacAddress != null) {
+                        switchManager.installServer42OutputVlanFlow(
+                                dpid, server42Port, server42Vlan, server42MacAddress);
+                        switchManager.installServer42OutputVxlanFlow(
+                                dpid, server42Port, server42Vlan, server42MacAddress);
+
+                        for (Integer port : request.getServer42FlowRttPorts()) {
+                            switchManager.installServer42InputFlow(dpid, server42Port, port, server42MacAddress);
+                        }
                     }
                 }
             }
@@ -1073,7 +1081,8 @@ class RecordHandler implements Runnable {
         boolean multiTable = request.isMultiTable();
         boolean switchLldp = request.isSwitchLldp();
         boolean switchArp = request.isSwitchArp();
-        boolean server42FlowRtt = request.isServer42FlowRtt();
+        boolean server42FlowRttFeatureToggle = request.isServer42FlowRttFeatureToggle();
+        boolean server42FlowRttSwitchProperty = request.isServer42FlowRttSwitchProperty();
         Integer server42Port = request.getServer42Port();
         Integer server42Vlan = request.getServer42Vlan();
         MacAddress server42MacAddress = request.getServer42MacAddress();
@@ -1103,11 +1112,9 @@ class RecordHandler implements Runnable {
                     defaultRules.add(context.getSwitchManager().buildArpInputCustomerFlow(dpid, port));
                 }
             }
-            if (server42FlowRtt) {
-                defaultRules.addAll(context.getSwitchManager()
-                        .buildExpectedServer42Flows(dpid, server42Port, server42Vlan, server42MacAddress,
-                                server42FlowRttPorts));
-            }
+            defaultRules.addAll(context.getSwitchManager()
+                    .buildExpectedServer42Flows(dpid, server42FlowRttFeatureToggle, server42FlowRttSwitchProperty,
+                            server42Port, server42Vlan, server42MacAddress, server42FlowRttPorts));
 
             List<FlowEntry> flows = defaultRules.stream()
                     .map(OfFlowStatsMapper.INSTANCE::toFlowEntry)
diff --git a/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/ISwitchManager.java b/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/ISwitchManager.java
index f2b9e05ef..5e9b2283c 100644
--- a/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/ISwitchManager.java
+++ b/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/ISwitchManager.java
@@ -424,15 +424,18 @@ public interface ISwitchManager extends IFloodlightService {
      * Build all expected Server 42 rules.
      *
      * @param dpid switch id
-     * @param server42Port server 42 port
-     * @param server42Vlan vlan of packer received from server 42
-     * @param server42MacAddress mac address of server 42
+     * @param server42FlowRttFeatureToggle server 42 feature toggle
+     * @param server42FlowRttSwitchProperty server 42 switch property
+     * @param server42Port server 42 port. Could be null if server42FlowRttSwitchProperty is false
+     * @param server42Vlan vlan of packer received from server 42.
+     *                     Could be null if server42FlowRttSwitchProperty is false
+     * @param server42MacAddress mac address of server 42. Could be null if server42FlowRttSwitchProperty is false
      * @param customerPorts switch ports with enabled server 42 ping
      * @return modification command
      */
     List<OFFlowMod> buildExpectedServer42Flows(
-            DatapathId dpid, int server42Port, int server42Vlan, MacAddress server42MacAddress,
-            Set<Integer> customerPorts)
+            DatapathId dpid, boolean server42FlowRttFeatureToggle, boolean server42FlowRttSwitchProperty,
+            Integer server42Port, Integer server42Vlan, MacAddress server42MacAddress, Set<Integer> customerPorts)
             throws SwitchNotFoundException;
 
     /**
diff --git a/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/SwitchManager.java b/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/SwitchManager.java
index 52dc453a6..83f9251f3 100644
--- a/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/SwitchManager.java
+++ b/src-java/floodlight-service/floodlight-modules/src/main/java/org/openkilda/floodlight/switchmanager/SwitchManager.java
@@ -1773,18 +1773,25 @@ public class SwitchManager implements IFloodlightModule, IFloodlightService, ISw
 
     @Override
     public List<OFFlowMod> buildExpectedServer42Flows(
-            DatapathId dpid, int server42Port, int server42Vlan, org.openkilda.model.MacAddress server42MacAddress,
+            DatapathId dpid, boolean server42FlowRttFeatureToggle, boolean server42FlowRttSwitchProperty,
+            Integer server42Port, Integer server42Vlan, org.openkilda.model.MacAddress server42MacAddress,
             Set<Integer> customerPorts) throws SwitchNotFoundException {
 
         List<SwitchFlowGenerator> generators = new ArrayList<>();
-        for (Integer port : customerPorts) {
-            generators.add(switchFlowFactory.getServer42InputFlowGenerator(server42Port, port, server42MacAddress));
-        }
-        generators.add(switchFlowFactory.getServer42TurningFlowGenerator());
-        generators.add(switchFlowFactory.getServer42OutputVlanFlowGenerator(
-                server42Port, server42Vlan, server42MacAddress));
-        generators.add(switchFlowFactory.getServer42OutputVxlanFlowGenerator(
-                server42Port, server42Vlan, server42MacAddress));
+        if (server42FlowRttFeatureToggle) {
+            generators.add(switchFlowFactory.getServer42TurningFlowGenerator());
+
+            if (server42FlowRttSwitchProperty) {
+                for (Integer port : customerPorts) {
+                    generators.add(switchFlowFactory.getServer42InputFlowGenerator(
+                            server42Port, port, server42MacAddress));
+                }
+                generators.add(switchFlowFactory.getServer42OutputVlanFlowGenerator(
+                        server42Port, server42Vlan, server42MacAddress));
+                generators.add(switchFlowFactory.getServer42OutputVxlanFlowGenerator(
+                        server42Port, server42Vlan, server42MacAddress));
+            }
+        }
 
         IOFSwitch sw = lookupSwitch(dpid);
         return generators.stream()
diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/NbWorkerTopology.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/NbWorkerTopology.java
index 5424742ad..0ef489304 100644
--- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/NbWorkerTopology.java
+++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/NbWorkerTopology.java
@@ -229,6 +229,7 @@ public class NbWorkerTopology extends AbstractTopology<NbWorkerTopologyConfig> {
                 .shuffleGrouping(SWITCHES_BOLT_NAME, StreamType.TO_SWITCH_MANAGER.toString())
                 .shuffleGrouping(ROUTER_BOLT_NAME, StreamType.ERROR.toString())
                 .shuffleGrouping(FEATURE_TOGGLES_BOLT_NAME, StreamType.ERROR.toString())
+                .shuffleGrouping(FEATURE_TOGGLES_BOLT_NAME, StreamType.TO_SWITCH_MANAGER.toString())
                 .shuffleGrouping(KILDA_CONFIG_BOLT_NAME, StreamType.ERROR.toString())
                 .shuffleGrouping(PATHS_BOLT_NAME, StreamType.ERROR.toString())
                 .shuffleGrouping(HISTORY_BOLT_NAME, StreamType.ERROR.toString())
diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/FeatureTogglesBolt.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/FeatureTogglesBolt.java
index b52692701..7ef7152b8 100644
--- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/FeatureTogglesBolt.java
+++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/bolts/FeatureTogglesBolt.java
@@ -15,6 +15,7 @@
 
 package org.openkilda.wfm.topology.nbworker.bolts;
 
+import org.openkilda.messaging.command.switches.SwitchValidateRequest;
 import org.openkilda.messaging.error.ErrorType;
 import org.openkilda.messaging.error.MessageException;
 import org.openkilda.messaging.info.InfoData;
@@ -25,9 +26,11 @@ import org.openkilda.messaging.nbtopology.request.CreateOrUpdateFeatureTogglesRe
 import org.openkilda.messaging.nbtopology.request.GetFeatureTogglesRequest;
 import org.openkilda.messaging.nbtopology.response.FeatureTogglesResponse;
 import org.openkilda.model.FeatureToggles;
+import org.openkilda.model.SwitchId;
 import org.openkilda.persistence.PersistenceManager;
 import org.openkilda.wfm.error.FeatureTogglesNotFoundException;
 import org.openkilda.wfm.share.mappers.FeatureTogglesMapper;
+import org.openkilda.wfm.share.utils.KeyProvider;
 import org.openkilda.wfm.topology.nbworker.StreamType;
 import org.openkilda.wfm.topology.nbworker.services.FeatureTogglesService;
 import org.openkilda.wfm.topology.nbworker.services.IFeatureTogglesCarrier;
@@ -94,6 +97,18 @@ public class FeatureTogglesBolt extends PersistenceOperationsBolt implements IFe
         emit(STREAM_NOTIFICATION_ID, getCurrentTuple(), makeNotificationTuple(payload));
     }
 
+    @Override
+    public void requestSwitchSync(SwitchId switchId) {
+        SwitchValidateRequest data = SwitchValidateRequest.builder()
+                .switchId(switchId)
+                .performSync(true)
+                .processMeters(true)
+                .removeExcess(true)
+                .build();
+        getOutput().emit(StreamType.TO_SWITCH_MANAGER.toString(), getCurrentTuple(),
+                new Values(data, KeyProvider.generateChainedKey(getCorrelationId())));
+    }
+
     // -- private --
 
     private Values makeNotificationTuple(InfoData payload) {
@@ -106,5 +121,7 @@ public class FeatureTogglesBolt extends PersistenceOperationsBolt implements IFe
     public void declareOutputFields(OutputFieldsDeclarer declarer) {
         super.declareOutputFields(declarer);
         declarer.declareStream(STREAM_NOTIFICATION_ID, STREAM_NOTIFICATION_FIELDS);
+        declarer.declareStream(StreamType.TO_SWITCH_MANAGER.toString(),
+                new Fields(MessageEncoder.FIELD_ID_PAYLOAD, MessageEncoder.FIELD_ID_CONTEXT));
     }
 }
diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FeatureTogglesService.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FeatureTogglesService.java
index 764f9fc90..d2d856ca2 100644
--- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FeatureTogglesService.java
+++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/FeatureTogglesService.java
@@ -17,13 +17,16 @@ package org.openkilda.wfm.topology.nbworker.services;
 
 import org.openkilda.model.FeatureToggles;
 import org.openkilda.model.FeatureToggles.FeatureTogglesCloner;
+import org.openkilda.model.Switch;
 import org.openkilda.persistence.repositories.FeatureTogglesRepository;
 import org.openkilda.persistence.repositories.RepositoryFactory;
+import org.openkilda.persistence.repositories.SwitchRepository;
 import org.openkilda.persistence.tx.TransactionManager;
 import org.openkilda.wfm.error.FeatureTogglesNotFoundException;
 
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.Collection;
 import java.util.Optional;
 
 @Slf4j
@@ -31,12 +34,14 @@ public class FeatureTogglesService {
     private final IFeatureTogglesCarrier carrier;
 
     private FeatureTogglesRepository featureTogglesRepository;
+    private SwitchRepository switchRepository;
     private TransactionManager transactionManager;
 
     public FeatureTogglesService(IFeatureTogglesCarrier carrier, RepositoryFactory repositoryFactory,
                                  TransactionManager transactionManager) {
         this.carrier = carrier;
         this.featureTogglesRepository = repositoryFactory.createFeatureTogglesRepository();
+        this.switchRepository = repositoryFactory.createSwitchRepository();
         this.transactionManager = transactionManager;
     }
 
@@ -71,6 +76,15 @@ public class FeatureTogglesService {
         if (!before.equals(after)) {
             log.info("Emit feature-toggles update notification - toggles:{}", after);
             carrier.featureTogglesUpdateNotification(after);
+
+            if (before.getServer42FlowRtt() != after.getServer42FlowRtt()) {
+                Collection<Switch> switches = switchRepository.findActive();
+
+                for (Switch sw : switches) {
+                    log.info("Emit switch {} sync command", sw.getSwitchId());
+                    carrier.requestSwitchSync(sw.getSwitchId());
+                }
+            }
         }
         return after;
     }
diff --git a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/IFeatureTogglesCarrier.java b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/IFeatureTogglesCarrier.java
index ffdb3bb2e..9fef92a89 100644
--- a/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/IFeatureTogglesCarrier.java
+++ b/src-java/nbworker-topology/nbworker-storm-topology/src/main/java/org/openkilda/wfm/topology/nbworker/services/IFeatureTogglesCarrier.java
@@ -16,7 +16,10 @@
 package org.openkilda.wfm.topology.nbworker.services;
 
 import org.openkilda.model.FeatureToggles;
+import org.openkilda.model.SwitchId;
 
 public interface IFeatureTogglesCarrier {
     void featureTogglesUpdateNotification(FeatureToggles toggles);
+
+    void requestSwitchSync(SwitchId switchId);
 }
diff --git a/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/fsm/SwitchValidateFsm.java b/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/fsm/SwitchValidateFsm.java
index 64e8cdadf..6b62e6ab9 100644
--- a/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/fsm/SwitchValidateFsm.java
+++ b/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/fsm/SwitchValidateFsm.java
@@ -79,7 +79,6 @@ import org.squirrelframework.foundation.fsm.impl.AbstractStateMachine;
 
 import java.util.HashSet;
 import java.util.List;
-import java.util.Optional;
 import java.util.Set;
 
 @Slf4j
@@ -334,9 +333,7 @@ public class SwitchValidateFsm extends AbstractStateMachine<
         final SwitchId switchId = getSwitchId();
         log.info("Sending requests to get expected switch service rules (switch={}, key={})", switchId, key);
 
-
-        Optional<FeatureToggles> featureToggles = featureTogglesRepository.find();
-        boolean isServer42FlowRtt = switchProperties.isServer42FlowRtt() && featureToggles
+        boolean isServer42FlowRttFeatureToggle = featureTogglesRepository.find()
                 .map(FeatureToggles::getServer42FlowRtt)
                 .orElse(FeatureToggles.DEFAULTS.getServer42FlowRtt());
 
@@ -346,7 +343,8 @@ public class SwitchValidateFsm extends AbstractStateMachine<
                 .multiTable(isMultiTable)
                 .switchLldp(isSwitchLldp)
                 .switchArp(isSwitchArp)
-                .server42FlowRtt(isServer42FlowRtt)
+                .server42FlowRttFeatureToggle(isServer42FlowRttFeatureToggle)
+                .server42FlowRttSwitchProperty(switchProperties.isServer42FlowRtt())
                 .server42Port(switchProperties.getServer42Port())
                 .server42Vlan(switchProperties.getServer42Vlan())
                 .server42MacAddress(switchProperties.getServer42MacAddress());
@@ -366,7 +364,7 @@ public class SwitchValidateFsm extends AbstractStateMachine<
 
             if (flowSide.isMultiTableSegment()) {
                 payload.flowPort(endpoint.getPortNumber());
-                if (isServer42FlowRtt && !flow.isOneSwitchFlow()) {
+                if (isServer42FlowRttFeatureToggle && switchProperties.isServer42FlowRtt() && !flow.isOneSwitchFlow()) {
                     payload.server42FlowRttPort(endpoint.getPortNumber());
                 }
             }
diff --git a/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/service/impl/SwitchRuleServiceImpl.java b/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/service/impl/SwitchRuleServiceImpl.java
index 80c8d544b..8385093e0 100644
--- a/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/service/impl/SwitchRuleServiceImpl.java
+++ b/src-java/swmanager-topology/swmanager-storm-topology/src/main/java/org/openkilda/wfm/topology/switchmanager/service/impl/SwitchRuleServiceImpl.java
@@ -75,14 +75,15 @@ public class SwitchRuleServiceImpl implements SwitchRuleService {
             return;
         }
         Optional<SwitchProperties> switchProperties = switchPropertiesRepository.findBySwitchId(switchId);
-        if (switchProperties.isPresent()) {
-            boolean server42Rtt = featureTogglesRepository.find().map(FeatureToggles::getServer42FlowRtt).orElse(false)
-                    && switchProperties.get().isServer42FlowRtt();
+        boolean server42FeatureToggle = featureTogglesRepository.find()
+                .map(FeatureToggles::getServer42FlowRtt).orElse(false);
+        data.setServer42FlowRttFeatureToggle(server42FeatureToggle);
 
+        if (switchProperties.isPresent()) {
             data.setMultiTable(switchProperties.get().isMultiTable());
             data.setSwitchLldp(switchProperties.get().isSwitchLldp());
             data.setSwitchArp(switchProperties.get().isSwitchArp());
-            data.setServer42FlowRtt(server42Rtt);
+            data.setServer42FlowRttSwitchProperty(switchProperties.get().isServer42FlowRtt());
             data.setServer42Port(switchProperties.get().getServer42Port());
             data.setServer42Vlan(switchProperties.get().getServer42Vlan());
             data.setServer42MacAddress(switchProperties.get().getServer42MacAddress());
@@ -92,7 +93,7 @@ public class SwitchRuleServiceImpl implements SwitchRuleService {
             Set<Integer> flowArpPorts = new HashSet<>();
             Set<Integer> server42FlowPorts = new HashSet<>();
             fillFlowPorts(switchProperties.get(), flowPaths, flowPorts, flowLldpPorts, flowArpPorts, server42FlowPorts,
-                    server42Rtt);
+                    server42FeatureToggle && switchProperties.get().isServer42FlowRtt());
 
             data.setFlowPorts(flowPorts);
             data.setFlowLldpPorts(flowLldpPorts);
@@ -118,14 +119,16 @@ public class SwitchRuleServiceImpl implements SwitchRuleService {
             return;
         }
         Optional<SwitchProperties> switchProperties = switchPropertiesRepository.findBySwitchId(switchId);
-        if (switchProperties.isPresent()) {
-            boolean server42Rtt = featureTogglesRepository.find().map(FeatureToggles::getServer42FlowRtt).orElse(false)
-                    && switchProperties.get().isServer42FlowRtt();
 
+        boolean server42FeatureToggle = featureTogglesRepository.find()
+                .map(FeatureToggles::getServer42FlowRtt).orElse(false);
+        data.setServer42FlowRttFeatureToggle(server42FeatureToggle);
+
+        if (switchProperties.isPresent()) {
             data.setMultiTable(switchProperties.get().isMultiTable());
             data.setSwitchLldp(switchProperties.get().isSwitchLldp());
             data.setSwitchArp(switchProperties.get().isSwitchArp());
-            data.setServer42FlowRtt(server42Rtt);
+            data.setServer42FlowRttSwitchProperty(switchProperties.get().isServer42FlowRtt());
             data.setServer42Port(switchProperties.get().getServer42Port());
             data.setServer42Vlan(switchProperties.get().getServer42Vlan());
             data.setServer42MacAddress(switchProperties.get().getServer42MacAddress());
@@ -135,7 +138,7 @@ public class SwitchRuleServiceImpl implements SwitchRuleService {
             Set<Integer> flowArpPorts = new HashSet<>();
             Set<Integer> server42FlowPorts = new HashSet<>();
             fillFlowPorts(switchProperties.get(), flowPaths, flowPorts, flowLldpPorts, flowArpPorts, server42FlowPorts,
-                    server42Rtt);
+                    server42FeatureToggle && switchProperties.get().isServer42FlowRtt());
             data.setFlowPorts(flowPorts);
             data.setFlowLldpPorts(flowLldpPorts);
             data.setFlowArpPorts(flowArpPorts);