Implement ITM Egress Tunnel Tables 39/72839/21
authorEdw7n <n.edwin.anthony@ericsson.com>
Thu, 14 Mar 2019 09:51:42 +0000 (15:21 +0530)
committerFaseela K <faseela.k@ericsson.com>
Mon, 6 May 2019 08:20:24 +0000 (08:20 +0000)
Adding a new Egress Tunnel Table for dpn-dpn tunnels.
All packets that will egress to a tunnel will go through this
table now, benefits being:

1. Applications need not listen on tunnel add/delete events,
   to update their flows based on port number or egress lport tag, as the
   port number will be contained within the egress tunnel table.

2. Tunnel addition and deletion can be ITM self-contained.

Change-Id: I8302318f479785c949fff928d5ba2f043f59b0c8
Signed-off-by: Edw7n <n.edwin.anthony@ericsson.com>
itm/itm-api/src/main/java/org/opendaylight/genius/itm/utils/DpnTepInterfaceInfo.java
itm/itm-api/src/main/yang/itm-state.yang
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/cache/DpnTepStateCache.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/confighelpers/ItmInternalTunnelAddWorker.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/listeners/TunnelInventoryStateListener.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/renderer/ovs/utilities/DirectTunnelUtils.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/itmdirecttunnels/workers/TunnelStateAddWorker.java
itm/itm-impl/src/main/java/org/opendaylight/genius/itm/rpc/ItmManagerRpcService.java
itm/itm-impl/src/test/java/org/opendaylight/genius/itm/impl/ItmInternalTunnelAddTest.java

index cb6a672593a9eba9798bb8eb57804a5b2e6e6a23..7bc1a1412d390a5c8fe93250c5d3e0b4b45d6cb6 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.genius.itm.utils;
 
+import java.math.BigInteger;
 import org.immutables.value.Value;
 import org.opendaylight.genius.infra.OpenDaylightImmutableStyle;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
@@ -22,4 +23,6 @@ public interface DpnTepInterfaceInfo {
     boolean isMonitoringEnabled();
 
     boolean isInternal();
+
+    BigInteger getRemoteDPN();
 }
index 779444079122d38662a373959db8ed6e4ceeddb6..81988c7efdf3e7ed797f8c3a2ad891d7346e73b3 100644 (file)
@@ -83,6 +83,14 @@ module itm-state {
           leaf DPN-ID {
               type uint64;
           }
+
+          leaf dst-id {
+              description "Identifier to get to a this DPN, which will be used in programming Egress flows ";
+              type int32 {
+                  range "1..2147483647";
+              }
+          }
+
           leaf up {
               status deprecated;
               type boolean;
index 61b2ae17d6cb5f5087302f177229b83bea22f8fe..eaf63223098243e2a96a531a8731e8239fae0bbf 100644 (file)
@@ -96,7 +96,8 @@ public class DpnTepStateCache extends DataObjectCache<BigInteger, DpnsTeps> {
                 .setTunnelName(remoteDpns.getTunnelName())
                 .setIsMonitoringEnabled(remoteDpns.isMonitoringEnabled())
                 .setIsInternal(remoteDpns.isInternal())
-                .setTunnelType(dpnsTeps.getTunnelType()).build();
+                .setTunnelType(dpnsTeps.getTunnelType())
+                .setRemoteDPN(remoteDpns.getDestinationDpnId()).build();
             dpnTepInterfaceMap.put(dpn, value);
             addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(),
                     dpnsTeps.getSourceDpnId().toString(), remoteDpns.getDestinationDpnId().toString());
index f1d235097ce69ec8b6a769c05487b7837da7fed3..1dbf2f4dcb15c76802aa4444102733f801a24b0e 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.genius.infra.TypedReadWriteTransaction;
 import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.itm.cache.OvsBridgeRefEntryCache;
+import org.opendaylight.genius.itm.globals.ITMConstants;
 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
 import org.opendaylight.genius.itm.impl.ItmUtils;
 import org.opendaylight.genius.itm.impl.TunnelMonitoringConfig;
@@ -55,6 +56,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.Dpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsStateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfoBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsBuilder;
@@ -120,16 +122,18 @@ public final class ItmInternalTunnelAddWorker {
                     meshedDpnList.add(dpn);
                 }
                 // Update the config datastore -- FIXME -- Error Handling
-                updateDpnTepInfoToConfig(tx, dpn);
+                updateDpnTepInfoToConfig(tx, dpn, directTunnelUtils);
             }
         }));
     }
 
-    private static void updateDpnTepInfoToConfig(TypedWriteTransaction<Configuration> tx, DPNTEPsInfo dpn) {
+    private static void updateDpnTepInfoToConfig(TypedWriteTransaction<Configuration> tx, DPNTEPsInfo dpn,
+        DirectTunnelUtils directTunnelUtils) throws ExecutionException, InterruptedException, OperationFailedException {
         LOG.debug("Updating CONFIGURATION datastore with DPN {} ", dpn);
         InstanceIdentifier<DpnEndpoints> dep = InstanceIdentifier.builder(DpnEndpoints.class).build() ;
         List<DPNTEPsInfo> dpnList = new ArrayList<>() ;
-        dpnList.add(dpn) ;
+        dpnList.add(new DPNTEPsInfoBuilder(dpn)
+            .setDstId(directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, dpn.getDPNID().toString())).build());
         DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnList).build() ;
         tx.merge(dep, tnlBuilder);
     }
index 65b8bb7d5515a1531770629315f66ad150566cd3..c077d6a18a629f5e2f8bf6db59261e0088bd2a64 100644 (file)
@@ -343,6 +343,7 @@ public class TunnelInventoryStateListener extends
                     // Do if-index and ingress flow clean-up only for tunnel-interfaces
                     directTunnelUtils.removeLportTagInterfaceMap(interfaceName);
                     directTunnelUtils.removeTunnelIngressFlow(tx, dpId, interfaceName);
+                    directTunnelUtils.removeTunnelEgressFlow(tx, dpId, interfaceName);
                 }));
             } else {
                 LOG.error("DPNTEPInfo is null for Tunnel Interface {}", interfaceName);
index 38a47ef933b77e089e2b3f6a3a3645eb67e7eef6..175176214509fec974b4b9271224447b5f69ef8f 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.math.BigInteger;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -28,21 +29,26 @@ import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.genius.itm.globals.ITMConstants;
 import org.opendaylight.genius.itm.impl.ITMBatchingUtils;
 import org.opendaylight.genius.itm.impl.ItmUtils;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
+import org.opendaylight.genius.mdsalutil.actions.ActionSetTunnelDestinationIp;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchInPort;
+import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
 import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
@@ -57,6 +63,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlanGpe;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.BridgeTunnelInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.IfIndexesTunnelMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.meta.rev171210.OvsBridgeRefInfo;
@@ -78,6 +85,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tun
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
@@ -170,13 +178,15 @@ public final class DirectTunnelUtils {
     private final IdManagerService idManagerService;
     private final IMdsalApiManager mdsalApiManager;
     private final EntityOwnershipUtils entityOwnershipUtils;
+    private final ItmConfig itmConfig;
 
     @Inject
     public DirectTunnelUtils(final IdManagerService idManagerService, final IMdsalApiManager mdsalApiManager,
-                             final EntityOwnershipUtils entityOwnershipUtils) {
+                             final EntityOwnershipUtils entityOwnershipUtils, final ItmConfig itmConfig) {
         this.idManagerService = idManagerService;
         this.mdsalApiManager = mdsalApiManager;
         this.entityOwnershipUtils = entityOwnershipUtils;
+        this.itmConfig = itmConfig;
     }
 
     public KeyedLocks<String> getTunnelLocks() {
@@ -369,6 +379,33 @@ public final class DirectTunnelUtils {
         mdsalApiManager.removeFlow(tx, dpnId, flowRef, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
     }
 
+    public void addTunnelEgressFlow(TypedWriteTransaction<Configuration> tx, BigInteger dpnId, String portNo,
+                                    int dstId, String interfaceName, IpAddress dstIp) {
+        LOG.debug("add tunnel egress flow for {}", interfaceName);
+        List<MatchInfoBase> matches = new ArrayList<>();
+        List<ActionInfo> actions = new ArrayList<>();
+        matches.add(new NxMatchRegister(NxmNxReg6.class, MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId)));
+        if (itmConfig.isUseOfTunnels()) {
+            actions.add(new ActionSetTunnelDestinationIp(0, dstIp));
+            actions.add(new ActionOutput(1, new Uri(portNo)));
+        } else {
+            actions.add(new ActionOutput(0, new Uri(portNo)));
+        }
+        String flowRef = getTunnelInterfaceFlowRef(dpnId, NwConstants.EGRESS_TUNNEL_TABLE, interfaceName);
+        Flow egressFlow = MDSALUtil.buildFlowNew(NwConstants.EGRESS_TUNNEL_TABLE, flowRef, 5, flowRef, 0, 0,
+            NwConstants.COOKIE_ITM_EGRESS_TUNNEL_TABLE, matches,
+            Collections.singletonList(MDSALUtil.buildApplyActionsInstruction(MDSALUtil.buildActions(actions))));
+        mdsalApiManager.addFlow(tx, dpnId, egressFlow);
+    }
+
+    public void removeTunnelEgressFlow(TypedReadWriteTransaction<Configuration> tx, BigInteger dpnId,
+                                       String interfaceName) throws ExecutionException, InterruptedException {
+        LOG.debug("remove tunnel egress flow for {}", interfaceName);
+        String flowRef =
+                getTunnelInterfaceFlowRef(dpnId, NwConstants.EGRESS_TUNNEL_TABLE, interfaceName);
+        mdsalApiManager.removeFlow(tx, dpnId, flowRef, NwConstants.EGRESS_TUNNEL_TABLE);
+    }
+
     private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
         return String.valueOf(dpnId) + tableId + ifName;
     }
@@ -398,8 +435,12 @@ public final class DirectTunnelUtils {
         IpAddress localIp = ifTunnel.getTunnelSource();
         options.put(DirectTunnelUtils.TUNNEL_OPTIONS_LOCAL_IP, localIp.getIpv4Address().getValue());
 
-        IpAddress remoteIp = ifTunnel.getTunnelDestination();
-        options.put(DirectTunnelUtils.TUNNEL_OPTIONS_REMOTE_IP, remoteIp.getIpv4Address().getValue());
+        if (itmConfig.isUseOfTunnels()) {
+            options.put(TUNNEL_OPTIONS_REMOTE_IP, TUNNEL_OPTIONS_VALUE_FLOW);
+        } else {
+            IpAddress remoteIp = ifTunnel.getTunnelDestination();
+            options.put(DirectTunnelUtils.TUNNEL_OPTIONS_REMOTE_IP, remoteIp.getIpv4Address().getValue());
+        }
 
         options.put(DirectTunnelUtils.TUNNEL_OPTIONS_TOS, DirectTunnelUtils.TUNNEL_OPTIONS_TOS_VALUE_INHERIT);
 
index 274fc38ada4ccab57d4ba16789162245b5201ca9..ffb77c7002a60b7310c3b00cba3d95081071abde 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.genius.itm.itmdirecttunnels.workers;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
@@ -78,12 +79,17 @@ public final class TunnelStateAddWorker {
 
         // This will be only tunnel If so not required
         // If this interface is a tunnel interface, create the tunnel ingress flow,
+        // Egress flow for table 95 is installed based on dstId of the remote dpn,
         // and start tunnel monitoring
         if (stateTnl != null) {
             return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(Datastore.CONFIGURATION,
-                tx -> directTunnelUtils.addTunnelIngressFlow(tx,
-                    DirectTunnelUtils.getDpnFromNodeConnectorId(nodeConnectorId), portNo, interfaceName,
-                    stateTnl.getIfIndex())));
+                tx -> {
+                    BigInteger dpId = DirectTunnelUtils.getDpnFromNodeConnectorId(nodeConnectorId);
+                    directTunnelUtils.addTunnelIngressFlow(tx, dpId, portNo, interfaceName, stateTnl.getIfIndex());
+                    directTunnelUtils.addTunnelEgressFlow(tx, dpId, String.valueOf(portNo),
+                        tunnelStateInfo.getDstDpnTepsInfo().getDstId(), interfaceName,
+                        tunnelStateInfo.getDstDpnTepsInfo().getTunnelEndPoints().get(0).getIpAddress());
+                }));
         }
         return Collections.emptyList();
     }
index 70723682c7a2b5ecfd78b693f32a0504f861249f..3e3e327db2a1b3418284818ecf6cb2bc6267e744 100644 (file)
@@ -58,16 +58,16 @@ import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
 import org.opendaylight.genius.mdsalutil.ActionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.actions.ActionOutput;
+import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
+import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.serviceutils.tools.mdsal.rpc.FutureRpcResults;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.BridgeRefInfo;
@@ -91,7 +91,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.DcGatewayIpList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.dc.gateway.ip.list.DcGatewayIp;
@@ -162,7 +161,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.g
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.get.dpn.info.output.ComputesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.OperationFailedException;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
@@ -187,6 +188,7 @@ public class ItmManagerRpcService implements ItmRpcService {
     private final DirectTunnelUtils directTunnelUtils;
     private final ManagedNewTransactionRunner txRunner;
     private final RetryingManagedNewTransactionRunner retryingTxRunner;
+    private final ItmConfig itmConfig;
 
     @Inject
     public ItmManagerRpcService(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
@@ -209,6 +211,7 @@ public class ItmManagerRpcService implements ItmRpcService {
         this.directTunnelUtils = directTunnelUtils;
         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
         this.retryingTxRunner = new RetryingManagedNewTransactionRunner(dataBroker);
+        this.itmConfig = itmConfig;
     }
 
     @PostConstruct
@@ -305,7 +308,7 @@ public class ItmManagerRpcService implements ItmRpcService {
                 } ,MoreExecutors.directExecutor());
             return  settableFuture;
         } else {
-            return fromListenableFuture(LOG, input, () -> getEgressActionsForInterface(input.getIntfName(),
+            return fromListenableFuture(LOG, input, () -> getEgressActionsForInternalTunnels(input.getIntfName(),
                     input.getTunnelKey(), input.getActionKey())).onFailureLogLevel(ERROR).build();
         }
     }
@@ -1163,46 +1166,41 @@ public class ItmManagerRpcService implements ItmRpcService {
                         .network.topology.topology.Node.class).getNodeId().getValue();
     }
 
-    private ListenableFuture<GetEgressActionsForTunnelOutput> getEgressActionsForInterface(String interfaceName,
-           Long tunnelKey, Integer actionKey) throws ReadFailedException {
-        int actionKeyStart = actionKey == null ? 0 : actionKey;
+    private ListenableFuture<GetEgressActionsForTunnelOutput>
+        getEgressActionsForInternalTunnels(String interfaceName, Long tunnelKey, Integer actionKey)
+            throws ExecutionException, InterruptedException, OperationFailedException {
+
         DpnTepInterfaceInfo interfaceInfo = dpnTepStateCache.getTunnelFromCache(interfaceName);
         if (interfaceInfo == null) {
             throw new IllegalStateException("Interface information not present in config DS for" + interfaceName);
         }
-        Optional<StateTunnelList> ifState = tunnelStateCache
-                .get(tunnelStateCache.getStateTunnelListIdentifier(interfaceName));
-        if (ifState.isPresent()) {
-            String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
-            List<Action> actions = getEgressActionInfosForInterface(tunnelType, ifState.get().getPortNumber(),
-                    tunnelKey, actionKeyStart).stream().map(ActionInfo::buildAction).collect(Collectors.toList());
-            return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder().setAction(actions).build());
+
+        String tunnelType = ItmUtils.convertTunnelTypetoString(interfaceInfo.getTunnelType());
+        if (!tunnelType.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_VXLAN)) {
+            throw new IllegalArgumentException(tunnelType + " tunnel not handled by ITM");
         }
-        throw new IllegalStateException("Interface information not present in oper DS for" + interfaceName);
-    }
 
-    private static List<ActionInfo> getEgressActionInfosForInterface(String tunnelType, String portNo, Long tunnelKey,
-                                                                     int actionKeyStart) {
-        List<ActionInfo> result = new ArrayList<>();
-        switch (tunnelType) {
-            case ITMConstants.TUNNEL_TYPE_GRE:
-            case ITMConstants.TUNNEL_TYPE_MPLSoGRE:
-                // Invoke IFM RPC and pass it on to the caller.
-                LOG.warn("Interface Type {} not handled by ITM", tunnelType);
-                break;
-            case ITMConstants.TUNNEL_TYPE_VXLAN:
-                //TODO tunnel_id to encode GRE key, once it is supported
-                // Until then, tunnel_id should be "cleaned", otherwise it stores the value coming from a VXLAN tunnel
-                result.add(new ActionSetFieldTunnelId(actionKeyStart++,
-                        BigInteger.valueOf(tunnelKey != null ? tunnelKey : 0L)));
-                result.add(new ActionOutput(actionKeyStart, new Uri(portNo)));
-                break;
-
-            default:
-                LOG.warn("Interface Type {} not handled yet", tunnelType);
-                break;
+        Optional<DPNTEPsInfo> dpntePsInfoOptional = dpnTEPsInfoCache.get(InstanceIdentifier.builder(DpnEndpoints.class)
+                .child(DPNTEPsInfo.class, new DPNTEPsInfoKey(new BigInteger(dpnTepStateCache
+                        .getTunnelEndPointInfoFromCache(interfaceInfo.getTunnelName()).getDstEndPointInfo()))).build());
+        Integer dstId;
+        if (dpntePsInfoOptional.isPresent()) {
+            dstId = dpntePsInfoOptional.get().getDstId();
+        } else {
+            dstId = directTunnelUtils.allocateId(ITMConstants.ITM_IDPOOL_NAME, interfaceInfo.getRemoteDPN().toString());
         }
-        return result;
+
+        List<ActionInfo> result = new ArrayList<>();
+        long regValue = MetaDataUtil.getRemoteDpnMetadatForEgressTunnelTable(dstId);
+        int actionKeyStart = actionKey == null ? 0 : actionKey;
+        result.add(new ActionSetFieldTunnelId(actionKeyStart++,
+                BigInteger.valueOf(tunnelKey != null ? tunnelKey : 0L)));
+        result.add(new ActionRegLoad(actionKeyStart++, NxmNxReg6.class, MetaDataUtil.REG6_START_INDEX,
+                MetaDataUtil.REG6_END_INDEX, regValue));
+        result.add(new ActionNxResubmit(actionKeyStart, NwConstants.EGRESS_TUNNEL_TABLE));
+
+        return Futures.immediateFuture(new GetEgressActionsForTunnelOutputBuilder()
+                .setAction(result.stream().map(ActionInfo::buildAction).collect(Collectors.toList())).build());
     }
 
     public static List<DcGatewayIp> getDcGatewayIpList(TypedReadWriteTransaction<Datastore.Configuration> tx)
index e36a5fd22017ccc12a5c4d64e25d96db5760a320..4908e4b61cb2e392ce2a571ad7ed957c0a50be5d 100644 (file)
@@ -16,6 +16,7 @@ import com.google.common.util.concurrent.Futures;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import org.junit.After;
 import org.junit.Before;
@@ -32,6 +33,7 @@ import org.opendaylight.genius.itm.confighelpers.ItmInternalTunnelAddWorker;
 import org.opendaylight.genius.itm.globals.ITMConstants;
 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
 import org.opendaylight.infrautils.caches.baseimpl.internal.CacheManagersRegistryImpl;
 import org.opendaylight.infrautils.caches.guava.internal.GuavaCacheProvider;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
@@ -65,6 +67,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnelKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.OperationFailedException;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.powermock.api.mockito.PowerMockito;
@@ -138,9 +141,13 @@ public class ItmInternalTunnelAddTest {
 
     AllocateIdOutput expectedId1 = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("100")).build();
     AllocateIdOutput expectedId2 = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("200")).build();
+    AllocateIdOutput expectedDstID1 = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("1")).build();
+    AllocateIdOutput expectedDstID2 = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("2")).build();
 
     Future<RpcResult<AllocateIdOutput>> idOutputOptional1;
     Future<RpcResult<AllocateIdOutput>> idOutputOptional2;
+    Future<RpcResult<AllocateIdOutput>> dstId1Output;
+    Future<RpcResult<AllocateIdOutput>> dstId2Output;
 
     @Mock DataBroker dataBroker;
     @Mock ReadOnlyTransaction mockReadTx;
@@ -151,6 +158,7 @@ public class ItmInternalTunnelAddTest {
     @Mock ItmConfig itmConfig;
     @Mock JobCoordinator jobCoordinator;
     @Mock IInterfaceManager interfaceManager;
+    @Mock EntityOwnershipUtils entityOwnershipUtils;
     ItmInternalTunnelAddWorker itmInternalTunnelAddWorker;
     DirectTunnelUtils directTunnelUtils;
 
@@ -167,6 +175,8 @@ public class ItmInternalTunnelAddTest {
 
         idOutputOptional1 = RpcResultBuilder.success(expectedId1).buildFuture();
         idOutputOptional2 = RpcResultBuilder.success(expectedId2).buildFuture();
+        dstId1Output = RpcResultBuilder.success(expectedDstID1).buildFuture();
+        dstId2Output = RpcResultBuilder.success(expectedDstID2).buildFuture();
 
         doReturn(Futures.immediateCheckedFuture(tunnelMonitorParamsOptional)).when(mockReadTx)
                 .read(LogicalDatastoreType.CONFIGURATION, tunnelMonitorParamsInstanceIdentifier);
@@ -177,6 +187,7 @@ public class ItmInternalTunnelAddTest {
         doReturn(Futures.immediateCheckedFuture(tunnelMonitorIntervalOptional)).when(mockReadWriteTx)
                 .read(LogicalDatastoreType.CONFIGURATION, tunnelMonitorIntervalIdentifier);
 
+        directTunnelUtils = new DirectTunnelUtils(idManagerService, mdsalApiManager, entityOwnershipUtils, itmConfig);
         itmInternalTunnelAddWorker = new ItmInternalTunnelAddWorker(dataBroker, jobCoordinator,
                 new TunnelMonitoringConfig(dataBroker, new GuavaCacheProvider(new CacheManagersRegistryImpl())),
                 itmConfig, directTunnelUtils, interfaceManager, new OvsBridgeRefEntryCache(dataBroker,
@@ -215,13 +226,13 @@ public class ItmInternalTunnelAddTest {
         tunnelEndPointsListGre.add(tunnelEndPointsGre);
         tunnelEndPointsListGreNew.add(tunnelEndPointsGreNew);
         dpntePsInfoVxlan = new DPNTEPsInfoBuilder().setDPNID(dpId1).setUp(true).withKey(new DPNTEPsInfoKey(dpId1))
-                .setTunnelEndPoints(tunnelEndPointsListVxlan).build();
+                .setTunnelEndPoints(tunnelEndPointsListVxlan).setDstId(dpId1.intValue()).build();
         dpntePsInfoVxlanNew = new DPNTEPsInfoBuilder().setDPNID(dpId2).withKey(new DPNTEPsInfoKey(dpId2)).setUp(true)
-                .setTunnelEndPoints(tunnelEndPointsListVxlanNew).build();
+                .setTunnelEndPoints(tunnelEndPointsListVxlanNew).setDstId(dpId2.intValue()).build();
         dpntePsInfoGre = new DPNTEPsInfoBuilder().setDPNID(dpId1).setUp(true).withKey(new DPNTEPsInfoKey(dpId1))
-                .setTunnelEndPoints(tunnelEndPointsListGre).build();
+                .setTunnelEndPoints(tunnelEndPointsListGre).setDstId(dpId1.intValue()).build();
         dpntePsInfoGreNew = new DPNTEPsInfoBuilder().setDPNID(dpId2).withKey(new DPNTEPsInfoKey(dpId2)).setUp(true)
-                .setTunnelEndPoints(tunnelEndPointsListGreNew).build();
+                .setTunnelEndPoints(tunnelEndPointsListGreNew).setDstId(dpId2.intValue()).build();
         tunnelMonitorParams = new TunnelMonitorParamsBuilder().setEnabled(true)
                 .setMonitorProtocol(monitorProtocol).build();
         tunnelMonitorInterval = new TunnelMonitorIntervalBuilder().setInterval(interval).build();
@@ -236,10 +247,12 @@ public class ItmInternalTunnelAddTest {
         doReturn(mockReadWriteTx).when(dataBroker).newReadWriteTransaction();
         doReturn(Futures.immediateCheckedFuture(null)).when(mockReadWriteTx).submit();
         doReturn(true).when(mockReadWriteTx).cancel();
+
     }
 
     @Test
-    public void testBuild_all_tunnels_VXLANtype() {
+    public void testBuild_all_tunnels_VXLANtype() throws ExecutionException, InterruptedException,
+        OperationFailedException {
 
         AllocateIdInput getIdInput1 = new AllocateIdInputBuilder()
                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
@@ -247,9 +260,15 @@ public class ItmInternalTunnelAddTest {
         AllocateIdInput getIdInput2 = new AllocateIdInputBuilder()
                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
                 .setIdKey("1:phy0:100:192.168.56.102:192.168.56.101:VXLAN").build();
+        AllocateIdInput dstDpID1 = new AllocateIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+                .setIdKey(dpId1.toString()).build();
+        AllocateIdInput dstDpID2 = new AllocateIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+                .setIdKey(dpId2.toString()).build();
 
         doReturn(idOutputOptional1).when(idManagerService).allocateId(getIdInput1);
         doReturn(idOutputOptional2).when(idManagerService).allocateId(getIdInput2);
+        doReturn(dstId1Output).when(idManagerService).allocateId(dstDpID1);
+        doReturn(dstId2Output).when(idManagerService).allocateId(dstDpID2);
 
         trunkInterfaceName1 = ItmUtils.getTrunkInterfaceName(parentInterfaceName,tepIp1,tepIp2,
                 tunnelType1.getName());
@@ -270,7 +289,8 @@ public class ItmInternalTunnelAddTest {
     }
 
     @Test
-    public void testBuild_all_tunnels_GREtype() {
+    public void testBuild_all_tunnels_GREtype() throws ExecutionException, InterruptedException,
+            OperationFailedException {
 
         AllocateIdInput getIdInput1 = new AllocateIdInputBuilder()
                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
@@ -278,6 +298,12 @@ public class ItmInternalTunnelAddTest {
         AllocateIdInput getIdInput2 = new AllocateIdInputBuilder()
                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
                 .setIdKey("1:phy0:100:192.168.56.102:192.168.56.101:GRE").build();
+        AllocateIdInput dstDpID1 = new AllocateIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+                .setIdKey(dpId1.toString()).build();
+        AllocateIdInput dstDpID2 = new AllocateIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+                .setIdKey(dpId2.toString()).build();
+        doReturn(dstId1Output).when(idManagerService).allocateId(dstDpID1);
+        doReturn(dstId2Output).when(idManagerService).allocateId(dstDpID2);
 
         doReturn(idOutputOptional1).when(idManagerService).allocateId(getIdInput1);
         doReturn(idOutputOptional2).when(idManagerService).allocateId(getIdInput2);
@@ -300,7 +326,8 @@ public class ItmInternalTunnelAddTest {
     }
 
     @Test
-    public void testBuild_all_tunnels_Boyhtype() {
+    public void testBuild_all_tunnels_Boyhtype() throws ExecutionException, InterruptedException,
+            OperationFailedException {
 
         AllocateIdInput getIdInput1 = new AllocateIdInputBuilder()
                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
@@ -308,9 +335,16 @@ public class ItmInternalTunnelAddTest {
         AllocateIdInput getIdInput2 = new AllocateIdInputBuilder()
                 .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
                 .setIdKey("1:phy0:100:192.168.56.102:192.168.56.101:GRE").build();
+        AllocateIdInput dstDpID1 = new AllocateIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+                .setIdKey(dpId1.toString()).build();
+        AllocateIdInput dstDpID2 = new AllocateIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+                .setIdKey(dpId2.toString()).build();
 
         doReturn(idOutputOptional1).when(idManagerService).allocateId(getIdInput1);
         doReturn(idOutputOptional2).when(idManagerService).allocateId(getIdInput2);
+        doReturn(dstId1Output).when(idManagerService).allocateId(dstDpID1);
+        doReturn(dstId2Output).when(idManagerService).allocateId(dstDpID2);
+
 
         trunkInterfaceName1 = ItmUtils.getTrunkInterfaceName(parentInterfaceName,tepIp1,tepIp2,
                 tunnelType1.getName());