NETVIRT-1200: Upstreaming fixes 2 93/70693/8
authorHANAMANTAGOUD V Kandagal <hanamantagoud.v.kandagal@ericsson.com>
Tue, 10 Apr 2018 06:47:57 +0000 (12:17 +0530)
committerHanamantagoud Kandagal <hanamantagoud.v.kandagal@ericsson.com>
Thu, 26 Apr 2018 05:45:06 +0000 (05:45 +0000)
VM interface IP not advertised to DCGW via BGP

Issue:
When compute server(CSS) is rebooted , the port state was
transitioning from UP->UNKNOWN and UNKNOWN->UP.The check for
original/updated state in InterfaceStateChange listener update() method
prevented the handling of states.

Fix:
When compute reboots, port state transition can have various
combination. Graceful transition would be UP->DOWN->UNKNOWN and
UNKNOWN->DOWN->UP. But as per the logs we saw UP->UNKNOWN and UNKNOWN->UP.
To handle all posible state transition , now State Transition Table is
introduced.

Change-Id: Ibd79866196f085dab30baaa11d8c5c526567e2fd
Signed-off-by: HANAMANTAGOUD V Kandagal <hanamantagoud.v.kandagal@ericsson.com>
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/InterfaceStateChangeListener.java

index 792c8ba79705598f3d24989775121296cd11fb7f..a176694ec5319a6d48ccaf26387e98ef09959cfd 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.netvirt.vpnmanager;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -41,12 +43,33 @@ public class InterfaceStateChangeListener
 
     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
     private static final short DJC_MAX_RETRIES = 3;
-
     private final DataBroker dataBroker;
     private final ManagedNewTransactionRunner txRunner;
     private final VpnInterfaceManager vpnInterfaceManager;
     private final JobCoordinator jobCoordinator;
 
+    Table<OperStatus, OperStatus, IntfTransitionState> stateTable = HashBasedTable.create();
+
+    enum IntfTransitionState {
+        STATE_UP,
+        STATE_DOWN,
+        STATE_IGNORE
+    }
+
+    private void initialize() {
+        //  Interface State Transition Table
+        //               Up                Down            Unknown
+        // ---------------------------------------------------------------
+        /* Up       { STATE_IGNORE,   STATE_DOWN,     STATE_IGNORE }, */
+        /* Down     { STATE_UP,       STATE_IGNORE,   STATE_IGNORE }, */
+        /* Unknown  { STATE_UP,       STATE_DOWN,     STATE_IGNORE }, */
+
+        stateTable.put(Interface.OperStatus.Up, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
+        stateTable.put(Interface.OperStatus.Down, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
+        stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
+        stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
+    }
+
     @Inject
     public InterfaceStateChangeListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager,
             final JobCoordinator jobCoordinator) {
@@ -55,6 +78,7 @@ public class InterfaceStateChangeListener
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.vpnInterfaceManager = vpnInterfaceManager;
         this.jobCoordinator = jobCoordinator;
+        initialize();
     }
 
     @PostConstruct
@@ -217,15 +241,6 @@ public class InterfaceStateChangeListener
                     Interface original, Interface update) {
         final String ifName = update.getName();
         try {
-            OperStatus originalOperStatus = original.getOperStatus();
-            OperStatus updateOperStatus = update.getOperStatus();
-            if (originalOperStatus.equals(Interface.OperStatus.Unknown)
-                  || updateOperStatus.equals(Interface.OperStatus.Unknown)) {
-                LOG.debug("Interface {} state change is from/to null/UNKNOWN. Ignoring the update event.",
-                        ifName);
-                return;
-            }
-
             if (update.getIfIndex() == null) {
                 return;
             }
@@ -248,7 +263,15 @@ public class InterfaceStateChangeListener
                                             LOG.error("remove: Unable to retrieve dpnId for interface {}", ifName, e);
                                             return;
                                         }
-                                        if (update.getOperStatus().equals(OperStatus.Up)) {
+                                        IntfTransitionState state = getTransitionState(original.getOperStatus(),
+                                                update.getOperStatus());
+                                        if (state.equals(IntfTransitionState.STATE_IGNORE)) {
+                                            LOG.info("InterfaceStateChangeListener: Interface {} state original {}"
+                                                    + "updated {} not handled", ifName, original.getOperStatus(),
+                                                    update.getOperStatus());
+                                            return;
+                                        }
+                                        if (state.equals(IntfTransitionState.STATE_UP)) {
                                             for (VpnInstanceNames vpnInterfaceVpnInstance :
                                                     vpnIf.getVpnInstanceNames()) {
                                                 String vpnName = vpnInterfaceVpnInstance.getVpnName();
@@ -268,7 +291,7 @@ public class InterfaceStateChangeListener
                                                             update, vpnName);
                                                 }
                                             }
-                                        } else if (update.getOperStatus().equals(OperStatus.Down)) {
+                                        } else if (state.equals(IntfTransitionState.STATE_DOWN)) {
                                             for (VpnInstanceNames vpnInterfaceVpnInstance :
                                                     vpnIf.getVpnInstanceNames()) {
                                                 String vpnName = vpnInterfaceVpnInstance.getVpnName();
@@ -334,4 +357,13 @@ public class InterfaceStateChangeListener
             }
         }
     }
+
+    private IntfTransitionState getTransitionState(Interface.OperStatus original , Interface.OperStatus updated) {
+        IntfTransitionState transitionState = stateTable.get(original, updated);
+
+        if (transitionState == null) {
+            return IntfTransitionState.STATE_IGNORE;
+        }
+        return transitionState;
+    }
 }