VPN flows in Table 21 pointing to wrong DCGW
[netvirt.git] / fibmanager / impl / src / main / java / org / opendaylight / netvirt / fibmanager / EvpnVrfEntryHandler.java
index fcd979ae80fbc99c07cad8dc4233eb93c842ac0f..a23c54d1477d37e684e109b1144208233bbd01fd 100644 (file)
@@ -11,29 +11,30 @@ import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.UpgradeState;
 import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetDestination;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
 import org.opendaylight.genius.utils.batching.SubTransaction;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
-import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.serviceutils.upgrade.UpgradeState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
@@ -44,22 +45,23 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
-public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntryHandler {
+public class EvpnVrfEntryHandler extends BaseVrfEntryHandler {
     private static final Logger LOG = LoggerFactory.getLogger(EvpnVrfEntryHandler.class);
     private final ManagedNewTransactionRunner txRunner;
     private final VrfEntryListener vrfEntryListener;
     private final BgpRouteVrfEntryHandler bgpRouteVrfEntryHandler;
     private final NexthopManager nexthopManager;
     private final JobCoordinator jobCoordinator;
-    private final IElanService elanManager;
 
     EvpnVrfEntryHandler(DataBroker broker, VrfEntryListener vrfEntryListener,
             BgpRouteVrfEntryHandler bgpRouteVrfEntryHandler, NexthopManager nexthopManager,
-            JobCoordinator jobCoordinator, IElanService elanManager, FibUtil fibUtil,
+            JobCoordinator jobCoordinator, FibUtil fibUtil,
             final UpgradeState upgradeState, final DataTreeEventCallbackRegistrar eventCallbacks) {
         super(broker, nexthopManager, null, fibUtil, upgradeState, eventCallbacks);
         this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
@@ -67,23 +69,21 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         this.bgpRouteVrfEntryHandler = bgpRouteVrfEntryHandler;
         this.nexthopManager = nexthopManager;
         this.jobCoordinator = jobCoordinator;
-        this.elanManager = elanManager;
     }
 
-    @Override
-    public void createFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
+    void createFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
         LOG.info("Initiating creation of Evpn Flows");
         final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
         final VpnInstanceOpDataEntry vpnInstance = getFibUtil().getVpnInstanceOpData(
                 vrfTableKey.getRouteDistinguisher()).get();
-        Long vpnId = vpnInstance.getVpnId();
+        Uint32 vpnId = vpnInstance.getVpnId();
         Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
         Preconditions.checkNotNull(vpnId, "Vpn Instance with rd " + vpnInstance.getVrfId()
                 + " has null vpnId!");
         if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.CONNECTED) {
             SubnetRoute subnetRoute = vrfEntry.augmentation(SubnetRoute.class);
             final List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
-            final long elanTag = subnetRoute.getElantag();
+            final long elanTag = subnetRoute.getElantag().toJava();
             LOG.trace("SubnetRoute augmented vrfentry found for rd {} prefix {} with elantag {}",
                     rd, vrfEntry.getDestPrefix(), elanTag);
             if (vpnToDpnList != null) {
@@ -100,8 +100,9 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
             }
             return;
         }
-        Prefixes localNextHopInfo = getFibUtil().getPrefixToInterface(vpnInstance.getVpnId(), vrfEntry.getDestPrefix());
-        List<BigInteger> localDpnId = new ArrayList<>();
+        Prefixes localNextHopInfo = getFibUtil().getPrefixToInterface(vpnInstance.getVpnId(),
+                                                                            vrfEntry.getDestPrefix());
+        List<Uint64> localDpnId = new ArrayList<>();
         boolean isNatPrefix = false;
         if (Prefixes.PrefixCue.Nat.equals(localNextHopInfo.getPrefixCue())) {
             LOG.info("NAT Prefix {} with vpnId {} rd {}. Skip local dpn {} FIB processing",
@@ -115,8 +116,7 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         createRemoteEvpnFlows(rd, vrfEntry, vpnInstance, localDpnId, vrfTableKey, isNatPrefix);
     }
 
-    @Override
-    public void removeFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
+    void removeFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry, String rd) {
         final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class);
         final VpnInstanceOpDataEntry vpnInstance = getFibUtil().getVpnInstanceOpData(
                 vrfTableKey.getRouteDistinguisher()).get();
@@ -126,31 +126,27 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         }
         VpnNexthop localNextHopInfo = nexthopManager.getVpnNexthop(vpnInstance.getVpnId(),
                 vrfEntry.getDestPrefix());
-        List<BigInteger> localDpnId = checkDeleteLocalEvpnFLows(vpnInstance.getVpnId(), rd, vrfEntry, localNextHopInfo);
+        List<Uint64> localDpnId = checkDeleteLocalEvpnFLows(vpnInstance.getVpnId(),
+                                                                    rd, vrfEntry, localNextHopInfo);
         deleteRemoteEvpnFlows(rd, vrfEntry, vpnInstance, vrfTableKey, localDpnId);
         vrfEntryListener.cleanUpOpDataForFib(vpnInstance.getVpnId(), rd, vrfEntry);
     }
 
-    @Override
-    public void updateFlows(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update, String rd) {
-        //Not used
-    }
-
-    private List<BigInteger> createLocalEvpnFlows(long vpnId, String rd, VrfEntry vrfEntry,
+    private List<Uint64> createLocalEvpnFlows(Uint32 vpnId, String rd, VrfEntry vrfEntry,
                                                   Prefixes localNextHopInfo) {
-        List<BigInteger> returnLocalDpnId = new ArrayList<>();
+        List<Uint64> returnLocalDpnId = new ArrayList<>();
         String localNextHopIP = vrfEntry.getDestPrefix();
         if (localNextHopInfo == null) {
             //Handle extra routes and imported routes
             Routes extraRoute = getVpnToExtraroute(vpnId, rd, vrfEntry.getDestPrefix());
-            if (extraRoute != null) {
+            if (extraRoute != null && extraRoute.getNexthopIpList() != null) {
                 for (String nextHopIp : extraRoute.getNexthopIpList()) {
                     LOG.info("NextHop IP for destination {} is {}", vrfEntry.getDestPrefix(), nextHopIp);
                     if (nextHopIp != null) {
                         localNextHopInfo = getFibUtil().getPrefixToInterface(vpnId, nextHopIp + "/32");
                         if (localNextHopInfo != null) {
                             localNextHopIP = nextHopIp + "/32";
-                            BigInteger dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
+                            Uint64 dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
                                     rd, vrfEntry);
                             returnLocalDpnId.add(dpnId);
                         }
@@ -160,21 +156,23 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         } else {
             LOG.info("Creating local EVPN flows for prefix {} rd {} route-paths {} evi {}.",
                     vrfEntry.getDestPrefix(), rd, vrfEntry.getRoutePaths(), vrfEntry.getL3vni());
-            BigInteger dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
+            Uint64 dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId,
                     rd, vrfEntry);
             returnLocalDpnId.add(dpnId);
         }
         return returnLocalDpnId;
     }
 
-    private BigInteger checkCreateLocalEvpnFlows(Prefixes localNextHopInfo, String localNextHopIP,
-                                                 final Long vpnId, final String rd,
+    // Allow deprecated TransactionRunner calls for now
+    @SuppressWarnings("ForbidCertainMethod")
+    private Uint64 checkCreateLocalEvpnFlows(Prefixes localNextHopInfo, String localNextHopIP,
+                                                 final Uint32 vpnId, final String rd,
                                                  final VrfEntry vrfEntry) {
-        final BigInteger dpnId = localNextHopInfo.getDpnId();
+        final Uint64 dpnId = localNextHopInfo.getDpnId();
         String jobKey = FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix());
         final long groupId = nexthopManager.createLocalNextHop(vpnId, dpnId,
             localNextHopInfo.getVpnInterfaceName(), localNextHopIP, vrfEntry.getDestPrefix(),
-            vrfEntry.getGatewayMacAddress());
+            vrfEntry.getGatewayMacAddress(), /*parentVpnId*/ null);
         LOG.debug("LocalNextHopGroup {} created/reused for prefix {} rd {} evi {} route-paths {}", groupId,
             vrfEntry.getDestPrefix(), rd, vrfEntry.getL3vni(), vrfEntry.getRoutePaths());
 
@@ -188,8 +186,10 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         return dpnId;
     }
 
+    // Allow deprecated TransactionRunner calls for now
+    @SuppressWarnings("ForbidCertainMethod")
     private void createRemoteEvpnFlows(String rd, VrfEntry vrfEntry, VpnInstanceOpDataEntry vpnInstance,
-                                       List<BigInteger> localDpnId, VrfTablesKey vrfTableKey, boolean isNatPrefix) {
+                                       List<Uint64> localDpnId, VrfTablesKey vrfTableKey, boolean isNatPrefix) {
         LOG.info("Creating remote EVPN flows for prefix {} rd {} route-paths {} evi {}",
             vrfEntry.getDestPrefix(), rd, vrfEntry.getRoutePaths(), vrfEntry.getL3vni());
         List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
@@ -208,7 +208,7 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         }
     }
 
-    private void createRemoteFibEntry(final BigInteger remoteDpnId, final long vpnId, final VrfTablesKey vrfTableKey,
+    private void createRemoteFibEntry(final Uint64 remoteDpnId, final Uint32 vpnId, final VrfTablesKey vrfTableKey,
                                       final VrfEntry vrfEntry, boolean isNatPrefix, WriteTransaction tx) {
 
         String rd = vrfTableKey.getRouteDistinguisher();
@@ -227,17 +227,27 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
 
         for (NexthopManager.AdjacencyResult adjacencyResult : tunnelInterfaceList) {
             List<ActionInfo> actionInfos = new ArrayList<>();
-            BigInteger tunnelId;
+            Uint64 tunnelId = Uint64.ZERO;
             String prefix = adjacencyResult.getPrefix();
             Prefixes prefixInfo = getFibUtil().getPrefixToInterface(vpnId, prefix);
             String interfaceName = prefixInfo.getVpnInterfaceName();
-            if (vrfEntry.getOrigin().equals(RouteOrigin.BGP.getValue()) || isNatPrefix) {
-                tunnelId = BigInteger.valueOf(vrfEntry.getL3vni());
+            if (RouteOrigin.BGP.getValue().equals(vrfEntry.getOrigin()) || isNatPrefix) {
+                tunnelId = Uint64.valueOf(vrfEntry.getL3vni().longValue());
             } else if (FibUtil.isVxlanNetwork(prefixInfo.getNetworkType())) {
-                tunnelId = BigInteger.valueOf(prefixInfo.getSegmentationId());
+                tunnelId = Uint64.valueOf(prefixInfo.getSegmentationId().longValue());
             } else {
-                Interface interfaceState = getFibUtil().getInterfaceStateFromOperDS(interfaceName);
-                tunnelId = BigInteger.valueOf(interfaceState.getIfIndex());
+                try {
+                    StateTunnelList stateTunnelList = getFibUtil().getTunnelState(interfaceName);
+                    if (stateTunnelList == null || stateTunnelList.getOperState() != TunnelOperStatus.Up) {
+                        LOG.trace("Tunnel is not up for interface {}", interfaceName);
+                        return;
+                    }
+                    tunnelId = Uint64.valueOf(stateTunnelList.getIfIndex().intValue());
+                } catch (ReadFailedException e) {
+                    LOG.error("createRemoteFibEntry: error in fetching tunnel state for interface {}",
+                            interfaceName, e);
+                    continue;
+                }
             }
             LOG.debug("adding set tunnel id action for label {}", tunnelId);
             String macAddress = null;
@@ -253,7 +263,7 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
             actionInfos.add(new ActionSetFieldTunnelId(tunnelId));
             List<ActionInfo> egressActions =
                     nexthopManager.getEgressActionsForInterface(adjacencyResult.getInterfaceName(), actionInfos.size(),
-                            true);
+                            true, vpnId, vrfEntry.getDestPrefix());
             if (egressActions.isEmpty()) {
                 LOG.error("Failed to retrieve egress action for prefix {} route-paths {} interface {}."
                         + " Aborting remote FIB entry creation..", vrfEntry.getDestPrefix(),
@@ -268,8 +278,10 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         LOG.debug("Successfully added FIB entry for prefix {} in rd {}", vrfEntry.getDestPrefix(), rd);
     }
 
+    // Allow deprecated TransactionRunner calls for now
+    @SuppressWarnings("ForbidCertainMethod")
     private void deleteRemoteEvpnFlows(String rd, VrfEntry vrfEntry, VpnInstanceOpDataEntry vpnInstance,
-                                       VrfTablesKey vrfTableKey, List<BigInteger> localDpnIdList) {
+                                       VrfTablesKey vrfTableKey, List<Uint64> localDpnIdList) {
         List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
         List<SubTransaction> subTxns =  new ArrayList<>();
         if (vpnToDpnList != null) {
@@ -280,23 +292,25 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
                         for (VpnToDpnList curDpn1 : vpnToDpnList) {
                             if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
                                 if (curDpn1.getDpnState() == VpnToDpnList.DpnState.Active) {
-                                    bgpRouteVrfEntryHandler.deleteRemoteRoute(BigInteger.ZERO, curDpn1.getDpnId(),
+                                    bgpRouteVrfEntryHandler.deleteRemoteRoute(Uint64.ZERO,
+                                            curDpn1.getDpnId(),
                                             vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
                                             extraRouteOptional, tx, subTxns);
                                 }
                             } else {
-                                deleteRemoteRoute(BigInteger.ZERO, curDpn1.getDpnId(),
+                                deleteRemoteRoute(Uint64.ZERO, curDpn1.getDpnId(),
                                         vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
                                         extraRouteOptional, tx);
                             }
                         }
                     } else {
-                        for (BigInteger localDpnId : localDpnIdList) {
+                        for (Uint64 localDpnId : localDpnIdList) {
                             for (VpnToDpnList curDpn2 : vpnToDpnList) {
-                                if (!curDpn2.getDpnId().equals(localDpnId)) {
+                                if (!Objects.equals(curDpn2.getDpnId(), localDpnId)) {
                                     if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.BGP) {
                                         if (curDpn2.getDpnState() == VpnToDpnList.DpnState.Active) {
-                                            bgpRouteVrfEntryHandler.deleteRemoteRoute(localDpnId, curDpn2.getDpnId(),
+                                            bgpRouteVrfEntryHandler.deleteRemoteRoute(localDpnId,
+                                                    curDpn2.getDpnId(),
                                                     vpnInstance.getVpnId(), vrfTableKey, vrfEntry,
                                                     extraRouteOptional, tx, subTxns);
                                         }
@@ -313,13 +327,15 @@ public class EvpnVrfEntryHandler extends BaseVrfEntryHandler implements IVrfEntr
         }
     }
 
-    private List<BigInteger> checkDeleteLocalEvpnFLows(long vpnId, String rd, VrfEntry vrfEntry,
+    // Allow deprecated TransactionRunner calls for now
+    @SuppressWarnings("ForbidCertainMethod")
+    private List<Uint64> checkDeleteLocalEvpnFLows(Uint32 vpnId, String rd, VrfEntry vrfEntry,
                                                        VpnNexthop localNextHopInfo) {
-        List<BigInteger> returnLocalDpnId = new ArrayList<>();
+        List<Uint64> returnLocalDpnId = new ArrayList<>();
         if (localNextHopInfo == null) {
             //Handle extra routes and imported routes
         } else {
-            final BigInteger dpnId = localNextHopInfo.getDpnId();
+            final Uint64 dpnId = localNextHopInfo.getDpnId();
             jobCoordinator.enqueueJob("FIB-" + rd + "-" + vrfEntry.getDestPrefix(),
                 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
                     tx -> makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW, tx,