Extra route fixes
[vpnservice.git] / fibmanager / fibmanager-impl / src / main / java / org / opendaylight / vpnservice / fibmanager / FibManager.java
index 80500315315a38b9a18cd35d8a9d87daeb78c56e..128444c65991b8f57dbcb88593d7c75afda3587e 100644 (file)
@@ -70,9 +70,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpc
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetTunnelTypeOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -275,6 +273,7 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
   public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
     BigInteger localDpnId = BigInteger.ZERO;
+    boolean isExtraRoute = false;
     VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
     String localNextHopIP = vrfEntry.getDestPrefix();
 
@@ -282,23 +281,22 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
         //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
         Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
         if (extra_route != null) {
-            localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp());
+            localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp() + "/32");
             localNextHopIP = extra_route.getNexthopIp() + "/32";
+            isExtraRoute = true;
         }
     }
 
 
     if(localNextHopInfo != null) {
       localDpnId = localNextHopInfo.getDpnId();
-      //if (getPrefixToInterface(vpnId, (staticRoute == true) ? extra_route.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()) == null)
-      {
+      Prefixes prefix = getPrefixToInterface(vpnId, isExtraRoute ? localNextHopIP : vrfEntry.getDestPrefix());
         makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, null /* invalid */,
                            NwConstants.DEL_FLOW);
         makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), 0 /* invalid */,
                            vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
         removeTunnelTableEntry(localDpnId, vrfEntry.getLabel());
         deleteLocalAdjacency(localDpnId, vpnId, localNextHopIP);
-      }
     }
     return localDpnId;
   }
@@ -422,9 +420,11 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
             if (vpnInterfaces.remove(currVpnInterface)) {
                 if (vpnInterfaces.isEmpty()) {
-                    //FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id);
-                    cleanUpDpnForVpn(dpnId, vpnId, rd);
+                  LOG.trace("Last vpn interface {} on dpn {} for vpn {}. Clean up fib in dpn", intfName, dpnId, rd);
+                  FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id);
+                  cleanUpDpnForVpn(dpnId, vpnId, rd);
                 } else {
+                  LOG.trace("Delete vpn interface {} from dpn {} to vpn {} list.", intfName, dpnId, rd);
                     FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
                             org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
                                     .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
@@ -444,32 +444,38 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
          - vpn interface op DS
      */
       Prefixes prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
-      boolean extra_route = false;
+      Extraroute extraRoute = null;
       if (prefixInfo == null) {
-          prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getNextHopAddress() + "/32");
-          extra_route = true;
+          extraRoute = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+          if(extraRoute != null) {
+              prefixInfo = getPrefixToInterface(vpnId, extraRoute.getNexthopIp() + "/32");
+              //clean up the vpn to extra route entry in DS
+              FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
+          }
       }
-      if (prefixInfo == null)
+      if (prefixInfo == null) {
+          LOG.debug("Cleanup VPN Data Failed as unable to find prefix Info for " + vrfEntry.getDestPrefix());
           return; //Don't have any info for this prefix (shouldn't happen); need to return
+      }
       String ifName = prefixInfo.getVpnInterfaceName();
       Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
       int numAdj = 0;
       if (optAdjacencies.isPresent()) {
           numAdj = optAdjacencies.get().getAdjacency().size();
       }
+      LOG.trace("cleanUpOpDataForFib: remove adjacency for prefix: {} {}", vpnId, vrfEntry.getDestPrefix());
       //remove adjacency corr to prefix
-      FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+      if (numAdj > 1) {
+        FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+                         FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+      }
 
-      if((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
-        //clean up the vpn interface from DpnToVpn list
-          delIntfFromDpnToVpnList(vpnId, prefixInfo.getDpnId(), ifName, rd);
+      if ((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
+          //clean up the vpn interface from DpnToVpn list
+          LOG.trace("Clean up vpn interface {} from dpn {} to vpn {} list.", ifName, prefixInfo.getDpnId(), rd);
           FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                  FibUtil.getPrefixToInterfaceIdentifier(
-                          vpnId,
-                          (extra_route) ? vrfEntry.getNextHopAddress() + "/32" : vrfEntry.getDestPrefix()));
-          FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
-                  FibUtil.getVpnInterfaceIdentifier(ifName));
-      }
+                         FibUtil.getVpnInterfaceIdentifier(ifName));
+       }
   }
 
   private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier,
@@ -500,17 +506,27 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
                                 final VrfEntry vrfEntry) {
     LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
     String rd = vrfTableKey.getRouteDistinguisher();
-    String egressInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
-    if(egressInterface == null) {
-      LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
-                vrfEntry.getNextHopAddress(), rd);
-      LOG.warn("Failed to delete Route: {} in vpn: {}",
-               vrfEntry.getDestPrefix(), rd);
-      return;
+    boolean isRemoteRoute = true;
+    if (localDpnId == null) {
+      // localDpnId is not known when clean up happens for last vm for a vpn on a dpn
+      VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
+      if(localNextHopInfo == null) {
+        //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+        Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+        if (extra_route != null) {
+          localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp());
+        }
+      }
+      if (localNextHopInfo != null) {
+        isRemoteRoute = (!remoteDpnId.equals(localNextHopInfo.getDpnId()));
+      }
+    }
+    if (isRemoteRoute) {
+      makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
+      LOG.debug("Successfully delete fib entry for "+ vrfEntry.getDestPrefix() + " vpnId "+vpnId);
+    } else{
+      LOG.debug("Did not delete fib entry rd: {} =, prefix: {} as it is local to dpn {}", rd, vrfEntry.getDestPrefix(), remoteDpnId);
     }
-
-    makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
-    LOG.debug("Successfully delete fib entry for "+ vrfEntry.getDestPrefix() + " vpnId "+vpnId);
   }
 
   private long getIpAddress(byte[] rawIpAddress) {
@@ -619,12 +635,33 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
     LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
     InstanceIdentifier<VrfTables> id = buildVrfId(rd);
-    Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
-    if(vrfTable.isPresent()) {
-      for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-        // Passing null as we don't know the dpn
-        // to which prefix is attached at this point
-        createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+    String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+    synchronized (lockOnDpnVpn.intern()) {
+      Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+      if (vrfTable.isPresent()) {
+        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+          // Passing null as we don't know the dpn
+          // to which prefix is attached at this point
+          createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+        }
+      }
+    }
+  }
+
+  public void populateFibOnDpn(BigInteger dpnId, long vpnId, String rd, String nexthopIp) {
+    LOG.trace("dpn {} for vpn {}, nexthopIp {} : populateFibOnDpn", dpnId, rd, nexthopIp);
+    InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+    String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+    synchronized (lockOnDpnVpn.intern()) {
+      Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+      if (vrfTable.isPresent()) {
+        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+          // Passing null as we don't know the dpn
+          // to which prefix is attached at this point
+          if (nexthopIp == vrfEntry.getNextHopAddress()) {
+            createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+          }
+        }
       }
     }
   }
@@ -632,12 +669,33 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
   public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
     LOG.trace("Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
     InstanceIdentifier<VrfTables> id = buildVrfId(rd);
-    Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
-    if(vrfTable.isPresent()) {
-      for(VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
-        // Passing null as we don't know the dpn
-        // to which prefix is attached at this point
-        deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+    String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+    synchronized (lockOnDpnVpn.intern()) {
+      Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+      if (vrfTable.isPresent()) {
+        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+          // Passing null as we don't know the dpn
+          // to which prefix is attached at this point
+          deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+        }
+      }
+    }
+  }
+
+  public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd, String nexthopIp) {
+    LOG.trace("dpn {} for vpn {}, nexthopIp {} : cleanUpDpnForVpn", dpnId, rd, nexthopIp);
+    InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+    String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+    synchronized (lockOnDpnVpn.intern()) {
+      Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+      if (vrfTable.isPresent()) {
+        for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+          // Passing null as we don't know the dpn
+          // to which prefix is attached at this point
+          if (nexthopIp == vrfEntry.getNextHopAddress()) {
+            deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+          }
+        }
       }
     }
   }
@@ -676,8 +734,8 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
 
         adjacency =
           nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
-                                                 vrfEntry.getDestPrefix(),
-                  (staticRoute == true) ? extra_route.getNexthopIp() : vrfEntry.getNextHopAddress());
+                  (staticRoute == true) ? extra_route.getNexthopIp() + "/32" : vrfEntry.getDestPrefix(),
+                                                vrfEntry.getNextHopAddress());
     } catch (NullPointerException e) {
       LOG.trace("", e);
     }
@@ -789,7 +847,11 @@ public class FibManager extends AbstractDataChangeListener<VrfEntry> implements
     instructions.add(new InstructionInfo(InstructionType.clear_actions));
     // Instruction to goto L3 InterfaceTable
 
-    instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
+    List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+    actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
+        Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
+    instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+    //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
 
     FlowEntity flowEntityL3Intf = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_INTERFACE_TABLE,
             getFlowRef(dpnId, NwConstants.L3_INTERFACE_TABLE, NwConstants.TABLE_MISS_FLOW),