Bug 5617: OfOverlay Refactoring - Destination mapper 56/36256/14
authorVladimir Lavor <vlavor@cisco.com>
Mon, 21 Mar 2016 14:04:52 +0000 (15:04 +0100)
committerVladimir Lavor <vlavor@cisco.com>
Wed, 6 Apr 2016 08:15:11 +0000 (10:15 +0200)
Signed-off-by: Vladimir Lavor <vlavor@cisco.com>
Change-Id: I7e1ac58b066f8eda1a5c989d1980459ee22a1960

28 files changed:
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/endpoint/EndpointManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowTable.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OrdinalFactory.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperFlows.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperUtils.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/external/ExternalMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/ingressnat/IngressNatMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/ingressnat/IngressNatMapperFlows.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/source/SourceMapper.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapperTest.java [deleted file]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowTableTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/GroupTableTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/MapperUtilsTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperFlowsTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperUtilsTest.java [new file with mode: 0644]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/egressnat/EgressNatMapperFlowsTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/egressnat/EgressNatMapperTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/external/ExternalMapperTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/ingressnat/IngressNatMapperFlowsTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/ingressnat/IngressNatMapperTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/policyenforcer/PolicyEnforcerTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/portsecurity/PortSecurityFlowsTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/portsecurity/PortSecurityTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/source/SourceMapperFlowsTest.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/source/SourceMapperTest.java

index 81bc50c2be10d86733b6aff4ba62889944896279..aa8124b72803dbcf914c4d1dd5f1f30c6463ba67 100755 (executable)
@@ -38,8 +38,10 @@ import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.SetUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointFields;
@@ -640,6 +642,27 @@ public class EndpointManager implements AutoCloseable {
         return endpoints.getEndpointL3();
     }
 
+    /**
+     * Reads L2 endpoint from data store using appropriate {@link EndpointL3}
+     *
+     * @return {@link EndpointL3} if exists, otherwise null
+     */
+    public Endpoint getL2EndpointFromL3(EndpointL3 endpointL3) {
+        if(endpointL3 != null) {
+            L2BridgeDomainId l2Context = endpointL3.getL2Context();
+            MacAddress macAddress = endpointL3.getMacAddress();
+            if (l2Context == null || macAddress == null) {
+                LOG.debug("[L2Context: {}, MacAddress: {}] Cannot read endpoint from DS unless both keys are specified!",
+                        l2Context, macAddress);
+                return null;
+            }
+            EpKey l2EndpointKey = new EpKey(l2Context, macAddress);
+            return endpoints.get(l2EndpointKey);
+        }
+
+        return null;
+    }
+
     /**
      * Reads endpointL3 from data store
      * @param l3c id of {@link L3Context}
index fadcc6e325d3a0627d7184997270fc47fcb38acc..743c519cd0010514b2fe3ca07f750971d3584300 100755 (executable)
@@ -8,14 +8,13 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
-
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -82,5 +81,4 @@ public abstract class FlowTable extends OfTable {
         flowb.setId(flowid);
         return flowb.build();
     }
-
 }
index 53e4717691d56710f8faa69b83dfeb2f21e4228f..4ae1d3e6f3f4987c7a5091acc13cd1d5e1e1953e 100755 (executable)
@@ -794,4 +794,24 @@ public final class FlowUtils {
                 .setHardTimeout(0)
                 .setIdleTimeout(0);
     }
+
+    /**
+     * Convert string value to byte array
+     *
+     * @param values input value as a (@link String)
+     * @return byte representation of input data
+     */
+    public static byte[] bytesFromHexString(String values) {
+        String target = "";
+        if (values != null) {
+            target = values;
+        }
+        String[] octets = target.split(":");
+
+        byte[] ret = new byte[octets.length];
+        for (int i = 0; i < octets.length; i++) {
+            ret[i] = Integer.valueOf(octets[i], 16).byteValue();
+        }
+        return ret;
+    }
 }
index 9d5ad4f5128f11002bd674e17612e883a5011969..2658b6850041e8aea2cf2e678eae4bd638c633ba 100755 (executable)
@@ -55,9 +55,8 @@ public class OrdinalFactory {
      * @param tenantId the tenant id
      * @param id a unique id
      * @return the ordinal
-     * @throws Exception throws all exception
      */
-    public static int getContextOrdinal(final TenantId tenantId, final UniqueId id) throws Exception {
+    public static int getContextOrdinal(final TenantId tenantId, final UniqueId id) {
         if (tenantId == null || id == null)
             return 0;
         return getContextOrdinalFromString(tenantId.getValue() + "|" + id.getValue());
@@ -98,7 +97,7 @@ public class OrdinalFactory {
         return getContextOrdinalFromString(destNode.getValue());
     }
 
-    public static int getContextOrdinal(Endpoint ep, NetworkDomainId networkContainment) throws Exception {
+    public static int getContextOrdinal(Endpoint ep, NetworkDomainId networkContainment) {
 
         Set<String> epgs = new TreeSet<>();
 
@@ -125,7 +124,7 @@ public class OrdinalFactory {
 
     }
 
-    public static int getContextOrdinal(Endpoint ep) throws Exception {
+    public static int getContextOrdinal(Endpoint ep) {
 
         Set<String> epgs = new TreeSet<>();
 
@@ -158,7 +157,7 @@ public class OrdinalFactory {
      *        the unique ID for the element
      * @return the 32-bit ordinal value
      */
-    private static int getContextOrdinalFromString(final String id) throws Exception {
+    private static int getContextOrdinalFromString(final String id) {
 
         Integer ord = ordinals.get(id);
         if (ord == null) {
@@ -171,7 +170,7 @@ public class OrdinalFactory {
     }
 
     public static final EndpointFwdCtxOrdinals getEndpointFwdCtxOrdinals(OfContext ctx,
-            Endpoint ep) throws Exception {
+            Endpoint ep) {
         IndexedTenant tenant = ctx.getTenant(ep.getTenant());
         if (tenant == null) {
             LOG.debug("Tenant {} is null", ep.getTenant());
@@ -187,7 +186,7 @@ public class OrdinalFactory {
         private EpKey ep;
         private int epgId = 0, bdId = 0, fdId = 0, l3Id = 0, cgId = 0, tunnelId = 0;
 
-        private EndpointFwdCtxOrdinals(Endpoint ep, OfContext ctx) throws Exception {
+        private EndpointFwdCtxOrdinals(Endpoint ep, OfContext ctx) {
             this.ep = new EpKey(ep.getL2Context(), ep.getMacAddress());
 
             IndexedTenant tenant = ctx.getTenant(ep.getTenant());
@@ -269,6 +268,7 @@ public class OrdinalFactory {
     }
 
     @VisibleForTesting
+    // Used only for unit testing
     public static void resetPolicyOrdinalValue() {
         policyOrdinal.set(1);
     }
index c613359b3f34141e17c57d5a3fe03d3e7fea4cf1..5597a1a1ccd53e932b29c46e979c924042c3cb74 100755 (executable)
@@ -8,98 +8,36 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ARP;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.IPv4;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.IPv6;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.decNwTtlAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ethernetMatch;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.getOfPortNum;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.groupAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpOpAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpShaAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpSpaAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveArpShaToArpThaAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveArpSpaToArpTpaAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveEthSrcToEthDstAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlDstAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlSrcAction;
-import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
 import org.opendaylight.groupbasedpolicy.dto.EgKey;
 import org.opendaylight.groupbasedpolicy.dto.EpKey;
 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowIdUtils;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
-import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.groupbasedpolicy.util.TenantUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
@@ -107,15 +45,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
 
 /**
  * <h1>Manage the table that maps the destination address to the next hop for the
@@ -144,10 +85,11 @@ import com.google.common.collect.Sets;
  * L3 flows:
  * <p>
  * <i>External, local and remote L3 routed flows:</i><br>
- * Priority = 50<br>
+ * Priority = 132<br>
  * Matches:<br>
  *      - ip (ethertype)
  *      - dl_dst mac address {@link MacAddress}<br>
+ *      - nw_dst ip address {@link IpAddress}<br>
  *      - setReg6 {@link NxmNxReg6}<br>
  * Actions:<br>
  *      - loadReg2 {@link NxmNxReg2}<br>
@@ -202,1303 +144,355 @@ import com.google.common.collect.Sets;
  */
 public class DestinationMapper extends FlowTable {
 
-    protected static final Logger LOG = LoggerFactory.getLogger(DestinationMapper.class);
+    private static final Logger LOG = LoggerFactory.getLogger(DestinationMapper.class);
 
-    // TODO Li alagalah: Improve UT coverage for this class.
+    private final DestinationMapperUtils utils;
+    private final short tableId;
 
-    // TODO Li alagalah: Use EndpointL3 for L3 flows, Endpoint for L2 flows
-    // This ensures we have the appropriate network-containment'
+    final Map<TenantId, HashSet<Subnet>> subnetsByTenant = new HashMap<>();
 
-    public static short TABLE_ID;
-    /**
-     * This is the MAC address of the magical router in the sky
-     */
+    // This is the MAC address of the magical router in the sky
     public static final MacAddress ROUTER_MAC = new MacAddress("88:f0:31:b5:12:b5");
-    public static final MacAddress MULTICAST_MAC = new MacAddress("01:00:00:00:00:00");
-    public static final Integer BASE_L3_PRIORITY = 100;
+    private static final MacAddress MULTICAST_MAC = new MacAddress("01:00:00:00:00:00");
+    private static final int EXTERNAL_L2 = 50;
+    private static final int LOCAL_L2 = 50;
+    private static final int L3_PREFIX = 100;
+    private static final int L3_LOCAL = 132;
+    private static final int L3_EXTERNAL = 132;
+    private static final int ROUTER_ARP = 150;
+    private static final int REMOTE_L2 = 50;
+    private static final int REMOTE_L3 = 132;
+    // Priorities
+    private static final int DROP_FLOW = 1;
+    private static final int BROADCAST = 140;
 
     public DestinationMapper(OfContext ctx, short tableId) {
         super(ctx);
-        this.TABLE_ID = tableId;
+        this.tableId = tableId;
+        utils = new DestinationMapperUtils(ctx);
     }
 
-    Map<TenantId, HashSet<Subnet>> subnetsByTenant = new HashMap<TenantId, HashSet<Subnet>>();
-
     @Override
     public short getTableId() {
-        return TABLE_ID;
+        return tableId;
     }
 
     @Override
     public void sync(Endpoint endpoint, OfWriter ofWriter) throws Exception {
+        NodeId endpointNodeId = ctx.getEndpointManager().getEndpointNodeId(endpoint);
+        if (endpointNodeId == null) {
+            LOG.warn("Endpoint {} has no location specified, skipped", endpoint);
+            return;
+        }
+        DestinationMapperFlows flows = new DestinationMapperFlows(utils, endpointNodeId, tableId);
 
-        // TODO: only temporary workaround, use src & dst endpoint in implementation
-        NodeId nodeId = ctx.getEndpointManager().getEndpointNodeId(endpoint);
+        // Do sync
+        syncFlows(flows, endpoint, endpointNodeId, ofWriter);
+    }
 
-        TenantId currentTenant = null;
+    @VisibleForTesting
+    void syncFlows(DestinationMapperFlows flows, Endpoint endpoint, NodeId nodeId, OfWriter ofWriter) {
 
-        ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
+        // Create basic drop flow
+        flows.dropFlow(DROP_FLOW, null, ofWriter);
 
-        SetMultimap<EpKey, EpKey> visitedEps = HashMultimap.create();
-        Set<EndpointFwdCtxOrdinals> epOrdSet = new HashSet<>();
+        // Sync flows related to endpoints
+        List<Subnet> localSubnets = utils.getLocalSubnets(nodeId);
+        if (localSubnets != null) {
+            // Local
+            syncLocalFlows(flows, endpoint, localSubnets, ofWriter);
+            // Remote & external
+            syncEndpointFlows(flows, nodeId, endpoint, ofWriter);
+        }
 
-        for (Endpoint srcEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
-            Set<EndpointGroupId> srcEpgIds = new HashSet<>();
-            if (srcEp.getEndpointGroup() != null)
-                srcEpgIds.add(srcEp.getEndpointGroup());
-            if (srcEp.getEndpointGroups() != null)
-                srcEpgIds.addAll(srcEp.getEndpointGroups());
+        // Sync router ARP flow
+        TenantId tenantId = endpoint.getTenant();
+        syncArpFlow(flows, tenantId, ofWriter);
 
-            for (EndpointGroupId epgId : srcEpgIds) {
-                EgKey epg = new EgKey(srcEp.getTenant(), epgId);
-                Set<EgKey> peers = Sets.union(Collections.singleton(epg), ctx.getCurrentPolicy().getPeers(epg));
-                for (EgKey peer : peers) {
-                    Collection<Endpoint> endpointsForGroup = new HashSet<>();
-                    endpointsForGroup.addAll(ctx.getEndpointManager().getEndpointsForGroup(peer));
-                    endpointsForGroup.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(peer));
-                    for (Endpoint peerEp : endpointsForGroup) {
-                        currentTenant = peerEp.getTenant();
-                        subnetsByTenant.put(currentTenant, getSubnets(currentTenant));
-                        EpKey srcEpKey = new EpKey(srcEp.getL2Context(), srcEp.getMacAddress());
-                        EpKey peerEpKey = new EpKey(peerEp.getL2Context(), peerEp.getMacAddress());
+        // Create broadcast flow
+        EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
+        if (ordinals != null) {
+            flows.createBroadcastFlow(BROADCAST, ordinals, MULTICAST_MAC, ofWriter);
+        }
 
-                        if (visitedEps.get(srcEpKey) != null && visitedEps.get(srcEpKey).contains(peerEpKey)) {
-                            continue;
-                        }
-                        syncEP(ofWriter, nodeId, srcEp, peerEp);
-                        visitedEps.put(srcEpKey, peerEpKey);
+        // L3 Prefix Endpoint handling
+        Collection<EndpointL3Prefix> prefixes = ctx.getEndpointManager().getEndpointsL3PrefixForTenant(tenantId);
+        if (prefixes != null) {
+            LOG.trace("DestinationMapper - Processing L3PrefixEndpoint");
+            syncL3PrefixFlow(flows, prefixes, tenantId, nodeId, ofWriter);
+        }
+    }
 
-                        // Process subnets and flood-domains for epPeer
-                        EndpointFwdCtxOrdinals epOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx,
-                                peerEp);
-                        if (epOrds == null) {
-                            LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", peerEp);
-                            continue;
-                        }
+    @VisibleForTesting
+    void syncEndpointFlows(DestinationMapperFlows flows, NodeId nodeId, Endpoint endpoint, OfWriter ofWriter) {
+        SetMultimap<EpKey, EpKey> visited = HashMultimap.create();
+        Set<EndpointGroupId> groupIds = utils.getAllEndpointGroups(endpoint);
+        for (EndpointGroupId groupId : groupIds) {
+            EgKey groupKey = new EgKey(endpoint.getTenant(), groupId);
+            Set<EgKey> peers = Sets.union(Collections.singleton(groupKey),
+                    ctx.getCurrentPolicy().getPeers(groupKey));
+            for (EgKey peer : peers) {
+                Collection<Endpoint> endpointsForGroup = new HashSet<>();
+                endpointsForGroup.addAll(ctx.getEndpointManager().getEndpointsForGroup(peer));
+                endpointsForGroup.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(peer));
+                for (Endpoint peerEndpoint : endpointsForGroup) {
+                    subnetsByTenant.put(peerEndpoint.getTenant(), utils.getSubnets(endpoint.getTenant()));
+                    EpKey epKey = new EpKey(endpoint.getL2Context(), endpoint.getMacAddress());
+                    EpKey peerEpKey = new EpKey(peerEndpoint.getL2Context(), peerEndpoint.getMacAddress());
+                    if (visited.get(epKey) != null && visited.get(epKey).contains(peerEpKey)) {
+                        continue;
+                    }
+                    // Basic checks
+                    IndexedTenant endpointTenant = utils.getIndexedTenant(endpoint.getTenant());
+                    IndexedTenant peerTenant = utils.getIndexedTenant(peerEndpoint.getTenant());
+                    if (endpointTenant == null || peerTenant == null) {
+                        LOG.debug("Source or destination endpoint references empty tenant. SrcEp: {} DestEp: {}",
+                                endpointTenant, peerTenant);
+                        continue;
+                    }
+                    EndpointFwdCtxOrdinals endpointOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
+                    EndpointFwdCtxOrdinals peerOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, peerEndpoint);
+                    if (endpointOrdinals == null || peerOrdinals == null) {
+                        LOG.debug("Source od destination endpoint ordinals are null. SrcOrdinals: {} DestOrdinals: {}",
+                                endpointOrdinals, peerOrdinals);
+                        continue;
+                    }
 
-                        epOrdSet.add(epOrds);
+                    if (peerEndpoint.getEndpointGroup() == null && peerEndpoint.getEndpointGroups() == null) {
+                        LOG.debug("Didn't process endpoint {} due to EPG(s) being null", peerEndpoint.getKey());
+                        continue;
                     }
-                }
-            }
-        }
 
-        for (Entry<TenantId, HashSet<Subnet>> subnetEntry : subnetsByTenant.entrySet()) {
-            if (subnetEntry.getValue() == null) {
-                LOG.trace("Tenant: {} has empty subnet entry.", subnetEntry.getKey());
-                continue;
-            }
-            currentTenant = subnetEntry.getKey();
-            for (Subnet sn : subnetEntry.getValue()) {
-                L3Context l3c = getL3ContextForSubnet(currentTenant, sn);
-                Flow arpFlow = createRouterArpFlow(currentTenant, nodeId, sn,
-                        OrdinalFactory.getContextOrdinal(currentTenant, l3c.getId()));
-                if (arpFlow != null) {
-                    ofWriter.writeFlow(nodeId, TABLE_ID, arpFlow);
-                } else {
-                    LOG.debug(
-                            "Gateway ARP flow is not created, because virtual router IP has not been set for subnet {} .",
-                            sn.getIpPrefix().getValue());
-                }
-            }
-        }
+                    List<Subnet> localSubnets = utils.getLocalSubnets(nodeId);
+                    if (localSubnets == null) {
+                        LOG.error("No subnets could be found locally for node: {}", nodeId);
+                        continue;
+                    }
+                    OfOverlayContext peerContext = peerEndpoint.getAugmentation(OfOverlayContext.class);
+                    Subnet epSubnet = endpointTenant.resolveSubnet(new SubnetId(endpoint.getNetworkContainment()));
+                    Endpoint l2GatewayEp = utils.getL2EpOfSubnetGateway(endpoint.getTenant(), epSubnet);
+                    boolean peerEpIsExternal = peerEndpoint.getNetworkContainment() != null
+                            && EndpointManager.isExternal(peerEndpoint, peerTenant.getExternalImplicitGroups());
+                    boolean subnetGwIsExternal = l2GatewayEp != null && EndpointManager.isExternal(l2GatewayEp,
+                            utils.getIndexedTenant(endpoint.getTenant()).getExternalImplicitGroups());
+                    // Sync external
+                    if (peerEpIsExternal || subnetGwIsExternal) {
+                        Set<NodeConnectorId> externalPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
+                        syncExternalFlows(flows, endpoint, peerEndpoint, l2GatewayEp, externalPorts, ofWriter);
+                    // Sync remote
+                    } else if (peerContext != null && !Objects.equals(peerContext.getNodeId(), nodeId)) {
+                        syncRemoteFlows(flows, endpoint, peerEndpoint, peerContext, nodeId, endpointOrdinals, peerOrdinals, localSubnets, ofWriter);
+                    }
 
-        // Write broadcast flows per flood domain.
-        for (EndpointFwdCtxOrdinals epOrd : epOrdSet) {
-            if (ofWriter.groupExists(nodeId, Integer.valueOf(epOrd.getFdId()).longValue())) {
-                ofWriter.writeFlow(nodeId, TABLE_ID, createBroadcastFlow(epOrd));
+                    visited.put(epKey, peerEpKey);
+                }
             }
         }
+    }
 
-        // L3 Prefix Endpoint handling
-        Collection<EndpointL3Prefix> prefixEps = ctx.getEndpointManager().getEndpointsL3PrefixForTenant(currentTenant);
-        if (prefixEps != null) {
-            LOG.trace("DestinationMapper - Processing L3PrefixEndpoints");
-            for (EndpointL3Prefix prefixEp : prefixEps) {
-                List<Subnet> localSubnets = getLocalSubnets(nodeId);
-                if (localSubnets == null) {
+    @VisibleForTesting
+    void syncArpFlow(DestinationMapperFlows flows, TenantId tenantId, OfWriter ofWriter) {
+        for (Entry<TenantId, HashSet<Subnet>> subnetEntry : subnetsByTenant.entrySet()) {
+            for (Subnet subnet : subnetEntry.getValue()) {
+                IndexedTenant tenant = ctx.getTenant(tenantId);
+                L3Context l3Context = utils.getL3ContextForSubnet(tenant, subnet);
+                if (subnet == null || subnet.getVirtualRouterIp() == null) {
+                    LOG.trace("Arp flow not created, subnet or its virtual router is null. Subnet Id: {}", subnet);
                     continue;
                 }
-                for (Subnet localSubnet: localSubnets) {
-                    Flow prefixFlow = createL3PrefixFlow(prefixEp, nodeId, localSubnet);
-                    if (prefixFlow != null) {
-                        ofWriter.writeFlow(nodeId, TABLE_ID, prefixFlow);
-                        LOG.trace("Wrote L3Prefix flow");
+                try {
+                    if (l3Context != null && l3Context.getId() != null && tenant != null) {
+                        flows.createRouterArpFlow(ROUTER_ARP, tenant, subnet, ofWriter);
                     }
+                } catch (Exception e) {
+                    LOG.error("Failed to get context ordinal from tenant Id {} and L3 Context Id {}", tenantId,
+                            l3Context.getId());
                 }
             }
         }
     }
 
-
-
-    // set up next-hop destinations for all the endpoints in the endpoint
-    // group on the node
-
-    private Flow createL3PrefixFlow(EndpointL3Prefix prefixEp, NodeId nodeId, Subnet subnet) throws Exception {
-        /*
-         * Priority: 100+lengthprefix
-         * Match: prefix, l3c, "mac address of router" ?
-         * Action:
-         * - set Reg2, Reg3 for L3Ep by L2Ep ?
-         * - if external,
-         * - Reg7: use switch location external port else punt for now
-         * - if internal
-         * - Reg7: grab L2Ep from L3Ep and use its location info
-         * - goto_table: POLENF (will check there for external on EP)
-         */
-
-        ReadOnlyTransaction rTx = ctx.getDataBroker().newReadOnlyTransaction();
-        // TODO Bug #3440 Target: Be - should support for more than first gateway.
-        EndpointL3Gateways l3Gateway = prefixEp.getEndpointL3Gateways().get(0);
-        Optional<EndpointL3> optL3Ep = readFromDs(LogicalDatastoreType.OPERATIONAL,
-                IidFactory.l3EndpointIid(l3Gateway.getL3Context(), l3Gateway.getIpAddress()), rTx);
-        if (!optL3Ep.isPresent()) {
-            LOG.error("createL3PrefixFlow - L3Endpoint gateway {} for L3Prefix {} not found.", l3Gateway, prefixEp);
-            return null;
-        }
-        EndpointL3 l3Ep = optL3Ep.get();
-        if (l3Ep.getL2Context() == null || l3Ep.getMacAddress() == null) {
-            LOG.debug("L3 endpoint representing L3 gateway does not contain L2-context or MAC address. {}", l3Ep);
-            return null;
-        }
-        Optional<Endpoint> optL2Ep = readFromDs(LogicalDatastoreType.OPERATIONAL,
-                IidFactory.endpointIid(l3Ep.getL2Context(), l3Ep.getMacAddress()), rTx);
-        if (!optL2Ep.isPresent()) {
-            LOG.error("createL3PrefixFlow - L2Endpoint for L3Gateway {} not found.", l3Ep);
-            return null;
-        }
-        Endpoint l2Ep = optL2Ep.get();
-        EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, l2Ep);
-        if (epFwdCtxOrds == null) {
-            LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", l2Ep);
-            return null;
-        }
-
-        NetworkDomainId epNetworkContainment = getEPNetworkContainment(l2Ep);
-
-        MacAddress epDestMac = l2Ep.getMacAddress();
-        MacAddress destSubnetGatewayMac = l2Ep.getMacAddress();
-        L3Context destL3c = getL3ContextForSubnet(prefixEp.getTenant(), subnet);
-        if (destL3c == null || destL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", subnet.getId());
-            return null;
-        }
-
-        MacAddress matcherMac = routerPortMac(destL3c, subnet.getVirtualRouterIp());
-
-        ArrayList<Instruction> l3instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-        List<Action> l3ApplyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
-        Action setNextHop;
-        String nextHop=null;
-
-        OfOverlayContext ofc = l2Ep.getAugmentation(OfOverlayContext.class);
-
-        long portNum = -1;
-        if (EndpointManager.isInternal(l2Ep, ctx.getTenant(l2Ep.getTenant()).getExternalImplicitGroups())) {
-            checkNotNull(ofc.getNodeConnectorId());
-            nextHop = ofc.getNodeConnectorId().getValue();
-            try {
-                portNum = getOfPortNum(ofc.getNodeConnectorId());
-            } catch (NumberFormatException ex) {
-                LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
-                return null;
-            }
-
-        } else {
-            // External
-            Set<NodeConnectorId> externalPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
-            checkNotNull(externalPorts);
-            for (NodeConnectorId externalPort : externalPorts) {
-                // TODO Bug #3440 Target: Be - should support for more than first external port.
-                //TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
-                nextHop = externalPort.getValue();
-                try {
-                    portNum = getOfPortNum(externalPort);
-                } catch (NumberFormatException ex) {
-                    LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
-                    return null;
+    @VisibleForTesting
+    void syncL3PrefixFlow(DestinationMapperFlows flows, Collection<EndpointL3Prefix> l3Prefixes,
+                                  TenantId tenantId, NodeId nodeId, OfWriter ofWriter) {
+        short policyEnforcerTableId = ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER();
+        for (EndpointL3Prefix l3Prefix : l3Prefixes) {
+            List<Subnet> localSubnets = utils.getLocalSubnets(nodeId);
+            if (localSubnets != null) {
+                for (Subnet localSubnet : localSubnets) {
+                    for (EndpointL3Gateways l3Gateway : l3Prefix.getEndpointL3Gateways()) {
+                        if (l3Gateway != null && l3Gateway.getL3Context() != null && l3Gateway.getIpAddress() != null) {
+                            EndpointL3 endpointL3 = ctx.getEndpointManager().getL3Endpoint(l3Gateway.getL3Context(),
+                                    l3Gateway.getIpAddress(), tenantId);
+                            Endpoint endpointL2 = ctx.getEndpointManager().getL2EndpointFromL3(endpointL3);
+                            IndexedTenant tenant = ctx.getTenant(l3Prefix.getTenant());
+                            Set<NodeConnectorId> externalPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
+                            if (endpointL3 != null && endpointL2 != null && tenant != null && externalPorts != null) {
+                                L3Context l3Context = utils.getL3ContextForSubnet(tenant, localSubnet);
+                                if (l3Context == null || l3Context.getId() == null) {
+                                    LOG.error("No L3 Context found associated with subnet {}", localSubnet.getId());
+                                    continue;
+                                }
+                                EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpointL2);
+                                if (ordinals == null) {
+                                    LOG.error("No Fwd Ctx ordinals found in endpoint ", endpointL2);
+                                    continue;
+                                }
+                                flows.createL3PrefixFlow(policyEnforcerTableId, L3_PREFIX, endpointL2, l3Prefix, tenant,
+                                        localSubnet, externalPorts, ofWriter);
+                            }
+                        }
+                    }
                 }
-                continue;
             }
         }
-
-        if (Strings.isNullOrEmpty(nextHop)
-                || portNum == -1) {
-            LOG.error("createL3Prefix - Cannot find nodeConnectorId for {} for Prefix: ", l2Ep, prefixEp);
-            return null;
-        }
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-
-        Action setDlDst = setDlDstAction(epDestMac);
-        l3ApplyActions.add(setDlDst);
-
-        Action decTtl = decNwTtlAction();
-        l3ApplyActions.add(decTtl);
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-
-        applyActions.addAll(l3ApplyActions);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-
-        l3instructions.add(applyActionsIns);
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        l3instructions.add(gotoTable);
-
-        Layer3Match m = null;
-        Long etherType = null;
-        String ikey = null;
-        Integer prefixLength=0;
-        if (prefixEp.getIpPrefix().getIpv4Prefix() != null) {
-            ikey = prefixEp.getIpPrefix().getIpv4Prefix().getValue();
-            etherType = IPv4;
-            prefixLength=Integer.valueOf(prefixEp.getIpPrefix().getIpv4Prefix().getValue().split("/")[1]);
-            m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
-        } else if (prefixEp.getIpPrefix().getIpv6Prefix() != null) {
-            ikey = prefixEp.getIpPrefix().getIpv6Prefix().getValue();
-            etherType = IPv6;
-            /*
-             *  This will result in flows with priority between 100-228, but since its matching on IPv6 prefix as well
-             *  this shouldn't pose and issue, as the priority is more important within the address space of the matcher,
-             *  even though technically flows are processed in priority order.
-             */
-
-            prefixLength=Integer.valueOf(prefixEp.getIpPrefix().getIpv6Prefix().getValue().split("/")[1]);
-            m = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
-        } else {
-            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", prefixEp);
-            return null;
-        }
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType));
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(epFwdCtxOrds.getL3Id())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "L3prefix", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(BASE_L3_PRIORITY+prefixLength))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
-        return flowb.build();
-    }
-
-    private Flow createBroadcastFlow(EndpointFwdCtxOrdinals epOrd) {
-        MatchBuilder mb = new MatchBuilder()
-                .setEthernetMatch(new EthernetMatchBuilder().setEthernetDestination(
-                        new EthernetDestinationBuilder().setAddress(MULTICAST_MAC)
-                                .setMask(MULTICAST_MAC)
-                                .build()).build());
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class, Long.valueOf(epOrd.getFdId())));
-
-        Match match = mb.build();
-        FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "broadcast", match);
-        FlowBuilder flowb = base().setPriority(Integer.valueOf(140))
-            .setId(flowId)
-            .setMatch(match)
-            .setInstructions(
-                    instructions(applyActionIns(nxLoadTunIdAction(BigInteger.valueOf(epOrd.getFdId()), false),
-                            groupAction(Long.valueOf(epOrd.getFdId())))));
-
-        return flowb.build();
     }
 
-    private MacAddress routerPortMac(L3Context l3c, IpAddress ipAddress) {
-
-        if (ctx.getDataBroker() == null) {
-            return null;
+    private void syncExternalFlows(DestinationMapperFlows flows, Endpoint endpoint, Endpoint peerEndpoint,
+                                   Endpoint gatewayEndpoint, Set<NodeConnectorId> externalPorts, OfWriter ofWriter) {
+        EndpointFwdCtxOrdinals peerOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, peerEndpoint);
+        if (peerOrdinals == null) {
+            return;
         }
-
-        MacAddress defaultMacAddress = ROUTER_MAC;
-
-        EndpointL3Key l3Key = new EndpointL3Key(ipAddress, l3c.getId());
-        InstanceIdentifier<EndpointL3> endpointsIid = InstanceIdentifier.builder(Endpoints.class)
-            .child(EndpointL3.class, l3Key)
-            .build();
-        ReadOnlyTransaction t = ctx.getDataBroker().newReadOnlyTransaction();
-
-        Optional<EndpointL3> r;
-        try {
-            r = t.read(LogicalDatastoreType.OPERATIONAL, endpointsIid).get();
-            if (!r.isPresent())
-                return defaultMacAddress;
-            EndpointL3 epL3 = r.get();
-            if (epL3.getMacAddress() == null) {
-                return defaultMacAddress;
-            } else {
-                return epL3.getMacAddress();
+        short goToTable = ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER();
+        if (endpoint.getNetworkContainment().equals(peerEndpoint.getNetworkContainment())) {
+            if (externalPorts.iterator().hasNext()) {
+                // L2 flow
+                flows.createExternalL2Flow(goToTable, EXTERNAL_L2, peerEndpoint, externalPorts, ofWriter);
             }
-        } catch (Exception e) {
-            LOG.error("Error reading EndpointL3 {}.{}", l3c, ipAddress, e);
-            return null;
-        }
-    }
-
-    private L3Context getL3ContextForSubnet(TenantId tenantId, Subnet sn) {
-        IndexedTenant indexedTenant = ctx.getTenant(tenantId);
-        if (indexedTenant == null) {
-            LOG.debug("Tenant {} is null, cannot get L3 context", tenantId);
-            return null;
-        }
-        L3Context l3c = indexedTenant.resolveL3Context(sn.getId());
-        return l3c;
-    }
-
-    private Flow createRouterArpFlow(TenantId tenantId, NodeId nodeId, Subnet sn, int l3Id) {
-        if (sn == null || sn.getVirtualRouterIp() == null) {
-            LOG.trace("Didn't create routerArpFlow since either subnet or subnet virtual router was null");
-            return null;
-        }
-        /*
-         * TODO: Li alagalah: This should be new Yang "gateways" list as well,
-         * that expresses the gateway and prefixes it is interface for. Should
-         * also check for external.
-         */
-        if (sn.getVirtualRouterIp().getIpv4Address() != null) {
-            String ikey = sn.getVirtualRouterIp().getIpv4Address().getValue();
-
-            L3Context l3c = getL3ContextForSubnet(tenantId, sn);
-            if (l3c == null) {
-                LOG.error("No L3 Context found associated with subnet {}", sn.getId());
+        } else if (gatewayEndpoint != null) {
+            HashSet<Subnet> subnets = utils.getSubnets(peerEndpoint.getTenant());
+            if (subnets == null) {
+                LOG.trace("No subnets in tenant {}", peerEndpoint.getTenant());
+                return;
             }
-
-            MacAddress routerMac = routerPortMac(l3c, sn.getVirtualRouterIp());
-            if (routerMac == null) {
-                return null;
+            for (L3Address l3Address : endpoint.getL3Address()) {
+                if (l3Address.getIpAddress() == null || l3Address.getL3Context() == null) {
+                    LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",
+                            endpoint.getL3Address());
+                    continue;
+                }
+                // L3 flow
+                flows.createExternalL3RoutedFlow(goToTable, L3_EXTERNAL, peerEndpoint, gatewayEndpoint, l3Address,
+                            externalPorts, ofWriter);
             }
-
-            BigInteger intRouterMac = new BigInteger(1, bytesFromHexString(routerMac.getValue()));
-
-            MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, ARP)).setLayer3Match(
-                    new ArpMatchBuilder().setArpOp(Integer.valueOf(1))
-                        .setArpTargetTransportAddress(new Ipv4Prefix(ikey + "/32"))
-                        .build());
-            addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(l3Id)));
-
-            Match match = mb.build();
-            FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "routerarp", match);
-            FlowBuilder flowb = base().setPriority(150)
-                .setId(flowId)
-                .setMatch(match)
-                .setInstructions(
-                        instructions(applyActionIns(nxMoveEthSrcToEthDstAction(), setDlSrcAction(routerMac),
-                                nxLoadArpOpAction(BigInteger.valueOf(2L)), nxMoveArpShaToArpThaAction(),
-                                nxLoadArpShaAction(intRouterMac), nxMoveArpSpaToArpTpaAction(),
-                                nxLoadArpSpaAction(ikey), outputAction(new NodeConnectorId(nodeId.getValue()
-                                        + ":INPORT")))));
-            return flowb.build();
-        } else {
-            LOG.warn("IPv6 virtual router {} for subnet {} not supported", sn.getVirtualRouterIp(), sn.getId()
-                .getValue());
-            return null;
-        }
-
-    }
-
-    private Flow createLocalL2Flow(Endpoint ep, EndpointFwdCtxOrdinals epFwdCtxOrds, OfOverlayContext ofc) {
-
-        // TODO Li alagalah - refactor common code but keep simple method
-        ArrayList<Instruction> instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
-        Action setNextHop;
-        String nextHop;
-
-        // BEGIN L2 LOCAL
-        nextHop = ofc.getNodeConnectorId().getValue();
-
-        long portNum;
-        try {
-            portNum = getOfPortNum(ofc.getNodeConnectorId());
-        } catch (NumberFormatException ex) {
-            LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
-            return null;
         }
-
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-
-        // END L2 LOCAL
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-        instructions.add(applyActionsIns);
-
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        instructions.add(gotoTable);
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, ep.getMacAddress(), null));
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(epFwdCtxOrds.getBdId())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "localL2", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(50))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(instructions).build());
-        return flowb.build();
     }
 
-    private void syncEP(OfWriter ofWriter, NodeId nodeId, Endpoint srcEp, Endpoint destEp)
-            throws Exception {
-
-        if (ctx.getTenant(srcEp.getTenant()) == null
-                || ctx.getTenant(destEp.getTenant()) == null) {
-            LOG.debug("Source or destination EP references empty tenant srcEp:{} destEp:{}", srcEp, destEp);
-            return;
-        }
-
-        // TODO: Conditions messed up, but for now, send policyInfo until this
-        // is fixed.
-        EndpointFwdCtxOrdinals destEpFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, destEp);
-        if (destEpFwdCtxOrds == null) {
-            LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", destEp);
-            return;
-        }
-        EndpointFwdCtxOrdinals srcEpFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, srcEp);
-        if (srcEpFwdCtxOrds == null) {
-            LOG.debug("getEndpointFwdCtxOrdinals is null for EP {}", srcEp);
+    private void syncLocalFlows(DestinationMapperFlows flows, Endpoint endpoint, List<Subnet> localSubnets,
+                                OfWriter ofWriter) {
+        short goToTable = ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER();
+        // L2 Flow
+        flows.createLocalL2Flow(goToTable, LOCAL_L2, endpoint, ofWriter);
+        if (endpoint.getL3Address() == null) {
+            LOG.trace("Endpoint {} didn't have L3 Address so was not processed for L3 flows.", endpoint.getKey());
             return;
         }
-
-
-        if (destEp.getTenant() == null || (destEp.getEndpointGroup() == null && destEp.getEndpointGroups() == null)) {
-            if (destEp.getTenant() == null) {
-                LOG.debug("Didn't process endpoint {} due to tenant being null", destEp.getKey());
+        for (L3Address l3Address : endpoint.getL3Address()) {
+            if (l3Address.getIpAddress() == null || l3Address.getL3Context() == null) {
+                LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",
+                        endpoint.getL3Address());
             } else {
-                LOG.debug("Didn't process endpoint {} due to EPG(s) being null", destEp.getKey());
-            }
-            return;
-        }
-
-        /*
-         * Only care about subnets for L3, but fetch them before loop. We need
-         * the local subnets for setting SRC MAC for routing. All Routing is now
-         * done locally! YAY! Instead of being shovelled L2 style across network
-         * ala Helium.
-         */
-        List<Subnet> localSubnets = getLocalSubnets(nodeId);
-        if (localSubnets == null) {
-            LOG.error("No subnets could be found locally for node: {}", nodeId);
-            return;
-        }
-
-        OfOverlayContext ofc = destEp.getAugmentation(OfOverlayContext.class);
-
-        // forwarding outside of internal domain should be done when dest EP or GW is external.
-        Subnet srcSubnet = ctx.getTenant(srcEp.getTenant()).resolveSubnet(new SubnetId(srcEp.getNetworkContainment()));
-        Endpoint l2Gw = this.getL2EndpointOfSubnetGateway(srcEp.getTenant(), srcSubnet);
-        boolean destEpIsExternal = destEp.getNetworkContainment() != null
-                && EndpointManager.isExternal(destEp, ctx.getTenant(destEp.getTenant()).getExternalImplicitGroups());
-        boolean subnetGwIsExternal = l2Gw != null
-                && EndpointManager.isExternal(l2Gw, ctx.getTenant(l2Gw.getTenant()).getExternalImplicitGroups());
-        if (destEpIsExternal || subnetGwIsExternal) {
-            if (ofc == null && destEp.getNetworkContainment().equals(srcEp.getNetworkContainment())) {
-                Flow flow = createExternalL2Flow(destEp, destEpFwdCtxOrds, nodeId);
-                if (flow != null) {
-                    ofWriter.writeFlow(nodeId, TABLE_ID, flow);
-                }
-            } else if (l2Gw != null && EndpointManager.isExternal(l2Gw, ctx.getTenant(l2Gw.getTenant()).getExternalImplicitGroups())
-                    && !destEp.getNetworkContainment().equals(srcEp.getNetworkContainment())) {
-                for (L3Address l3a : destEp.getL3Address()) {
-                    if (l3a.getIpAddress() == null || l3a.getL3Context() == null) {
-                        LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",
-                                destEp.getL3Address());
+                for (Subnet localSubnet : localSubnets) {
+                    HashSet<Subnet> subnets = utils.getSubnets(endpoint.getTenant());
+                    if (subnets == null) {
+                        LOG.trace("No subnets in tenant {}", utils.getIndexedTenant(endpoint.getTenant()));
                         continue;
                     }
-                    for (Subnet localSubnet : localSubnets) {
-                        Flow extL3Flow = createExternalL3RoutedFlow(destEp, l3a, destEpFwdCtxOrds, localSubnet, nodeId);
-                        if (extL3Flow != null) {
-                            ofWriter.writeFlow(nodeId, TABLE_ID, extL3Flow);
-                        } else {
-                            LOG.trace("Did not write remote L3 flow for endpoint {} and subnet {}", l3a.getIpAddress(),
-                                    localSubnet.getIpPrefix().getValue());
-                        }
+                    Subnet remoteSubnet = ctx.getTenant(endpoint.getTenant())
+                            .resolveSubnet(new SubnetId(endpoint.getNetworkContainment()));
+                    // Do check
+                    if(checked(localSubnet, remoteSubnet, l3Address, endpoint)) {
+                        // L3 flow
+                        flows.createLocalL3RoutedFlow(goToTable, L3_LOCAL, endpoint, l3Address, localSubnet, remoteSubnet,
+                                ofWriter);
                     }
                 }
             }
         }
-        else if (ofc != null && Objects.equals(ofc.getNodeId(), nodeId)) {
-            // this is a local endpoint; send to the approppriate local
-            // port
-
-            if (srcEpFwdCtxOrds.getBdId() == destEpFwdCtxOrds.getBdId()) {
-                ofWriter.writeFlow(nodeId, TABLE_ID, createLocalL2Flow(destEp, destEpFwdCtxOrds, ofc));
-            }
-            // TODO Li alagalah: Need to move to EndpointL3 for L3 processing.
-            // The Endpoint conflation must end!
-            if (destEp.getL3Address() == null) {
-                LOG.trace("Endpoint {} didn't have L3 Address so was not processed for L3 flows.", destEp.getKey());
-                return;
-            }
-
-            for (L3Address l3a : destEp.getL3Address()) {
-                if (l3a.getIpAddress() == null || l3a.getL3Context() == null) {
-                    LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",
-                            destEp.getL3Address());
-                    continue;
-                } else {
-                    for (Subnet localSubnet : localSubnets) {
-                        Flow flow = createLocalL3RoutedFlow(destEp, l3a, destEpFwdCtxOrds, ofc, localSubnet);
-                        if (flow != null) {
-                            ofWriter.writeFlow(nodeId, TABLE_ID, flow);
-                        } else {
-                            LOG.trace("Did not write remote L3 flow for endpoint {} and subnet {}", l3a.getIpAddress(),
-                                    localSubnet.getIpPrefix().getValue());
-                        }
-                    }
-                }
-            }
-        } else if(ofc!= null) {
-            // this endpoint is on a different switch; send to the
-            // appropriate tunnel
-            if (srcEpFwdCtxOrds.getBdId() == destEpFwdCtxOrds.getBdId()) {
-                Flow remoteL2Flow = createRemoteL2Flow(destEp, nodeId, srcEpFwdCtxOrds, destEpFwdCtxOrds, ofc);
-                if (remoteL2Flow != null) {
-                    ofWriter.writeFlow(nodeId, TABLE_ID, remoteL2Flow);
-                }
-            } else {
-                LOG.trace("DestinationMapper: RemoteL2Flow: not created, in different BDs src: {} dst: {}",
-                        srcEpFwdCtxOrds.getBdId(), destEpFwdCtxOrds.getBdId());
-            }
-
-            // TODO Li alagalah: Need to move to EndpointL3 for L3 processing.
-            // The Endpoint conflation must end!
-            if (destEp.getL3Address() == null) {
-                LOG.trace("Endpoint {} didn't have L3 Address so was not processed for L3 flows.", destEp.getKey());
-                return;
-            }
-            for (L3Address l3a : destEp.getL3Address()) {
-                if (l3a.getIpAddress() == null || l3a.getL3Context() == null) {
-                    LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",
-                            destEp.getL3Address());
-                    continue;
-                } else {
-                    for (Subnet localSubnet : localSubnets) {
-                        Flow remoteL3Flow = createRemoteL3RoutedFlow(destEp, l3a, nodeId, srcEpFwdCtxOrds,
-                                destEpFwdCtxOrds, ofc, localSubnet);
-                        if (remoteL3Flow != null) {
-                            ofWriter.writeFlow(nodeId, TABLE_ID, remoteL3Flow);
-                        } else {
-                            LOG.trace("Did not write remote L3 flow for endpoint {} and subnet {}", l3a.getIpAddress(),
-                                    localSubnet.getIpPrefix().getValue());
-                        }
-                    }
-                }
-            }
-        } // remote (tunnel)
-
-        // }
-
     }
 
-    /*
-     * ################################## DestMapper Flow methods
-     * ##################################
-     */
-    private Flow createLocalL3RoutedFlow(Endpoint destEp, L3Address destL3Address, EndpointFwdCtxOrdinals epFwdCtxOrds,
-            OfOverlayContext ofc, Subnet srcSubnet) {
-
-        // TODO Li alagalah - refactor common code but keep simple method
-
-        Subnet destSubnet = null;
-        HashSet<Subnet> subnets = getSubnets(destEp.getTenant());
-        if (subnets == null) {
-            LOG.trace("No subnets in tenant {}", destEp.getTenant());
-            return null;
-        }
-        NetworkDomainId epNetworkContainment = getEPNetworkContainment(destEp);
-        for (Subnet subnet : subnets) {
-            // TODO Li alagalah add IPv6 support
-            if (subnet.getId().getValue().equals(epNetworkContainment.getValue())) {
-                destSubnet = subnet;
-                break;
+    private void syncRemoteFlows(DestinationMapperFlows flows, Endpoint endpoint, Endpoint peerEndpoint, OfOverlayContext ofc,
+                                 NodeId nodeId, EndpointFwdCtxOrdinals endpointOrdinals,
+                                 EndpointFwdCtxOrdinals peerOrdinals, List<Subnet> localSubnets, OfWriter ofWriter) {
+        short goToTable = ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER();
+        if (endpointOrdinals.getBdId() == peerOrdinals.getBdId()) {
+            IpAddress tunDst = ctx.getSwitchManager().getTunnelIP(ofc.getNodeId(), TunnelTypeVxlan.class);
+            NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
+            // L2 flow
+            if (tunDst != null && tunPort != null) {
+                flows.createRemoteL2Flow(goToTable, REMOTE_L2, endpoint, peerEndpoint, tunDst, tunPort, ofWriter);
             }
-        }
-        if (destSubnet == null) {
-            LOG.trace("Destination IP address does not match any subnet in tenant {}", destL3Address.getIpAddress());
-            return null;
-        }
-
-        if (destSubnet.getVirtualRouterIp() == null) {
-            LOG.trace("Destination subnet {} for Endpoint {}.{} has no gateway IP", destSubnet.getIpPrefix(),
-                    destL3Address.getKey());
-            return null;
-        }
-
-        if (srcSubnet.getVirtualRouterIp() == null) {
-            LOG.trace("Local subnet {} has no gateway IP", srcSubnet.getIpPrefix());
-            return null;
-        }
-        L3Context destL3c = getL3ContextForSubnet(destEp.getTenant(), destSubnet);
-        if (destL3c == null || destL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", destSubnet.getId());
-            return null;
-        }
-        L3Context srcL3c = getL3ContextForSubnet(destEp.getTenant(), srcSubnet);
-        if (srcL3c == null || srcL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", srcSubnet.getId());
-            return null;
-        }
-
-        if (!(srcL3c.getId().getValue().equals(destL3c.getId().getValue()))) {
-            LOG.trace("Trying to route between two L3Contexts {} and {}. Not currently supported.", srcL3c.getId()
-                .getValue(), destL3c.getId().getValue());
-            return null;
-        }
-
-        MacAddress matcherMac = routerPortMac(destL3c, srcSubnet.getVirtualRouterIp());
-        MacAddress epDestMac = destEp.getMacAddress();
-        MacAddress destSubnetGatewayMac = routerPortMac(destL3c, destSubnet.getVirtualRouterIp());
-
-        if (srcSubnet.getId().getValue().equals(destSubnet.getId().getValue())) {
-            // This is our final destination, so match on actual EP mac.
-            matcherMac = epDestMac;
-        }
-
-        ArrayList<Instruction> l3instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-        List<Action> l3ApplyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
-        Action setNextHop;
-        String nextHop;
-
-        // BEGIN L3 LOCAL
-        nextHop = ofc.getNodeConnectorId().getValue();
-
-        long portNum;
-        try {
-            portNum = getOfPortNum(ofc.getNodeConnectorId());
-        } catch (NumberFormatException ex) {
-            LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
-            return null;
-        }
-
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-        // END L3 LOCAL
-
-        // Lets not re-write the srcMac if its local.
-        if (!(matcherMac.getValue().equals(epDestMac.getValue()))) {
-            Action setDlSrc = setDlSrcAction(destSubnetGatewayMac);
-            l3ApplyActions.add(setDlSrc);
-        }
-
-        Action setDlDst = setDlDstAction(epDestMac);
-        l3ApplyActions.add(setDlDst);
-
-        Action decTtl = decNwTtlAction();
-        l3ApplyActions.add(decTtl);
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-
-        applyActions.addAll(l3ApplyActions);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-
-        l3instructions.add(applyActionsIns);
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        l3instructions.add(gotoTable);
-        Layer3Match m = null;
-        Long etherType = null;
-        String ikey = null;
-        if (destL3Address.getIpAddress().getIpv4Address() != null) {
-            ikey = destL3Address.getIpAddress().getIpv4Address().getValue() + "/32";
-            etherType = IPv4;
-            m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
-        } else if (destL3Address.getIpAddress().getIpv6Address() != null) {
-            ikey = destL3Address.getIpAddress().getIpv6Address().getValue() + "/128";
-            etherType = IPv6;
-            m = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
         } else {
-            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", destL3Address.toString());
-            return null;
+            LOG.trace("DestinationMapper: RemoteL2Flow: not created, in different BDs src: {} dst: {}",
+                    endpointOrdinals.getBdId(), peerOrdinals.getBdId());
         }
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
-            .setLayer3Match(m);
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(epFwdCtxOrds.getL3Id())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "localL3", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(132))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
-        return flowb.build();
-    }
-
-    private Flow createExternalL3RoutedFlow(Endpoint destEp, L3Address destL3Address, EndpointFwdCtxOrdinals epFwdCtxOrds,
-            Subnet srcSubnet, NodeId nodeId) {
-
-        Subnet destSubnet = null;
-        HashSet<Subnet> subnets = getSubnets(destEp.getTenant());
-        if (subnets == null) {
-            LOG.trace("No subnets in tenant {}", destEp.getTenant());
-            return null;
-        }
-        NetworkDomainId epNetworkContainment = getEPNetworkContainment(destEp);
-        for (Subnet subnet : subnets) {
-            // TODO Li alagalah add IPv6 support
-            if (subnet.getId().getValue().equals(epNetworkContainment.getValue())) {
-                destSubnet = subnet;
-                break;
-            }
-        }
-        if (destSubnet == null) {
-            LOG.trace("Destination IP address does not match any subnet in tenant {}", destL3Address.getIpAddress());
-            return null;
-        }
-
-        if (destSubnet.getVirtualRouterIp() == null) {
-            LOG.trace("Destination subnet {} for Endpoint {}.{} has no gateway IP", destSubnet.getIpPrefix(),
-                    destL3Address.getKey());
-            return null;
-        }
-
-        if (srcSubnet.getVirtualRouterIp() == null) {
-            LOG.trace("Local subnet {} has no gateway IP", srcSubnet.getIpPrefix());
-            return null;
-        }
-        L3Context destL3c = getL3ContextForSubnet(destEp.getTenant(), destSubnet);
-        if (destL3c == null || destL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", destSubnet.getId());
-            return null;
-        }
-        L3Context srcL3c = getL3ContextForSubnet(destEp.getTenant(), srcSubnet);
-        if (srcL3c == null || srcL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", srcSubnet.getId());
-            return null;
-        }
-
-        if (!(srcL3c.getId().getValue().equals(destL3c.getId().getValue()))) {
-            LOG.trace("Trying to route between two L3Contexts {} and {}. Not currently supported.", srcL3c.getId()
-                .getValue(), destL3c.getId().getValue());
-            return null;
-        }
-
-        Endpoint l2Gw = getL2EndpointOfSubnetGateway(destEp.getTenant(), srcSubnet);
-        if(l2Gw == null) {
-            LOG.warn("The endpoint representing external gateway of subnet {} not found", srcSubnet);
-            return null;
-        }
-        MacAddress matcherMac = destEp.getMacAddress();
-        MacAddress destSubnetGatewayMac = l2Gw.getMacAddress();
-
-        ArrayList<Instruction> l3instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-        List<Action> l3ApplyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
-        Action setNextHop;
-
-        Set<NodeConnectorId> extPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
-        if (extPorts == null || !extPorts.iterator().hasNext()) {
-            LOG.warn("No external interface on node: {}. External Gateway {} is not reachable!", nodeId, l2Gw.getKey());
-            return null;
-        }
-        // only one external port is supported for now
-         NodeConnectorId extPort = extPorts.iterator().next();
-
-        long portNum;
-        try {
-            portNum = getOfPortNum(extPort);
-        } catch (NumberFormatException ex) {
-            LOG.warn("Could not parse port number {}", extPort, ex);
-            return null;
-        }
-
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-        // END L3 LOCAL
-
-
-        Action setDlSrc = setDlSrcAction(destSubnetGatewayMac);
-        l3ApplyActions.add(setDlSrc);
-
-        Action setDlDst = setDlDstAction(l2Gw.getMacAddress());
-        l3ApplyActions.add(setDlDst);
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-
-        applyActions.addAll(l3ApplyActions);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-
-        l3instructions.add(applyActionsIns);
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        l3instructions.add(gotoTable);
-        Layer3Match m = null;
-        Long etherType = null;
-        String ikey = null;
-        if (destL3Address.getIpAddress().getIpv4Address() != null) {
-            ikey = destL3Address.getIpAddress().getIpv4Address().getValue() + "/32";
-            etherType = IPv4;
-            m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
-        } else if (destL3Address.getIpAddress().getIpv6Address() != null) {
-            ikey = destL3Address.getIpAddress().getIpv6Address().getValue() + "/128";
-            etherType = IPv6;
-            m = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
-        } else {
-            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", destL3Address.toString());
-            return null;
+        if (peerEndpoint.getL3Address() == null) {
+            LOG.trace("Endpoint {} didn't have L3 Address so was not processed for L3 flows.", peerEndpoint.getKey());
+            return;
         }
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
-            .setLayer3Match(m);
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(epFwdCtxOrds.getL3Id())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "externalL3", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(132))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
-        return flowb.build();
-    }
-
-    private Endpoint getL2EndpointOfSubnetGateway(TenantId tenantId, Subnet subnet) {
-        if (subnet != null && subnet.getVirtualRouterIp() != null) {
-            IpAddress gwIpAddress = subnet.getVirtualRouterIp();
-            Collection<EndpointL3Prefix> prefixEps = ctx.getEndpointManager().getEndpointsL3PrefixForTenant(tenantId);
-            if (prefixEps != null) {
-                for (EndpointL3Prefix prefixEp : prefixEps) {
-                    for (EndpointL3Gateways gw : prefixEp.getEndpointL3Gateways()) {
-                        EndpointL3 l3Ep = ctx.getEndpointManager().getL3Endpoint(gw.getL3Context(), gwIpAddress,
-                                prefixEp.getTenant());
-                        if (l3Ep != null && l3Ep.getL2Context() != null && l3Ep.getMacAddress() != null) {
-                            return ctx.getEndpointManager().getEndpoint(
-                                    new EpKey(l3Ep.getL2Context(), l3Ep.getMacAddress()));
+        for (L3Address l3Address : peerEndpoint.getL3Address()) {
+            if (l3Address.getIpAddress() == null || l3Address.getL3Context() == null) {
+                LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",
+                        peerEndpoint.getL3Address());
+            } else {
+                for (Subnet localSubnet : localSubnets) {
+                    HashSet<Subnet> subnets = utils.getSubnets(peerEndpoint.getTenant());
+                    if (subnets == null) {
+                        LOG.trace("No subnets in tenant {}", peerEndpoint.getTenant());
+                        return;
+                    }
+                    Subnet remoteSubnet = ctx.getTenant(peerEndpoint.getTenant())
+                            .resolveSubnet(new SubnetId(peerEndpoint.getNetworkContainment()));
+                    // Do check
+                    if(checked(localSubnet, remoteSubnet, l3Address, peerEndpoint)) {
+                        IpAddress tunDst = ctx.getSwitchManager().getTunnelIP(ofc.getNodeId(), TunnelTypeVxlan.class);
+                        NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
+                        // L3 flow
+                        if (tunDst != null && tunPort != null) {
+                            flows.createRemoteL3RoutedFlow(goToTable, REMOTE_L3, peerEndpoint, l3Address, remoteSubnet, tunDst,
+                                    tunPort, localSubnet, ofWriter);
                         }
                     }
                 }
             }
         }
-        return null;
     }
 
-    private Flow createRemoteL2Flow(Endpoint ep, NodeId nodeId, EndpointFwdCtxOrdinals srcEpFwdCtxOrds,
-            EndpointFwdCtxOrdinals destEpFwdCtxOrds, OfOverlayContext ofc) {
-
-        // TODO Li alagalah - refactor common code but keep simple method
-
-        // this endpoint is on a different switch; send to the
-        // appropriate tunnel
-
-        ArrayList<Instruction> instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(destEpFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(destEpFwdCtxOrds.getCgId()));
-        Action setNextHop;
-        String nextHop;
-
-        // BEGIN TUNNEL HANDLING
-        IpAddress tunDst = ctx.getSwitchManager().getTunnelIP(ofc.getNodeId(), TunnelTypeVxlan.class);
-        NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
-        if (tunDst == null) {
-            LOG.warn("Failed to get Tunnel IP for NodeId {} with EP {}", nodeId, ep);
-            return null;
-        }
-        if (tunPort == null) {
-            LOG.warn("Failed to get Tunnel Port for NodeId {} with EP {}", nodeId, ep);
-            return null;
-        }
-
-        Action tundstAction;
-
-        if (tunDst.getIpv4Address() != null) {
-            nextHop = tunDst.getIpv4Address().getValue();
-            tundstAction = nxLoadTunIPv4Action(nextHop, false);
-        } else if (tunDst.getIpv6Address() != null) {
-            // nextHop = tunDst.getIpv6Address().getValue();
-            LOG.error("IPv6 tunnel destination {} for {} not supported", tunDst.getIpv6Address().getValue(),
-                    ofc.getNodeId());
-            return null;
-        } else {
-            // this shouldn't happen
-            LOG.error("Tunnel IP for {} invalid", ofc.getNodeId());
-            return null;
-        }
-
-        long portNum;
-        try {
-            portNum = getOfPortNum(tunPort);
-        } catch (NumberFormatException ex) {
-            LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
-            return null;
-        }
-
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-        applyActions.add(tundstAction);
-        // END TUNNEL
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-        instructions.add(applyActionsIns);
-
-        applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        instructions.add(gotoTable);
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, ep.getMacAddress(), null));
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(destEpFwdCtxOrds.getBdId())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "remoteL2", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(50))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(instructions).build());
-
-        return flowb.build();
-    }
-
-    private Flow createExternalL2Flow(Endpoint ep, EndpointFwdCtxOrdinals epFwdCtxOrds,NodeId nodeId) {
-
-        ArrayList<Instruction> instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
-        Action setNextHop;
-
-        // BEGIN L2 LOCAL
-        Set<NodeConnectorId> extPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
-        if(extPorts == null || !extPorts.iterator().hasNext()) {
-            return null;
-        }
-        // Only one external port is currently supported.
-        NodeConnectorId extPort = extPorts.iterator().next();
-        long portNum;
-        try {
-            portNum = getOfPortNum(extPort);
-        } catch (NumberFormatException ex) {
-            LOG.warn("Could not parse port number {}", extPort, ex);
-            return null;
+    private boolean checked(Subnet localSubnet, Subnet remoteSubnet, L3Address l3Address, Endpoint peerEndpoint) {
+        if(peerEndpoint.getTenant() == null) {
+            LOG.trace("Endpoint {} does not contain info about tenant", peerEndpoint.getKey());
+            return false;
         }
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-
-        // END L2 LOCAL
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-        instructions.add(applyActionsIns);
-
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        instructions.add(gotoTable);
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, ep.getMacAddress(), null));
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(epFwdCtxOrds.getBdId())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "externalL2", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(50))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(instructions).build());
-        return flowb.build();
-    }
-
-    private Flow createRemoteL3RoutedFlow(Endpoint destEp, L3Address destL3Address, NodeId nodeId,
-            EndpointFwdCtxOrdinals srcEpFwdCtxOrds, EndpointFwdCtxOrdinals destEpFwdCtxOrds, OfOverlayContext ofc,
-            Subnet srcSubnet) {
-
-        // TODO Li alagalah - refactor common code but keep simple method
-
-        // this endpoint is on a different switch; send to the
-        // appropriate tunnel
-        Subnet destSubnet = null;
-        HashSet<Subnet> subnets = getSubnets(destEp.getTenant());
-        if (subnets == null) {
-            LOG.trace("No subnets in tenant {}", destEp.getTenant());
-            return null;
-        }
-        NetworkDomainId epNetworkContainment = getEPNetworkContainment(destEp);
-        for (Subnet subnet : subnets) {
-            // TODO Li alagalah add IPv6 support
-            if (subnet.getId().getValue().equals(epNetworkContainment.getValue())) {
-                destSubnet = subnet;
-                break;
-            }
-        }
-        if (destSubnet == null) {
-            LOG.info("Destination IP address does not match any subnet in tenant {}", destL3Address.getIpAddress());
-            return null;
+        if (remoteSubnet == null) {
+            LOG.trace("Destination IP address does not match any subnet in tenant {}",
+                    l3Address.getIpAddress());
+            return false;
         }
-
-        if (destSubnet.getVirtualRouterIp() == null) {
-            LOG.trace("Destination subnet {} for Endpoint {}.{} has no gateway IP", destSubnet.getIpPrefix(),
-                    destL3Address.getKey());
-            return null;
+        if (remoteSubnet.getVirtualRouterIp() == null) {
+            LOG.trace("Destination subnet {} for Endpoint {}.{} has no gateway IP",
+                    remoteSubnet.getIpPrefix(), peerEndpoint, l3Address.getKey());
+            return false;
         }
-
-        if (srcSubnet.getVirtualRouterIp() == null) {
-            LOG.trace("Local subnet {} has no gateway IP", srcSubnet.getIpPrefix());
-            return null;
+        if (localSubnet.getVirtualRouterIp() == null) {
+            LOG.trace("Local subnet {} has no gateway IP", localSubnet.getIpPrefix());
+            return false;
         }
-        L3Context destL3c = getL3ContextForSubnet(destEp.getTenant(), destSubnet);
+        L3Context destL3c = utils.getL3ContextForSubnet(ctx.getTenant(peerEndpoint.getTenant()), remoteSubnet);
         if (destL3c == null || destL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", destSubnet.getId());
-            return null;
+            LOG.error("No L3 Context found associated with subnet {}", remoteSubnet.getId());
+            return false;
         }
-        L3Context srcL3c = getL3ContextForSubnet(destEp.getTenant(), srcSubnet);
+        L3Context srcL3c = utils.getL3ContextForSubnet(ctx.getTenant(peerEndpoint.getTenant()), localSubnet);
         if (srcL3c == null || srcL3c.getId() == null) {
-            LOG.error("No L3 Context found associated with subnet {}", srcSubnet.getId());
-            return null;
+            LOG.error("No L3 Context found associated with subnet {}", localSubnet.getId());
+            return false;
         }
-
         if (!(srcL3c.getId().getValue().equals(destL3c.getId().getValue()))) {
             LOG.trace("Trying to route between two L3Contexts {} and {}. Not currently supported.", srcL3c.getId()
-                .getValue(), destL3c.getId().getValue());
-            return null;
-        }
-
-        MacAddress matcherMac = routerPortMac(destL3c, srcSubnet.getVirtualRouterIp());
-        MacAddress epDestMac = destEp.getMacAddress();
-        MacAddress destSubnetGatewayMac = routerPortMac(destL3c, destSubnet.getVirtualRouterIp());
-        if (srcSubnet.getId().getValue().equals(destSubnet.getId().getValue())) {
-            // This is our final destination, so match on actual EP mac.
-            matcherMac = epDestMac;
-        }
-        ArrayList<Instruction> l3instructions = new ArrayList<>();
-        List<Action> applyActions = new ArrayList<>();
-        List<Action> l3ApplyActions = new ArrayList<>();
-
-        int order = 0;
-
-        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(destEpFwdCtxOrds.getEpgId()));
-        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(destEpFwdCtxOrds.getCgId()));
-        Action setNextHop;
-        String nextHop;
-
-        // BEGIN TUNNEL HANDLING
-        IpAddress tunDst = ctx.getSwitchManager().getTunnelIP(ofc.getNodeId(), TunnelTypeVxlan.class);
-        NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
-        if (tunDst == null) {
-            LOG.warn("Failed to get Tunnel IP for NodeId {} with L3Address {}", nodeId, destL3Address);
-            return null;
-        }
-        if (tunPort == null) {
-            LOG.warn("Failed to get Tunnel port for NodeId {} with L3Address {}", nodeId, destL3Address);
-            return null;
-        }
-
-        Action tundstAction;
-
-        if (tunDst.getIpv4Address() != null) {
-            nextHop = tunDst.getIpv4Address().getValue();
-            tundstAction = nxLoadTunIPv4Action(nextHop, false);
-        } else if (tunDst.getIpv6Address() != null) {
-            // nextHop = tunDst.getIpv6Address().getValue();
-            LOG.error("IPv6 tunnel destination {} for {} not supported", tunDst.getIpv6Address().getValue(),
-                    ofc.getNodeId());
-            return null;
-        } else {
-            // this shouldn't happen
-            LOG.error("Tunnel IP for {} invalid", ofc.getNodeId());
-            return null;
-        }
-
-        long portNum;
-        try {
-            portNum = getOfPortNum(tunPort);
-        } catch (NumberFormatException ex) {
-            LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
-            return null;
-        }
-
-        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
-        applyActions.add(tundstAction);
-        // END TUNNEL
-
-        order += 1;
-        applyActions.add(setdEPG);
-        applyActions.add(setdCG);
-        applyActions.add(setNextHop);
-
-        // Lets not re-write the srcMac if its local.
-        if (!(matcherMac.getValue().equals(epDestMac.getValue()))) {
-            Action setDlSrc = setDlSrcAction(destSubnetGatewayMac);
-            l3ApplyActions.add(setDlSrc);
-        }
-
-        Action setDlDst = setDlDstAction(epDestMac);
-        l3ApplyActions.add(setDlDst);
-
-        Action decTtl = decNwTtlAction();
-        l3ApplyActions.add(decTtl);
-
-        applyActions.addAll(l3ApplyActions);
-        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-
-        l3instructions.add(applyActionsIns);
-        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
-            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
-            .build();
-        l3instructions.add(gotoTable);
-        Layer3Match m = null;
-        Long etherType = null;
-        String ikey = null;
-        if (destL3Address.getIpAddress().getIpv4Address() != null) {
-            ikey = destL3Address.getIpAddress().getIpv4Address().getValue() + "/32";
-            etherType = IPv4;
-            m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
-        } else if (destL3Address.getIpAddress().getIpv6Address() != null) {
-            ikey = destL3Address.getIpAddress().getIpv6Address().getValue() + "/128";
-            etherType = IPv6;
-            m = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
-        } else {
-            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", destL3Address.toString());
-            return null;
-        }
-
-        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
-            .setLayer3Match(m);
-        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(destEpFwdCtxOrds.getL3Id())));
-        Match match = mb.build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "remoteL3", match);
-        FlowBuilder flowb = base().setId(flowid)
-            .setPriority(Integer.valueOf(132))
-            .setMatch(match)
-            .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
-        return flowb.build();
-    }
-
-    private NetworkDomainId getEPNetworkContainment(Endpoint endpoint) {
-        if (endpoint.getNetworkContainment() != null) {
-            return endpoint.getNetworkContainment();
-        } else {
-            /*
-             * TODO: Be alagalah: Endpoint Refactor: This should be set on input
-             * which we can't do because of the backwards way endpoints were
-             * "architected".
-             */
-            return ctx.getTenant(endpoint.getTenant())
-                .getEndpointGroup(endpoint.getEndpointGroup())
-                .getNetworkDomain();
-        }
-    }
-
-    private HashSet<Subnet> getSubnets(final TenantId tenantId) {
-
-        if (ctx.getDataBroker() == null) {
-            return null;
-        }
-
-        ReadOnlyTransaction t = ctx.getDataBroker().newReadOnlyTransaction();
-        InstanceIdentifier<Tenant> tiid = TenantUtils.tenantIid(tenantId);
-        Optional<Tenant> tenantInfo;
-        try {
-            tenantInfo = t.read(LogicalDatastoreType.CONFIGURATION, tiid).get();
-        } catch (Exception e) {
-            LOG.error("Could not read Tenant {}", tenantId, e);
-            return null;
-        } finally {
-            t.close();
-        }
-
-        if (!tenantInfo.isPresent()) {
-            LOG.warn("Tenant {} not found", tenantId);
-            return null;
-        }
-
-        ForwardingContext fwCtx = tenantInfo.get().getForwardingContext();
-        if (fwCtx == null || fwCtx.getSubnet() == null) {
-            return new HashSet<>();
-        }
-        return new HashSet<>(fwCtx.getSubnet());
-    }
-
-    // Need a method to get subnets for EPs attached to the node locally
-    // to set the source Mac address for the router interface.
-    private List<Subnet> getLocalSubnets(NodeId nodeId) {
-        Collection<Endpoint> endpointsForNode = ctx.getEndpointManager().getEndpointsForNode(nodeId);
-
-        List<Subnet> localSubnets = new ArrayList<Subnet>();
-
-        for (Endpoint endpoint : endpointsForNode) {
-            HashSet<Subnet> subnets = getSubnets(endpoint.getTenant());
-            if (subnets == null) {
-                LOG.debug("No local subnets in tenant {} for EP {}.", endpoint.getTenant(), endpoint.getKey());
-                continue;
-            }
-            NetworkDomainId epNetworkContainment = getEPNetworkContainment(endpoint);
-            for (Subnet subnet : subnets) {
-                if (epNetworkContainment.getValue().equals(subnet.getId().getValue())) {
-                    localSubnets.add(subnet);
-                }
-            }
-        }
-        return localSubnets;
-    }
-
-    public static byte[] bytesFromHexString(String values) {
-        String target = "";
-        if (values != null) {
-            target = values;
-        }
-        String[] octets = target.split(":");
-
-        byte[] ret = new byte[octets.length];
-        for (int i = 0; i < octets.length; i++) {
-            ret[i] = Integer.valueOf(octets[i], 16).byteValue();
+                    .getValue(), destL3c.getId().getValue());
+            return false;
         }
-        return ret;
+        return true;
     }
 }
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperFlows.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperFlows.java
new file mode 100644 (file)
index 0000000..b7cea0f
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowIdUtils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
+class DestinationMapperFlows {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DestinationMapperFlows.class);
+    private final DestinationMapperUtils utils;
+    private final NodeId nodeId;
+    private final short tableId;
+
+    public DestinationMapperFlows(DestinationMapperUtils utils, NodeId nodeId, short tableId) {
+        this.utils = Preconditions.checkNotNull(utils);
+        this.nodeId = Preconditions.checkNotNull(nodeId);
+        this.tableId = tableId;
+    }
+
+    /**
+     * Default flow which drops all incoming traffic
+     *
+     * @param priority  of flow in the table
+     * @param etherType can be set as specific protocol to match
+     * @param ofWriter  flow writer
+     */
+    void dropFlow(int priority, Long etherType, OfWriter ofWriter) {
+        FlowId flowId;
+        FlowBuilder flowBuilder = FlowUtils.base(tableId)
+                .setPriority(priority)
+                .setInstructions(FlowUtils.dropInstructions());
+        if (etherType != null) {
+            MatchBuilder matchBuilder = new MatchBuilder()
+                    .setEthernetMatch(FlowUtils.ethernetMatch(null, null, etherType));
+            Match match = matchBuilder.build();
+            flowId = FlowIdUtils.newFlowId(tableId, "drop", match);
+            flowBuilder.setMatch(match);
+        } else {
+            flowId = FlowIdUtils.newFlowId("dropAll");
+        }
+        flowBuilder.setId(flowId);
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    /**
+     * Create external L2 flow for every external port found on node
+     *
+     * @param goToTable     {@link GoToTable} instruction value
+     * @param priority      of the flow
+     * @param peerEndpoint  original endpoint (input parameter to {@link DestinationMapper#sync(Endpoint, OfWriter)}
+     * @param externalPorts list of external {@link NodeConnectorId}-s get from node
+     * @param ofWriter      flow writer
+     */
+    void createExternalL2Flow(short goToTable, int priority, Endpoint peerEndpoint, Set<NodeConnectorId> externalPorts,
+                              OfWriter ofWriter) {
+        OrdinalFactory.EndpointFwdCtxOrdinals peerOrdinals = utils.getEndpointOrdinals(peerEndpoint);
+        if (peerOrdinals != null) {
+            MatchBuilder matchBuilder = new MatchBuilder()
+                    .setEthernetMatch(ethernetMatch(null, peerEndpoint.getMacAddress(), null));
+            addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg4.class, (long) peerOrdinals.getBdId()));
+            Match match = matchBuilder.build();
+
+            long port;
+            for (NodeConnectorId externalPort : externalPorts) {
+                try {
+                    port = getOfPortNum(externalPort);
+                    writeExternalL2Flow(goToTable, priority, peerOrdinals, port, match, ofWriter);
+                } catch (NumberFormatException e) {
+                    LOG.warn("Invalid NodeConnectorId. External port: {}", externalPort);
+                }
+            }
+        }
+    }
+
+    /**
+     * Create external L3 flow for every external port found on node
+     *
+     * @param goToTable     {@link GoToTable} instruction value
+     * @param priority      of the flow
+     * @param peerEndpoint  to original endpoint (input parameter to {@link DestinationMapper#sync(Endpoint, OfWriter)}
+     * @param l2GatewayEp   L2 endpoint of subnet gateway
+     * @param destL3Address endpoint L3 address
+     * @param externalPorts list of external {@link NodeConnectorId}-s get from node
+     * @param ofWriter      flow writer
+     */
+    void createExternalL3RoutedFlow(short goToTable, int priority, Endpoint peerEndpoint, Endpoint l2GatewayEp,
+                                    L3Address destL3Address, Set<NodeConnectorId> externalPorts, OfWriter ofWriter) {
+        OrdinalFactory.EndpointFwdCtxOrdinals peerOrdinals = utils.getEndpointOrdinals(peerEndpoint);
+        if (peerOrdinals != null) {
+            Layer3Match layer3Match;
+            Long etherType;
+            String ikey;
+            if (destL3Address.getIpAddress() != null && destL3Address.getIpAddress().getIpv4Address() != null) {
+                ikey = destL3Address.getIpAddress().getIpv4Address().getValue() + "/32";
+                etherType = IPv4;
+                layer3Match = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
+            } else if (destL3Address.getIpAddress() != null && destL3Address.getIpAddress().getIpv6Address() != null) {
+                ikey = destL3Address.getIpAddress().getIpv6Address().getValue() + "/128";
+                etherType = IPv6;
+                layer3Match = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
+            } else {
+                LOG.error("Endpoint has Ip Address that is not recognised as either IPv4 or IPv6.", destL3Address);
+                return;
+            }
+            MacAddress matcherMac = peerEndpoint.getMacAddress();
+            MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
+                    .setLayer3Match(layer3Match);
+            addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) peerOrdinals.getL3Id()));
+            Match match = matchBuilder.build();
+
+            long port;
+            for (NodeConnectorId externalPort : externalPorts) {
+                try {
+                    port = getOfPortNum(externalPort);
+                    writeExternalL3RoutedFlow(goToTable, priority, port, l2GatewayEp, match, peerOrdinals, ofWriter);
+                } catch (NumberFormatException e) {
+                    LOG.warn("Invalid NodeConnectorId. External port: {}", externalPort);
+                }
+            }
+        }
+    }
+
+    /**
+     * Create local L2 flow
+     *
+     * @param goToTable {@link GoToTable} instruction value
+     * @param priority  of the flow
+     * @param endpoint  original endpoint (input parameter to {@link DestinationMapper#sync(Endpoint, OfWriter)}
+     * @param ofWriter  flow writer
+     */
+    void createLocalL2Flow(short goToTable, int priority, Endpoint endpoint, OfWriter ofWriter) {
+        OfOverlayContext context = endpoint.getAugmentation(OfOverlayContext.class);
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpoint);
+
+        Action setNextHop;
+        try {
+            setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(getOfPortNum(context.getNodeConnectorId())));
+        } catch (NumberFormatException ex) {
+            LOG.warn("Could not parse port number {}", context.getNodeConnectorId(), ex);
+            return;
+        }
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(ordinals.getEpgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(ordinals.getCgId())));
+        applyActions.add(setNextHop);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+
+        ArrayList<Instruction> instructions = new ArrayList<>();
+        instructions.add(applyActionsIns);
+        instructions.add(gotoTable);
+
+        MatchBuilder matchBuilder = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null, endpoint.getMacAddress(), null));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg4.class, (long) ordinals.getBdId()));
+        Match match = matchBuilder.build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "localL2", match);
+        FlowBuilder flowBuilder = base(tableId).setId(flowId)
+                .setPriority(priority)
+                .setMatch(match)
+                .setInstructions(new InstructionsBuilder().setInstruction(instructions).build());
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    /**
+     * Create local L3 routed flow
+     *
+     * @param goToTable   {@link GoToTable} instruction value
+     * @param priority    of the flow
+     * @param endpoint    original endpoint (input parameter to {@link DestinationMapper#sync(Endpoint, OfWriter)}
+     * @param l3Address   endpoint L3 address
+     * @param localSubnet subnet from local node
+     * @param destSubnet  destination endpoint's subnet
+     * @param ofWriter    flow writer
+     */
+    void createLocalL3RoutedFlow(short goToTable, int priority, Endpoint endpoint, L3Address l3Address,
+                                 Subnet localSubnet, Subnet destSubnet, OfWriter ofWriter) {
+        NodeConnectorId connectorId = endpoint.getAugmentation(OfOverlayContext.class).getNodeConnectorId();
+        L3Context l3Context = utils.getL3ContextForSubnet(utils.getIndexedTenant(endpoint.getTenant()), localSubnet);
+        if (l3Context == null) {
+            return;
+        }
+        MacAddress matcherMac = utils.routerPortMac(l3Context, localSubnet.getVirtualRouterIp(), endpoint.getTenant());
+        MacAddress epDestMac = endpoint.getMacAddress();
+        if (matcherMac == null || epDestMac == null) {
+            return;
+        }
+        MacAddress destSubnetGatewayMac = utils.routerPortMac(l3Context, destSubnet.getVirtualRouterIp(),
+                endpoint.getTenant());
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpoint);
+        if (localSubnet.getId().getValue().equals(destSubnet.getId().getValue())) {
+            matcherMac = epDestMac;
+        }
+        Action setNextHopAction;
+        try {
+            setNextHopAction = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(getOfPortNum(connectorId)));
+        } catch (NumberFormatException ex) {
+            LOG.warn("Could not parse port number {}", connectorId, ex);
+            return;
+        }
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlDstAction(epDestMac));
+        l3ApplyActions.add(decNwTtlAction());
+        if (!(matcherMac.getValue().equals(epDestMac.getValue()))) {
+            l3ApplyActions.add(setDlSrcAction(destSubnetGatewayMac));
+        }
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(ordinals.getEpgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(ordinals.getCgId())));
+        applyActions.add(setNextHopAction);
+        applyActions.addAll(l3ApplyActions);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+        Layer3Match l3Match;
+        Long etherType;
+        String ikey;
+        if (l3Address.getIpAddress() != null && l3Address.getIpAddress().getIpv4Address() != null) {
+            ikey = l3Address.getIpAddress().getIpv4Address().getValue() + "/32";
+            etherType = IPv4;
+            l3Match = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
+        } else if (l3Address.getIpAddress() != null && l3Address.getIpAddress().getIpv6Address() != null) {
+            ikey = l3Address.getIpAddress().getIpv6Address().getValue() + "/128";
+            etherType = IPv6;
+            l3Match = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
+        } else {
+            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", l3Address.toString());
+            return;
+        }
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
+                .setLayer3Match(l3Match);
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) ordinals.getL3Id()));
+        Match match = matchBuilder.build();
+        FlowId flowid = FlowIdUtils.newFlowId(tableId, "localL3", match);
+        FlowBuilder flowBuilder = base(tableId).setId(flowid)
+                .setPriority(priority)
+                .setMatch(match)
+                .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    /**
+     * Create remote L2 flow
+     *
+     * @param goToTable    {@link GoToTable} instruction value
+     * @param priority     of the flow
+     * @param endpoint     original peer
+     * @param peerEndpoint peer endpoint to original endpoint
+     * @param tunDst       tunnel destination Ip address
+     * @param connectorId  tunnel port
+     * @param ofWriter     flow writer
+     */
+    void createRemoteL2Flow(short goToTable, int priority, Endpoint endpoint, Endpoint peerEndpoint, IpAddress tunDst,
+                            NodeConnectorId connectorId, OfWriter ofWriter) {
+        OrdinalFactory.EndpointFwdCtxOrdinals endpointOrdinals = utils.getEndpointOrdinals(endpoint);
+        long port;
+        try {
+            port = getOfPortNum(connectorId);
+        } catch (NumberFormatException ex) {
+            LOG.warn("Could not parse port number {}", connectorId);
+            return;
+        }
+        Action tunnelDestinationAction = null;
+        if (tunDst.getIpv4Address() != null) {
+            tunnelDestinationAction = nxLoadTunIPv4Action(tunDst.getIpv4Address().getValue(), false);
+        } else if (tunDst.getIpv6Address() != null) {
+            LOG.error("IPv6 tunnel destination {} for {} not supported", tunDst.getIpv6Address().getValue(),
+                    nodeId);
+            return;
+        }
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(endpointOrdinals.getEpgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(endpointOrdinals.getCgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(port)));
+        applyActions.add(tunnelDestinationAction);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+
+        ArrayList<Instruction> instructions = new ArrayList<>();
+        instructions.add(applyActionsIns);
+        instructions.add(gotoTable);
+
+        MatchBuilder matchBuilder = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null, peerEndpoint.getMacAddress(), null));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg4.class, (long) endpointOrdinals.getBdId()));
+        Match match = matchBuilder.build();
+        FlowId flowid = FlowIdUtils.newFlowId(tableId, "remoteL2", match);
+        FlowBuilder flowBuilder = base(tableId).setId(flowid)
+                .setPriority(priority)
+                .setMatch(match)
+                .setInstructions(new InstructionsBuilder().setInstruction(instructions).build());
+
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    /**
+     * Create remote L3 routed flow
+     *
+     * @param goToTable     {@link GoToTable} instruction value
+     * @param priority      of the flow
+     * @param endpoint      peer
+     * @param destL3Address destination L3 address
+     * @param destSubnet    subnet from destination node
+     * @param tunDst        tunnel destination Ip address
+     * @param connectorId   tunnel port
+     * @param localSubnet   subnet from local node
+     * @param ofWriter      flow writer
+     */
+    void createRemoteL3RoutedFlow(short goToTable, int priority, Endpoint endpoint, L3Address destL3Address,
+                                  Subnet destSubnet, IpAddress tunDst, NodeConnectorId connectorId, Subnet localSubnet,
+                                  OfWriter ofWriter) {
+        L3Context context = utils.getL3ContextForSubnet(utils.getIndexedTenant(endpoint.getTenant()), destSubnet);
+        if (context == null) {
+            return;
+        }
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpoint);
+        MacAddress matcherMac = utils.routerPortMac(context, localSubnet.getVirtualRouterIp(), endpoint.getTenant());
+        MacAddress epDestMac = endpoint.getMacAddress();
+        if (matcherMac == null || epDestMac == null) {
+            return;
+        }
+        MacAddress destSubnetGatewayMac = utils.routerPortMac(context, destSubnet.getVirtualRouterIp(),
+                endpoint.getTenant());
+
+        // L3 Actions
+        List<Action> l3ApplyActions = new ArrayList<>();
+        if (localSubnet.getId().getValue().equals(destSubnet.getId().getValue())) {
+            // This is our final destination, so match on actual EP mac.
+            matcherMac = epDestMac;
+        }
+        if (!(matcherMac.getValue().equals(epDestMac.getValue()))) {
+            Action setDlSrc = setDlSrcAction(destSubnetGatewayMac);
+            l3ApplyActions.add(setDlSrc);
+        }
+        l3ApplyActions.add(setDlDstAction(epDestMac));
+        l3ApplyActions.add(decNwTtlAction());
+
+
+        // Actions
+        Action tunnelDestinationAction;
+        if (tunDst != null && tunDst.getIpv4Address() != null) {
+            tunnelDestinationAction = nxLoadTunIPv4Action(tunDst.getIpv4Address().getValue(), false);
+        } else if (tunDst != null && tunDst.getIpv6Address() != null) {
+            LOG.error("IPv6 tunnel destination {} for {} not supported", tunDst.getIpv6Address().getValue(), nodeId);
+            return;
+        } else {
+            LOG.error("Tunnel IP for {} invalid", nodeId);
+            return;
+        }
+        long port;
+        try {
+            port = getOfPortNum(connectorId);
+        } catch (NumberFormatException ex) {
+            LOG.warn("Could not parse port number {}", connectorId, ex);
+            return;
+        }
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(ordinals.getEpgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(ordinals.getCgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(port)));
+        applyActions.add(tunnelDestinationAction);
+        applyActions.addAll(l3ApplyActions);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+
+        Layer3Match layer3Match;
+        Long etherType;
+        String ikey;
+        if (destL3Address.getIpAddress().getIpv4Address() != null) {
+            ikey = destL3Address.getIpAddress().getIpv4Address().getValue() + "/32";
+            etherType = IPv4;
+            layer3Match = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
+        } else {
+            ikey = destL3Address.getIpAddress().getIpv6Address().getValue() + "/128";
+            etherType = IPv6;
+            layer3Match = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
+        }
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
+                .setLayer3Match(layer3Match);
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) ordinals.getL3Id()));
+        Match match = matchBuilder.build();
+        FlowId flowid = FlowIdUtils.newFlowId(tableId, "remoteL3", match);
+        FlowBuilder flowBuilder = base(tableId).setId(flowid)
+                .setPriority(priority)
+                .setMatch(match)
+                .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    /**
+     * Creates arp flow using virtual router IP in {@link Subnet}
+     *
+     * @param priority      of the flow
+     * @param indexedTenant of the {@link Endpoint}
+     * @param subnet        entries get from peer's tenants
+     * @param ofWriter      flow writer
+     * @throws Exception could be thrown during {@link OrdinalFactory#getContextOrdinal(TenantId, UniqueId)}. Handled
+     *                   in {@link DestinationMapper#syncArpFlow(DestinationMapperFlows, TenantId, OfWriter)}
+     */
+    void createRouterArpFlow(int priority, IndexedTenant indexedTenant, Subnet subnet, OfWriter ofWriter)
+            throws Exception {
+        Tenant tenant = indexedTenant.getTenant();
+        if (tenant != null) {
+            L3Context l3Context = utils.getL3ContextForSubnet(indexedTenant, subnet);
+            if (l3Context != null) {
+                int contextOrdinal = OrdinalFactory.getContextOrdinal(tenant.getId(), l3Context.getId());
+                MacAddress routerMac = utils.routerPortMac(l3Context, subnet.getVirtualRouterIp(),
+                        indexedTenant.getTenant().getId());
+                if (routerMac != null) {
+                    if (subnet.getVirtualRouterIp().getIpv4Address() == null
+                            && subnet.getVirtualRouterIp().getIpv6Address() != null) {
+                        LOG.warn("IPv6 virtual router {} for subnet {} not supported", subnet.getVirtualRouterIp(), subnet.getId()
+                                .getValue());
+                        return;
+                    }
+                    String ipv4Value = subnet.getVirtualRouterIp().getIpv4Address().getValue();
+                    BigInteger intRouterMac = new BigInteger(1, bytesFromHexString(routerMac.getValue()));
+                    MatchBuilder matchBuilder = new MatchBuilder()
+                            .setEthernetMatch(ethernetMatch(null, null, ARP))
+                            .setLayer3Match(new ArpMatchBuilder()
+                                    .setArpOp(1)
+                                    .setArpTargetTransportAddress(new Ipv4Prefix(ipv4Value + "/32"))
+                                    .build());
+                    addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) contextOrdinal));
+                    Match match = matchBuilder.build();
+                    FlowId flowId = FlowIdUtils.newFlowId(tableId, "routerarp", match);
+                    FlowBuilder flowBuilder = base(tableId).setPriority(priority)
+                            .setId(flowId)
+                            .setMatch(match)
+                            .setInstructions(instructions(applyActionIns(nxMoveEthSrcToEthDstAction(),
+                                    setDlSrcAction(routerMac), nxLoadArpOpAction(BigInteger.valueOf(2L)),
+                                    nxMoveArpShaToArpThaAction(), nxLoadArpShaAction(intRouterMac),
+                                    nxMoveArpSpaToArpTpaAction(), nxLoadArpSpaAction(ipv4Value),
+                                    outputAction(new NodeConnectorId(nodeId.getValue() + ":INPORT")))));
+                    ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+                }
+            } else {
+                LOG.error("No L3 Context found associated with subnet {}.", subnet.getId());
+            }
+        }
+    }
+
+    /**
+     * Broadcast flow for destination mapper
+     *
+     * @param priority of the flow
+     * @param ordinals of the endpoint (input parameter in {@link DestinationMapper#sync(Endpoint, OfWriter)})
+     * @param mac      address of the multicast router {@link DestinationMapper#MULTICAST_MAC}
+     * @param ofWriter flow writer
+     */
+    void createBroadcastFlow(int priority, OrdinalFactory.EndpointFwdCtxOrdinals ordinals, MacAddress mac,
+                             OfWriter ofWriter) {
+        MatchBuilder matchBuilder = new MatchBuilder()
+                .setEthernetMatch(new EthernetMatchBuilder()
+                        .setEthernetDestination(new EthernetDestinationBuilder().setAddress(mac).setMask(mac).build())
+                        .build());
+        addNxRegMatch(matchBuilder, FlowUtils.RegMatch.of(NxmNxReg5.class, (long) ordinals.getFdId()));
+        Match match = matchBuilder.build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "broadcast", match);
+        FlowBuilder flowBuilder = base(tableId)
+                .setPriority(priority)
+                .setId(flowId)
+                .setMatch(match)
+                .setInstructions(instructions(applyActionIns(nxLoadTunIdAction(BigInteger
+                        .valueOf(ordinals.getFdId()), false), groupAction((long) ordinals.getFdId()))));
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    /**
+     * L3 prefix flow is created with endpoint {@link NodeConnectorId} if internal. If endpoint is external and
+     * external ports are present, one flow per external port is created
+     *
+     * @param goToTable     policy enforcer table Id
+     * @param priority      of the flow
+     * @param gatewayEp      L2 endpoint, should contain {@link MacAddress} and {@link OrdinalFactory.EndpointFwdCtxOrdinals}
+     * @param l3Prefix      endpoint L3 prefix value
+     * @param tenant        value get from {@link L3Prefix}
+     * @param localSubnet   value where this node is present
+     * @param externalPorts list of all external ports
+     * @param ofWriter      flow writer
+     */
+    void createL3PrefixFlow(short goToTable, int priority, Endpoint gatewayEp, EndpointL3Prefix l3Prefix, IndexedTenant tenant,
+                            Subnet localSubnet, Set<NodeConnectorId> externalPorts, OfWriter ofWriter) {
+        L3Context l3Context = utils.getL3ContextForSubnet(tenant, localSubnet);
+        if (l3Context != null && localSubnet.getVirtualRouterIp() != null) {
+            MacAddress matcherMacAddress = utils.routerPortMac(l3Context, localSubnet.getVirtualRouterIp(),
+                    tenant.getTenant().getId());
+            OfOverlayContext context = gatewayEp.getAugmentation(OfOverlayContext.class);
+            if (EndpointManager.isInternal(gatewayEp, tenant.getExternalImplicitGroups())) {
+                Preconditions.checkNotNull(context.getNodeConnectorId());
+                try {
+                    Long port = getOfPortNum(context.getNodeConnectorId());
+                    if(matcherMacAddress != null) {
+                        writeL3PrefixFlow(priority, goToTable, gatewayEp, l3Prefix, port, matcherMacAddress, ofWriter);
+                    }
+                } catch (NumberFormatException e) {
+                    LOG.warn("Could not parse port number {}", context.getNodeConnectorId());
+                }
+            } else { // External
+                for (NodeConnectorId externalPort : externalPorts) {
+                    try {
+                        Long port = getOfPortNum(externalPort);
+                        if(matcherMacAddress != null) {
+                            writeL3PrefixFlow(priority, goToTable, gatewayEp, l3Prefix, port, matcherMacAddress, ofWriter);
+                        }
+                    } catch (NumberFormatException e) {
+                        LOG.warn("Could not parse port number {}", externalPort);
+                    }
+                }
+            }
+        }
+    }
+
+    private void writeExternalL2Flow(short goToTable, int priority, OrdinalFactory.EndpointFwdCtxOrdinals ordinals,
+                                     Long port, Match match, OfWriter ofWriter) {
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(ordinals.getEpgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(ordinals.getCgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(port)));
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+
+        ArrayList<Instruction> instructions = new ArrayList<>();
+        instructions.add(applyActionsIns);
+        instructions.add(gotoTable);
+
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "externalL2", match);
+        FlowBuilder flowBuilder = base(tableId).setId(flowId)
+                .setPriority(priority)
+                .setMatch(match)
+                .setInstructions(new InstructionsBuilder().setInstruction(instructions).build());
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    private void writeExternalL3RoutedFlow(short goToTable, int priority, long port, Endpoint l2GatewayEp, Match match,
+                                           OrdinalFactory.EndpointFwdCtxOrdinals peerOrdinals, OfWriter ofWriter) {
+        MacAddress destSubnetGatewayMac = l2GatewayEp.getMacAddress();
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlSrcAction(destSubnetGatewayMac));
+        l3ApplyActions.add(setDlDstAction(l2GatewayEp.getMacAddress()));
+
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(peerOrdinals.getEpgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(peerOrdinals.getCgId())));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(port)));
+        applyActions.addAll(l3ApplyActions);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+
+        FlowId flowid = FlowIdUtils.newFlowId(tableId, "externalL3", match);
+        FlowBuilder flowBuilder = base(tableId).setId(flowid)
+                .setPriority(priority)
+                .setMatch(match)
+                .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
+        ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+    }
+
+    private void writeL3PrefixFlow(int priority, short goToTable, Endpoint endpoint, EndpointL3Prefix l3Prefix,
+                                   Long port, MacAddress matcherMacAddress, OfWriter ofWriter) {
+        MacAddress macAddress = endpoint.getMacAddress();
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpoint);
+        Action setEpgAction = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(ordinals.getEpgId()));
+        Action setCgAction = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(ordinals.getCgId()));
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlDstAction(macAddress));
+        l3ApplyActions.add(decNwTtlAction());
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(setEpgAction);
+        applyActions.add(setCgAction);
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(port)));
+        applyActions.addAll(l3ApplyActions);
+
+        int order = 0;
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(goToTable))
+                .build();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+
+        if(l3Prefix.getIpPrefix() != null) {
+            Long etherType;
+            Integer prefixLength;
+            if (l3Prefix.getIpPrefix().getIpv4Prefix() != null) {
+                etherType = IPv4;
+                prefixLength = Integer.valueOf(l3Prefix.getIpPrefix().getIpv4Prefix().getValue().split("/")[1]);
+            } else if (l3Prefix.getIpPrefix().getIpv6Prefix() != null) {
+                etherType = IPv6;
+                prefixLength = Integer.valueOf(l3Prefix.getIpPrefix().getIpv6Prefix().getValue().split("/")[1]);
+            } else {
+                LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", l3Prefix);
+                return;
+            }
+            MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMacAddress, etherType));
+            addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) ordinals.getL3Id()));
+            Match match = matchBuilder.build();
+
+            FlowId flowid = FlowIdUtils.newFlowId(tableId, "L3prefix", match);
+            FlowBuilder flowBuilder = base(tableId).setId(flowid)
+                    .setPriority(priority + prefixLength)
+                    .setMatch(match)
+                    .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
+            ofWriter.writeFlow(nodeId, tableId, flowBuilder.build());
+        }
+    }
+}
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperUtils.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperUtils.java
new file mode 100644 (file)
index 0000000..4848760
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination;
+
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.groupbasedpolicy.dto.EpKey;
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+class DestinationMapperUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DestinationMapperUtils.class);
+
+    private final OfContext ctx;
+
+    DestinationMapperUtils(OfContext ctx) {
+        this.ctx = Preconditions.checkNotNull(ctx);
+    }
+
+    HashSet<Subnet> getSubnets(TenantId tenantId) {
+        IndexedTenant indexedTenant = ctx.getTenant(tenantId);
+        if (indexedTenant != null && indexedTenant.getTenant() != null) {
+            ForwardingContext forwardingContext = indexedTenant.getTenant().getForwardingContext();
+            if (forwardingContext != null && forwardingContext.getSubnet() != null) {
+                return new HashSet<>(forwardingContext.getSubnet());
+            }
+        }
+
+        return new HashSet<>();
+    }
+
+    L3Context getL3ContextForSubnet(IndexedTenant indexedTenant, Subnet subnet) {
+        if (indexedTenant == null) {
+            return null;
+        }
+        return indexedTenant.resolveL3Context(subnet.getId());
+    }
+
+    NetworkDomainId getEPNetworkContainment(Endpoint endpoint, IndexedTenant tenant) {
+        if (endpoint.getNetworkContainment() != null) {
+            return endpoint.getNetworkContainment();
+        } else if (tenant != null) {
+            return tenant.getEndpointGroup(endpoint.getEndpointGroup())
+                    .getNetworkDomain();
+        } else {
+            return null;
+        }
+    }
+
+    // Need a method to get subnets for EPs attached to the node locally
+    // to set the source Mac address for the router interface.
+    List<Subnet> getLocalSubnets(NodeId nodeId) {
+        Collection<Endpoint> endpointsForNode = ctx.getEndpointManager().getEndpointsForNode(nodeId);
+
+        List<Subnet> localSubnets = new ArrayList<>();
+
+        for (Endpoint endpoint : endpointsForNode) {
+            HashSet<Subnet> subnets = getSubnets(endpoint.getTenant());
+            if (subnets.isEmpty()) {
+                LOG.debug("No local subnets in tenant {} for EP {}.", endpoint.getTenant(), endpoint.getKey());
+                continue;
+            }
+            NetworkDomainId epNetworkContainment = getEPNetworkContainment(endpoint, ctx.getTenant(endpoint.getTenant()));
+            for (Subnet subnet : subnets) {
+                if (epNetworkContainment.getValue().equals(subnet.getId().getValue())) {
+                    localSubnets.add(subnet);
+                }
+            }
+        }
+        return localSubnets;
+    }
+
+    Endpoint getL2EpOfSubnetGateway(TenantId tenantId, Subnet subnet) {
+        if (subnet != null && subnet.getVirtualRouterIp() != null) {
+            IpAddress gwIpAddress = subnet.getVirtualRouterIp();
+            Collection<EndpointL3Prefix> prefixEps = ctx.getEndpointManager().getEndpointsL3PrefixForTenant(tenantId);
+            if (prefixEps != null) {
+                for (EndpointL3Prefix prefixEp : prefixEps) {
+                    for (EndpointL3Gateways gw : prefixEp.getEndpointL3Gateways()) {
+                        EndpointL3 l3Ep = ctx.getEndpointManager().getL3Endpoint(gw.getL3Context(), gwIpAddress,
+                                prefixEp.getTenant());
+                        if (l3Ep != null && l3Ep.getL2Context() != null && l3Ep.getMacAddress() != null) {
+                            return ctx.getEndpointManager().getEndpoint(
+                                    new EpKey(l3Ep.getL2Context(), l3Ep.getMacAddress()));
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    MacAddress routerPortMac(L3Context l3c, IpAddress ipAddress, TenantId tenantId) {
+        MacAddress defaultMacAddress = DestinationMapper.ROUTER_MAC;
+        if (l3c.getId() != null) {
+            EndpointL3 endpointL3 = ctx.getEndpointManager().getL3Endpoint(l3c.getId(), ipAddress, tenantId);
+            if (endpointL3 == null || endpointL3.getMacAddress() == null) {
+                return defaultMacAddress;
+            } else {
+                return endpointL3.getMacAddress();
+            }
+        } else {
+            return defaultMacAddress;
+        }
+    }
+
+    IndexedTenant getIndexedTenant(TenantId tenantId) {
+        return ctx.getTenant(tenantId);
+    }
+
+    Set<EndpointGroupId> getAllEndpointGroups(Endpoint endpoint) {
+        Set<EndpointGroupId> groupIds = new HashSet<>();
+        if (endpoint.getEndpointGroup() != null) {
+            groupIds.add(endpoint.getEndpointGroup());
+        }
+        if (endpoint.getEndpointGroups() != null) {
+            groupIds.addAll(endpoint.getEndpointGroups());
+        }
+        return groupIds;
+    }
+
+    OrdinalFactory.EndpointFwdCtxOrdinals getEndpointOrdinals(Endpoint endpoint) {
+        try {
+            return OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
+        } catch (Exception e) {
+            LOG.error("Failed to get fwd ctx ordinals for endpoint {}", endpoint);
+            return null;
+        }
+    }
+
+}
index 95384d212da45f56295ca9821a842a5a41ff108d..d75afa2e234f29053a207ec7936424ca1b62e7ed 100755 (executable)
@@ -187,19 +187,19 @@ public class ExternalMapper extends FlowTable {
         // we only use NAT when going to external networks.
         Ipv4Prefix natIp = new Ipv4Prefix(ipv4Address.getValue() + "/32");
         Match match = new MatchBuilder()
-            .setEthernetMatch(FlowUtils.ethernetMatch(null, null, Long.valueOf(FlowUtils.IPv4)))
-            .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(natIp).build())
-            .setVlanMatch(FlowUtils.vlanMatch(0, false))
-            .build();
+                .setEthernetMatch(FlowUtils.ethernetMatch(null, null, Long.valueOf(FlowUtils.IPv4)))
+                .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(natIp).build())
+                .setVlanMatch(FlowUtils.vlanMatch(0, false))
+                .build();
         List<ActionBuilder> pushVlanActions = new ArrayList<>();
         pushVlanActions.addAll(FlowUtils.pushVlanActions(vlanId));
         pushVlanActions.add(new ActionBuilder().setOrder(0).setAction(nxOutputRegAction(NxmNxReg7.class)));
         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "external_nat_push_vlan", match);
         return base().setPriority(priority)
-            .setId(flowid)
-            .setMatch(match)
-            .setInstructions(FlowUtils.instructions(applyActionIns(pushVlanActions)))
-            .build();
+                .setId(flowid)
+                .setMatch(match)
+                .setInstructions(FlowUtils.instructions(applyActionIns(pushVlanActions)))
+                .build();
     }
 
     public static Subnet resolveSubnetForIpv4Address(IndexedTenant t, Ipv4Address ipv4Addr) {
@@ -246,10 +246,10 @@ public class ExternalMapper extends FlowTable {
             pushVlanActions.add(new ActionBuilder().setOrder(0).setAction(nxOutputRegAction(NxmNxReg7.class)));
             FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "external_push_vlan", match);
             flows.add(base().setPriority(priority)
-                .setId(flowid)
-                .setMatch(match)
-                .setInstructions(FlowUtils.instructions(applyActionIns(pushVlanActions)))
-                .build());
+                    .setId(flowid)
+                    .setMatch(match)
+                    .setInstructions(FlowUtils.instructions(applyActionIns(pushVlanActions)))
+                    .build());
         }
         return flows;
     }
@@ -257,9 +257,9 @@ public class ExternalMapper extends FlowTable {
     private Flow defaultFlow() {
         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "defaultExternalFlow", null);
         Flow flow = base().setPriority(100)
-            .setId(flowid)
-            .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
-            .build();
+                .setId(flowid)
+                .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
+                .build();
         return flow;
     }
 }
index 3792f412bf2314892ba88a0ef300f7885b2187b3..0186c2f76291a32b83f3e5f94f688ab9db74a59c 100755 (executable)
@@ -139,7 +139,7 @@ public class IngressNatMapper extends FlowTable {
 
         // Flows for ingress NAT translation
         Collection<EndpointL3> l3Endpoints = ctx.getEndpointManager().getL3EndpointsWithNat();
-        OrdinalFactory.EndpointFwdCtxOrdinals epFwdCtxOrdinals = getEndpointOrdinals(endpoint);
+        OrdinalFactory.EndpointFwdCtxOrdinals epFwdCtxOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
         EndpointKey endpointKey = endpoint.getKey();
         for (EndpointL3 l3Endpoint : l3Endpoints) {
             L2BridgeDomainId l2Context = l3Endpoint.getL2Context();
@@ -174,18 +174,4 @@ public class IngressNatMapper extends FlowTable {
             }
         }
     }
-
-    private OrdinalFactory.EndpointFwdCtxOrdinals getEndpointOrdinals(Endpoint endpoint) {
-        try {
-            OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
-            if (ordinals == null) {
-                LOG.info("getEndpointFwdCtxOrdinals is null for EP {}", endpoint);
-                return null;
-            }
-            return ordinals;
-        } catch (Exception e) {
-            LOG.error("Failed to get endpoint ordinals, endpoint: {}", endpoint);
-            return null;
-        }
-    }
 }
index 4cf70f99f34c2e4da45955d2162e7fc1aba4b278..1bbc8cd98f67f851d5a52d7fd2c6ce19da665702 100644 (file)
@@ -212,7 +212,7 @@ class IngressNatMapperFlows {
     private Flow createOutsideArpFlow(IndexedTenant tenant, int priority, IpAddress outsideDestAddress,
                                       MacAddress toMac, NodeId nodeId) {
         String ikey = outsideDestAddress.getIpv4Address().getValue();
-        BigInteger intMac = new BigInteger(1, bytesFromHexString(toMac.getValue()));
+        BigInteger intMac = new BigInteger(1, FlowUtils.bytesFromHexString(toMac.getValue()));
         MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, ARP)).setLayer3Match(
                 new ArpMatchBuilder().setArpOp(1)
                         .setArpTargetTransportAddress(new Ipv4Prefix(ikey + "/32"))
@@ -317,18 +317,4 @@ class IngressNatMapperFlows {
             return null;
         }
     }
-
-    private byte[] bytesFromHexString(String values) {
-        String target = "";
-        if (values != null) {
-            target = values;
-        }
-        String[] octets = target.split(":");
-
-        byte[] ret = new byte[octets.length];
-        for (int i = 0; i < octets.length; i++) {
-            ret[i] = Integer.valueOf(octets[i], 16).byteValue();
-        }
-        return ret;
-    }
 }
index 937c022b4219bdb376920fe4c5585e985cecabd5..9d6fc038fa3e6706042236154cc4388e0034de58 100755 (executable)
@@ -123,7 +123,8 @@ public class SourceMapper extends FlowTable {
                 for (EgKey peer : peers) {
                     Collection<Endpoint> peerEgEndpoints = ctx.getEndpointManager().getEndpointsForGroup(peer);
                     for (Endpoint peerEgEndpoint : peerEgEndpoints) {
-                        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = getEndpointOrdinals(ctx, peerEgEndpoint);
+                        OrdinalFactory.EndpointFwdCtxOrdinals ordinals =
+                                OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, peerEgEndpoint);
                         flows.createTunnelFlow(destinationMapperId, TUNNEL_FLOW, tunnelPort, ordinals,
                                 ofWriter);
                         flows.createBroadcastFlow(destinationMapperId, BROADCAST_FLOW, tunnelPort,
@@ -138,7 +139,8 @@ public class SourceMapper extends FlowTable {
         }
         IndexedTenant tenant = ctx.getTenant(endpoint.getTenant());
         // Sync the local EP information
-        OrdinalFactory.EndpointFwdCtxOrdinals endpointFwdCtxOrdinals = getEndpointOrdinals(ctx, endpoint);
+        OrdinalFactory.EndpointFwdCtxOrdinals endpointFwdCtxOrdinals =
+                OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
         MacAddress macAddress = endpoint.getMacAddress();
         if (endpointFwdCtxOrdinals != null) {
             OfOverlayContext ofOverlayContext = endpoint.getAugmentation(OfOverlayContext.class);
@@ -150,15 +152,6 @@ public class SourceMapper extends FlowTable {
         }
     }
 
-    private OrdinalFactory.EndpointFwdCtxOrdinals getEndpointOrdinals(OfContext ctx, Endpoint endpoint) {
-        try {
-            return OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
-        } catch (Exception e) {
-            LOG.error("Failed to get fwd ctx ordinals for endpoint {}", endpoint);
-            return null;
-        }
-    }
-
     private Set<EgKey> getEndpointGroups(Endpoint endpoint) {
         Set<EgKey> endpointGroups = new HashSet<>();
         if (endpoint.getEndpointGroup() != null) {
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapperTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapperTest.java
deleted file mode 100755 (executable)
index 5b9bf9a..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-/*\r
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;\r
-\r
-import static org.junit.Assert.assertEquals;\r
-import static org.junit.Assert.assertNotEquals;\r
-import static org.junit.Assert.assertTrue;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ARP;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.decNwTtlAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.dropInstructions;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ethernetMatch;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.getOfPortNum;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.groupAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpOpAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpShaAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadArpSpaAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveArpShaToArpThaAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveArpSpaToArpTpaAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveEthSrcToEthDstAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxMoveRegTunIdAction;\r
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlSrcAction;\r
-\r
-import java.math.BigInteger;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Objects;\r
-\r
-import org.junit.Before;\r
-import org.junit.Ignore;\r
-import org.junit.Test;\r
-import org.junit.runner.RunWith;\r
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;\r
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;\r
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination.DestinationMapper;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.TunnelBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;\r
-import org.powermock.api.mockito.PowerMockito;\r
-import org.powermock.core.classloader.annotations.PrepareForTest;\r
-import org.powermock.modules.junit4.PowerMockRunner;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import com.google.common.collect.ImmutableList;\r
-\r
-@RunWith(PowerMockRunner.class)\r
-@PrepareForTest({PolicyManager.class})\r
-public class DestinationMapperTest extends FlowTableTest {\r
-    protected static final Logger LOG =\r
-            LoggerFactory.getLogger(DestinationMapperTest.class);\r
-\r
-    NodeConnectorId remoteTunnelId =\r
-            new NodeConnectorId(remoteNodeId.getValue() + ":101");\r
-\r
-    @Override\r
-    @Before\r
-    public void setup() throws Exception {\r
-        PowerMockito.stub(PowerMockito.method(PolicyManager.class, "setSfcTableOffset")).toReturn(true);\r
-\r
-        initCtx();\r
-        table = new DestinationMapper(ctx,ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER());\r
-        super.setup();\r
-    }\r
-\r
-    @Ignore\r
-    @Test\r
-    public void testNoEps() throws Exception {\r
-        OfWriter fm = dosync(null);\r
-        assertEquals(1, fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER()).getFlow().size());\r
-    }\r
-\r
-    private void verifyDMap(Endpoint remoteEp,\r
-            Endpoint localEp) throws Exception {\r
-\r
-        OfWriter fm = dosync(null);\r
-        assertNotEquals(0, fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER()).getFlow().size());\r
-\r
-        // presumably counts flows that have correct matches set up\r
-        int count = 0;\r
-        HashMap<String, Flow> flowMap = new HashMap<>();\r
-        for (Flow f : fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER()).getFlow()) {\r
-            flowMap.put(f.getId().getValue(), f);\r
-            if (f.getMatch() == null) {\r
-                assertEquals(dropInstructions(),\r
-                        f.getInstructions());\r
-                count += 1;\r
-            } else if (Objects.equals(ethernetMatch(null, null, ARP),\r
-                    f.getMatch().getEthernetMatch())) {\r
-                // router ARP reply\r
-                Instruction ins = f.getInstructions().getInstruction().get(0);\r
-                assertTrue(ins.getInstruction() instanceof ApplyActionsCase);\r
-                List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
-                assertEquals(nxMoveEthSrcToEthDstAction(),\r
-                        actions.get(0).getAction());\r
-                assertEquals(Integer.valueOf(0), actions.get(0).getOrder());\r
-                assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),\r
-                        actions.get(1).getAction());\r
-                assertEquals(Integer.valueOf(1), actions.get(1).getOrder());\r
-                assertEquals(nxLoadArpOpAction(BigInteger.valueOf(2L)),\r
-                        actions.get(2).getAction());\r
-                assertEquals(Integer.valueOf(2), actions.get(2).getOrder());\r
-                assertEquals(nxMoveArpShaToArpThaAction(),\r
-                        actions.get(3).getAction());\r
-                assertEquals(Integer.valueOf(3), actions.get(3).getOrder());\r
-                assertEquals(nxLoadArpShaAction(new BigInteger(1, DestinationMapper\r
-                        .bytesFromHexString(DestinationMapper.ROUTER_MAC\r
-                                .getValue()))),\r
-                        actions.get(4).getAction());\r
-                assertEquals(Integer.valueOf(4), actions.get(4).getOrder());\r
-                assertEquals(nxMoveArpSpaToArpTpaAction(),\r
-                        actions.get(5).getAction());\r
-                assertEquals(Integer.valueOf(5), actions.get(5).getOrder());\r
-                assertTrue(nxLoadArpSpaAction("10.0.0.1").equals(actions.get(6).getAction()) ||\r
-                        nxLoadArpSpaAction("10.0.1.1").equals(actions.get(6).getAction()) ||\r
-                        nxLoadArpSpaAction("10.0.2.1").equals(actions.get(6).getAction()));\r
-                assertEquals(Integer.valueOf(6), actions.get(6).getOrder());\r
-                count += 1;\r
-            } else if (Objects.equals(localEp.getMacAddress(),\r
-                    f.getMatch().getEthernetMatch()\r
-                            .getEthernetDestination().getAddress())) {\r
-                int icount = 0;\r
-                for (Instruction ins : f.getInstructions().getInstruction()) {\r
-                    if (ins.getInstruction() instanceof ApplyActionsCase) {\r
-                        long p = getOfPortNum(nodeConnectorId);\r
-                        List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
-                        assertEquals(nxLoadRegAction(NxmNxReg7.class,\r
-                                BigInteger.valueOf(p)),\r
-                                actions.get(2).getAction());\r
-                        icount += 1;\r
-                    } else if (ins.getInstruction() instanceof GoToTableCase) {\r
-                        assertEquals(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()),\r
-                                ins.getInstruction());\r
-                        icount += 1;\r
-                    }\r
-                }\r
-                assertEquals(2, icount);\r
-                LOG.info("{}", f);\r
-                count += 1;\r
-            } else if (Objects.equals(remoteEp.getMacAddress(),\r
-                    f.getMatch().getEthernetMatch()\r
-                            .getEthernetDestination().getAddress())) {\r
-                int icount = 0;\r
-                for (Instruction ins : f.getInstructions().getInstruction()) {\r
-                    if (ins.getInstruction() instanceof ApplyActionsCase) {\r
-                        long p = getOfPortNum(tunnelId);\r
-                        List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
-                        assertEquals(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(p)),\r
-                                actions.get(actions.size() - 1).getAction());\r
-                        icount += 1;\r
-                    } else if (ins.getInstruction() instanceof GoToTableCase) {\r
-                        assertEquals(gotoTableIns((short) (table.getTableId() + 1)),\r
-                                ins.getInstruction());\r
-                        icount += 1;\r
-                    }\r
-                }\r
-                assertEquals(2, icount);\r
-                LOG.info("{}", f);\r
-                count += 1;\r
-            } else if (Objects.equals(DestinationMapper.ROUTER_MAC,\r
-                    f.getMatch().getEthernetMatch()\r
-                            .getEthernetDestination()\r
-                            .getAddress())) {\r
-                if (f.getMatch().getLayer3Match() instanceof Ipv4Match) {\r
-                    // should be local port with rewrite dlsrc and dldst plus\r
-                    // ttl decr\r
-                    Instruction ins = f.getInstructions().getInstruction().get(0);\r
-                    assertTrue(ins.getInstruction() instanceof ApplyActionsCase);\r
-                    List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
-                    long p = getOfPortNum(nodeConnectorId);\r
-                    assertEquals(nxLoadRegAction(NxmNxReg7.class,\r
-                            BigInteger.valueOf(p)),\r
-                            actions.get(2).getAction());\r
-                    assertEquals(Integer.valueOf(2), actions.get(2).getOrder());\r
-                    assertEquals(Integer.valueOf(3), actions.get(3).getOrder());\r
-                    assertEquals(Integer.valueOf(4), actions.get(4).getOrder());\r
-                    assertEquals(decNwTtlAction(),\r
-                            actions.get(5).getAction());\r
-                    assertEquals(Integer.valueOf(5), actions.get(5).getOrder());\r
-                    count += 1;\r
-                } else if (f.getMatch().getLayer3Match() instanceof Ipv6Match) {\r
-                    // should be remote port with rewrite dlsrc plus\r
-                    // ttl decr\r
-                    Instruction ins = f.getInstructions().getInstruction().get(0);\r
-                    assertTrue(ins.getInstruction() instanceof ApplyActionsCase);\r
-                    List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
-                    long p = getOfPortNum(tunnelId);\r
-                    assertEquals(nxLoadRegAction(NxmNxReg7.class,\r
-                            BigInteger.valueOf(p)),\r
-                            actions.get(4).getAction());\r
-                    assertEquals(Integer.valueOf(4), actions.get(4).getOrder());\r
-                    assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),\r
-                            actions.get(5).getAction());\r
-                    assertEquals(Integer.valueOf(5), actions.get(5).getOrder());\r
-                    assertEquals(decNwTtlAction(),\r
-                            actions.get(6).getAction());\r
-                    assertEquals(Integer.valueOf(6), actions.get(6).getOrder());\r
-                    count += 1;\r
-                }\r
-            } else if (Objects.equals(DestinationMapper.MULTICAST_MAC,\r
-                    f.getMatch().getEthernetMatch()\r
-                            .getEthernetDestination()\r
-                            .getAddress())) {\r
-                // broadcast/multicast flow should output to group table\r
-                Instruction ins = f.getInstructions().getInstruction().get(0);\r
-                assertTrue(ins.getInstruction() instanceof ApplyActionsCase);\r
-                List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
-                assertEquals(nxMoveRegTunIdAction(NxmNxReg0.class, false),\r
-                        actions.get(0).getAction());\r
-                assertEquals(Integer.valueOf(0), actions.get(0).getOrder());\r
-\r
-                Long v = (long) OrdinalFactory.getContextOrdinal(tid, fd);\r
-                assertEquals(groupAction(v), actions.get(1).getAction());\r
-                assertEquals(Integer.valueOf(1), actions.get(1).getOrder());\r
-                count += 1;\r
-            }\r
-        }\r
-\r
-        // TODO Li alagalah: Due to subnet checking this test is no longer setup\r
-        // correct. Must address before Li.\r
-        // assertEquals(8, count);\r
-        assertEquals(fm.getTableForNode(nodeId, ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER()).getFlow().size(), count);\r
-        int numberOfFlows = fm.getTableForNode(nodeId, (short) 2).getFlow().size();\r
-        fm = dosync(flowMap);\r
-        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 2).getFlow().size());\r
-    }\r
-\r
-    @Override\r
-    protected EndpointBuilder localEP() {\r
-        return super.localEP()\r
-                .setL3Address(ImmutableList.of(new L3AddressBuilder()\r
-                        .setL3Context(l3c)\r
-                        .setIpAddress(new IpAddress(new Ipv4Address("10.0.0.1")))\r
-                        .build()));\r
-    }\r
-\r
-    @Override\r
-    protected EndpointBuilder remoteEP(NodeId remoteNodeId) {\r
-        return super.remoteEP(remoteNodeId)\r
-                .setL3Address(ImmutableList.of(new L3AddressBuilder()\r
-                        .setL3Context(l3c)\r
-                        .setIpAddress(new IpAddress(new Ipv6Address("::ffff:0:0:0:10.0.0.2")))\r
-                        .build()));\r
-    }\r
-\r
-    private void addSwitches() {\r
-        switchManager.addSwitch(\r
-                nodeId,\r
-                tunnelId,\r
-                Collections.<NodeConnectorId>emptySet(),\r
-                new OfOverlayNodeConfigBuilder().setTunnel(\r
-                        ImmutableList.of(new TunnelBuilder().setIp(new IpAddress(new Ipv4Address("1.2.3.4")))\r
-                            .setTunnelType(TunnelTypeVxlan.class)\r
-                            .setNodeConnectorId(tunnelId)\r
-                            .build())).build());\r
-        switchManager.addSwitch(\r
-                remoteNodeId,\r
-                remoteTunnelId,\r
-                Collections.<NodeConnectorId>emptySet(),\r
-                new OfOverlayNodeConfigBuilder().setTunnel(\r
-                        ImmutableList.of(new TunnelBuilder().setIp(new IpAddress(new Ipv4Address("1.2.3.5")))\r
-                            .setTunnelType(TunnelTypeVxlan.class)\r
-                            .setNodeConnectorId(tunnelId)\r
-                            .build())).build());\r
-    }\r
-\r
-    @Ignore\r
-    @Test\r
-    public void testSame() throws Exception {\r
-        addSwitches();\r
-        Endpoint localEp = localEP().build();\r
-        endpointManager.addEndpoint(localEp);\r
-        Endpoint remoteEp = remoteEP(remoteNodeId).build();\r
-        endpointManager.addEndpoint(remoteEp);\r
-\r
-\r
-        ctx.addTenant(baseTenant().setPolicy(new PolicyBuilder(baseTenant().getPolicy()).setContract(\r
-                ImmutableList.of(baseContract(null).build())).build()).build());\r
-        verifyDMap(remoteEp, localEp);\r
-    }\r
-\r
-    @Ignore\r
-    @Test\r
-    public void testDiff() throws Exception {\r
-        addSwitches();\r
-        Endpoint localEp = localEP().build();\r
-        endpointManager.addEndpoint(localEp);\r
-        Endpoint remoteEp = remoteEP(remoteNodeId)\r
-                .setEndpointGroup(eg2)\r
-                .build();\r
-        endpointManager.addEndpoint(remoteEp);\r
-\r
-        ctx.addTenant(baseTenant().setPolicy(new PolicyBuilder(baseTenant().getPolicy()).setContract(\r
-                ImmutableList.of(baseContract(null).build())).build()).build());\r
-        verifyDMap(remoteEp, localEp);\r
-    }\r
-\r
-}\r
index efb4160cd38814661daa254e60386785ba96352a..fd9ee41c3e864bc7056e39180df21844577f7561 100755 (executable)
@@ -36,7 +36,7 @@ public class FlowTableTest extends OfTableTest {
                 }\r
             }\r
         }\r
-        //table.sync(nodeId, ofWriter);\r
+        //table.sync(NODE_ID, ofWriter);\r
         return ofWriter;\r
     }\r
 }\r
index b2cca0761c0a2e3eabc62a3fc05949295c750df6..8fe25913bd09f9b0347d31da4ea37d7d30befaf6 100755 (executable)
@@ -160,9 +160,9 @@ public class GroupTableTest {
     @Ignore
     @Test
     public void updateTest() throws Exception {
-        //doNothing().when(groupTable).sync(nodeId, ofWriter);
+        //doNothing().when(groupTable).sync(NODE_ID, ofWriter);
 
-        //groupTable.sync(nodeId, ofWriter);
+        //groupTable.sync(NODE_ID, ofWriter);
         //verify(groupTable).sync(any(NodeId.class), any(OfWriter.class));
     }
 
@@ -171,7 +171,7 @@ public class GroupTableTest {
     public void updateTestNoFCN() throws Exception {
         doReturn(null).when(groupTable).getFCNodeFromDatastore(any(NodeId.class));
 
-        //groupTable.sync(nodeId, ofWriter);
+        //groupTable.sync(NODE_ID, ofWriter);
         verify(ofWriter, never()).writeBucket(any(NodeId.class), any(GroupId.class), any(Bucket.class));;
         verify(ofWriter, never()).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
         verify(ofWriter, never()).writeGroup(any(NodeId.class), any(GroupId.class), any(GroupTypes.class),
@@ -185,7 +185,7 @@ public class GroupTableTest {
         when(endpointManager.getGroupsForNode(any(NodeId.class))).thenReturn(
                 Collections.<EgKey>emptySet());
 
-        //groupTable.sync(nodeId, ofWriter);
+        //groupTable.sync(NODE_ID, ofWriter);
         verify(ofWriter).writeGroup(any(NodeId.class), any(GroupId.class));
     }
 
@@ -196,7 +196,7 @@ public class GroupTableTest {
         when(endpointManager.getGroupsForNode(any(NodeId.class))).thenReturn(
                 Collections.<EgKey>emptySet());
 
-        //groupTable.sync(nodeId, ofWriter);
+        //groupTable.sync(NODE_ID, ofWriter);
         verify(ofWriter, never()).writeGroup(any(NodeId.class), any(GroupId.class));
     }
 }
index 93ac285cb295388f8711cc3a327313d99c90dea7..f49ebcc22d9e6c501fa418bf2c157305d50ca132 100644 (file)
@@ -1,5 +1,6 @@
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper;\r
 \r
+import com.google.common.base.Preconditions;\r
 import com.google.common.collect.ImmutableList;\r
 import org.opendaylight.groupbasedpolicy.api.sf.L4ClassifierDefinition;\r
 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;\r
@@ -25,6 +26,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.I
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;\r
@@ -49,8 +51,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContextBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomainBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;\r
@@ -70,39 +75,43 @@ import java.util.List;
 \r
 public abstract class MapperUtilsTest {\r
 \r
-    protected static final String IPV4_1 = "170.0.0.1";\r
-    protected static final String IPV4_2 = "190.0.0.1";\r
-    protected static final String MAC_0 = "00:00:00:00:00:00";\r
-    protected static final String MAC_1 = "00:00:00:00:00:01";\r
-    protected static final String CONNECTOR_0 = "0";\r
-    protected static final String CONNECTOR_1 = "1";\r
+    protected static final MacAddress MAC_0 = new MacAddress("00:00:00:00:00:00");\r
+    protected static final MacAddress MAC_1 = new MacAddress("00:00:00:00:00:01");\r
+    protected static final MacAddress MAC_2 = new MacAddress("00:00:00:00:00:02");\r
+    protected static final Ipv4Address IPV4_0 = new Ipv4Address("170.0.0.1");\r
+    protected static final Ipv4Address IPV4_1 = new Ipv4Address("190.0.0.1");\r
+    protected static final Ipv4Address IPV4_2 = new Ipv4Address("210.0.0.1");\r
+    protected static final Ipv6Address IPV6_1 = new Ipv6Address("2000:db80:85a3:08ba:0947:8a2e:3a70:7334");\r
+    protected static final Ipv6Address IPV6_2 = new Ipv6Address("0947:db80:3a70:7334:85a3:8a2e:2000:08ba");\r
+    protected static final NodeConnectorId CONNECTOR_0 = new NodeConnectorId("0");\r
+    protected static final NodeConnectorId CONNECTOR_1 = new NodeConnectorId("1");\r
+    protected static final NodeConnectorId CONNECTOR_2 = new NodeConnectorId("2");\r
+    protected static final SubnetId SUBNET_0 = new SubnetId("subnet0");\r
+    protected static final SubnetId SUBNET_1 = new SubnetId("subnet1");\r
+    protected static final SubnetId SUBNET_2 = new SubnetId("subnet2");\r
+    protected static final SubnetId SUBNET_EXT = new SubnetId("externalSubnet");\r
     protected static final String IP_PREFIX_32 = "/32";\r
     protected static final String IP_PREFIX_128 = "/128";\r
-    protected static final String IPV6_1 = "2000:db80:85a3:08ba:0947:8a2e:3a70:7334";\r
-    protected static final String IPV6_2 = "0947:db80:3a70:7334:85a3:8a2e:2000:08ba";\r
-    protected static final String DHCP_IP = "255.255.255.255";\r
-    protected static final String TENANT_ID = "dummy tenant";\r
-    protected static final String NODE_ID = "dummy node";\r
+    protected static final TenantId TENANT_ID = new TenantId("tenantId");\r
+    protected static final NodeId NODE_ID = new NodeId("nodeId");\r
+    protected static final EndpointGroupId ENDPOINT_GROUP_0 = new EndpointGroupId("eg0");\r
+    protected static final EndpointGroupId ENDPOINT_GROUP_1 = new EndpointGroupId("eg1");\r
+    protected static final EndpointGroupId ENDPOINT_GROUP_2 = new EndpointGroupId("eg2");\r
+    protected static final NetworkDomainId NET_DOMAIN_ID = new NetworkDomainId("ndId");\r
+    protected static final L2BridgeDomainId L2BD_ID = new L2BridgeDomainId("l2bdId");\r
+    protected static final L2FloodDomainId L2FD_ID = new L2FloodDomainId("l2fdId");\r
+    protected static final L2FloodDomainId L2_FD_ID_EXT = new L2FloodDomainId("externalL2fdId");\r
+    protected static final L3ContextId L3C_ID = new L3ContextId("l3cId");\r
+    protected static final ContractId CONTRACT_ID = new ContractId("contractId");\r
+    protected static final ContextId CONTEXT_ID = new L3ContextId("ctxId");\r
+    // Often used strings\r
+    protected static final String ALLOW = "allow";\r
     protected static final String L2 = "L2";\r
-    protected static final String EPG_ID = "dummy epg id";\r
-    protected static final String ENDPOINT_GROUP_0 = "eg0";\r
-    protected static final String ENDPOINT_GROUP_1 = "eg1";\r
-    protected static final String ENDPOINT_GROUP_2 = "eg2";\r
-    private static final String DOMAIN_ID = "dummy id";\r
-    protected final NodeId nodeId = new NodeId(NODE_ID);\r
-    protected final NodeConnectorId nodeConnectorId = new NodeConnectorId(nodeId.getValue() + CONNECTOR_0);\r
-    protected final L2BridgeDomainId bd = new L2BridgeDomainId("c95182ba-7807-43f8-98f7-6c7c720b7639");\r
-    protected final EndpointGroupId eg = new EndpointGroupId("36dec84a-08c7-497b-80b6-a0035af72a12");\r
-    protected final EndpointGroupId eg2 = new EndpointGroupId("632e5e11-7988-4eb5-8fe6-6c182d890276");\r
-    protected final ContractId cid = new ContractId("a5874893-bcd5-46de-96af-3c8d99bedf9f");\r
-    protected final L3ContextId l3c = new L3ContextId("2cf51ee4-e996-467e-a277-2d380334a91d");\r
-    protected final L2FloodDomainId fd = new L2FloodDomainId("98e1439e-52d2-46f8-bd69-5136e6088771");\r
-    protected final L2FloodDomainId ext_fd = new L2FloodDomainId("d8024f7a-b83e-11e5-9912-ba0be0483c18");\r
-    protected final SubnetId sub = new SubnetId("4fcf8dfc-53b5-4aef-84d3-6b5586992fcb");\r
-    protected final SubnetId sub2 = new SubnetId("c285a59f-fcb8-42e6-bf29-87ea522fd626");\r
-    protected final SubnetId sub3 = new SubnetId("a0380d52-2a25-48ef-882c-a4d4cd9e00ec");\r
-    protected final SubnetId ext_sub = new SubnetId("8da17ad9-3261-4dc9-bcff-928a2f73cce7");\r
-    protected final TenantId tid = new TenantId(TENANT_ID);\r
+    protected static final String OPENFLOW = "openflow:";\r
+    protected static final String DROP_ALL = "dropAll";\r
+    protected static final String DROP = "drop";\r
+    protected static final String TCP_SRC = "tcp_src_80";\r
+    // Mock variables\r
     protected Short tableId;\r
     protected OfContext ctx;\r
     protected OfWriter ofWriter;\r
@@ -112,143 +121,182 @@ public abstract class MapperUtilsTest {
     protected PolicyInfo policyInfo;\r
     protected FlowTable table;\r
 \r
-    protected FlowBuilder flowBuilder(FlowId flowId, short tableId, Integer priority, Match match, Instructions instructions) {\r
+    protected FlowBuilder buildFlow(FlowId flowId, short tableId, Integer priority, Match match, Instructions instructions) {\r
         FlowBuilder flowBuilder = FlowUtils.base(tableId);\r
         flowBuilder.setId(flowId)\r
                 .setPriority(priority)\r
                 .setMatch(match)\r
                 .setInstructions(instructions);\r
-\r
         return flowBuilder;\r
     }\r
 \r
-    protected EndpointL3Builder endpointL3Builder(String ip, String insideIp, String mac, String l2, boolean ipv6) {\r
+    protected EndpointL3Builder buildL3Endpoint(Ipv4Address natIp, Ipv4Address ip, MacAddress mac, String l2bd) {\r
+        Preconditions.checkNotNull(natIp);\r
+        Preconditions.checkNotNull(ip);\r
+        Preconditions.checkNotNull(mac);\r
         EndpointL3Builder endpointL3Builder = new EndpointL3Builder();\r
-\r
-        // Set NAT address augmentation\r
-        if (ip != null) {\r
-            if (ipv6) {\r
-                NatAddressBuilder natAddressBuilder = new NatAddressBuilder();\r
-                natAddressBuilder.setNatAddress(new IpAddress(new Ipv6Address(ip)));\r
-                endpointL3Builder.addAugmentation(NatAddress.class, natAddressBuilder.build());\r
-            } else {\r
-                NatAddressBuilder natAddressBuilder = new NatAddressBuilder();\r
-                natAddressBuilder.setNatAddress(new IpAddress(new Ipv4Address(ip)));\r
-                endpointL3Builder.addAugmentation(NatAddress.class, natAddressBuilder.build());\r
-            }\r
-        }\r
-\r
-        // Set IP address\r
-        if (insideIp != null) {\r
-            if (ipv6) {\r
-                endpointL3Builder.setIpAddress(new IpAddress(new Ipv6Address(insideIp)));\r
-            } else {\r
-                endpointL3Builder.setIpAddress(new IpAddress(new Ipv4Address(insideIp)));\r
-            }\r
+        NatAddressBuilder natAddressBuilder = new NatAddressBuilder();\r
+        natAddressBuilder.setNatAddress(new IpAddress(new Ipv4Address(natIp)));\r
+        endpointL3Builder.addAugmentation(NatAddress.class, natAddressBuilder.build());\r
+        endpointL3Builder.setIpAddress(new IpAddress(ip));\r
+        endpointL3Builder.setMacAddress(new MacAddress(mac));\r
+        if (l2bd != null) {\r
+            endpointL3Builder.setL2Context(new L2BridgeDomainId(l2bd));\r
         }\r
+        return endpointL3Builder;\r
+    }\r
 \r
-        // Set MAC\r
-        if (mac != null) {\r
-            endpointL3Builder.setMacAddress(new MacAddress(mac));\r
-        }\r
+    protected EndpointL3Builder buildL3Endpoint(Ipv6Address natIp, Ipv6Address ip, MacAddress mac, String l2bd) {\r
+        Preconditions.checkNotNull(natIp);\r
+        Preconditions.checkNotNull(ip);\r
+        Preconditions.checkNotNull(mac);\r
+        EndpointL3Builder endpointL3Builder = new EndpointL3Builder();\r
+        NatAddressBuilder natAddressBuilder = new NatAddressBuilder();\r
+        natAddressBuilder.setNatAddress(new IpAddress(new Ipv6Address(natIp)));\r
+        endpointL3Builder.addAugmentation(NatAddress.class, natAddressBuilder.build());\r
+        endpointL3Builder.setIpAddress(new IpAddress(ip));\r
 \r
-        // Set L2 context\r
-        if (l2 != null) {\r
-            endpointL3Builder.setL2Context(new L2BridgeDomainId(l2));\r
+        endpointL3Builder.setMacAddress(new MacAddress(mac));\r
+        if (l2bd != null) {\r
+            endpointL3Builder.setL2Context(new L2BridgeDomainId(l2bd));\r
         }\r
-\r
         return endpointL3Builder;\r
+    }\r
 \r
+    public SegmentationBuilder buildSegmentation() {\r
+        SegmentationBuilder segmentationBuilder = new SegmentationBuilder();\r
+        segmentationBuilder.setSegmentationId(1);\r
+        return  segmentationBuilder;\r
     }\r
 \r
-    protected IndexedTenant indexedTenantBuilder() {\r
+    protected TenantBuilder buildTenant() {\r
         TenantBuilder tenantBuilder = new TenantBuilder();\r
-        tenantBuilder.setId(new TenantId(TENANT_ID));\r
+        tenantBuilder.setId(TENANT_ID);\r
+        tenantBuilder.setForwardingContext(buildForwardingContext().build());\r
+        PolicyBuilder policyBuilder = new PolicyBuilder();\r
+        policyBuilder.setEndpointGroup(getEndpointGroups());\r
+        policyBuilder.setSubjectFeatureInstances(getSubjectFeatureInstances());\r
+        tenantBuilder.setPolicy(policyBuilder.build());\r
+        return tenantBuilder;\r
+    }\r
 \r
-        // Set forwarding context\r
-        SegmentationBuilder segmentationBuilder = new SegmentationBuilder();\r
-        segmentationBuilder.setSegmentationId(1);\r
-        List<L2FloodDomain> l2FloodDomains = new ArrayList<>();\r
-        L2FloodDomainBuilder l2FloodDomainBuilder = new L2FloodDomainBuilder();\r
-        l2FloodDomainBuilder.setId(new L2FloodDomainId("l2id"));\r
-        l2FloodDomainBuilder.addAugmentation(Segmentation.class, segmentationBuilder.build());\r
-        l2FloodDomains.add(l2FloodDomainBuilder.build());\r
+    protected IndexedTenant getTestIndexedTenant() {\r
+        return new IndexedTenant(buildTenant().build());\r
+    }\r
+\r
+    protected ForwardingContextBuilder buildForwardingContext() {\r
         ForwardingContextBuilder forwardingContextBuilder = new ForwardingContextBuilder();\r
-        forwardingContextBuilder.setL2FloodDomain(l2FloodDomains);\r
-        tenantBuilder.setForwardingContext(forwardingContextBuilder.build());\r
+        forwardingContextBuilder.setL2FloodDomain(getL2FloodDomainList(false));\r
+        forwardingContextBuilder.setL2BridgeDomain(getL2BridgeDomainList());\r
+        forwardingContextBuilder.setL3Context(getL3ContextList());\r
+        forwardingContextBuilder.setSubnet(getSubnetList());\r
+        return forwardingContextBuilder;\r
+    }\r
 \r
-        return new IndexedTenant(tenantBuilder.build());\r
+    protected List<L3Context> getL3ContextList() {\r
+        List<L3Context> l3Contexts = new ArrayList<>();\r
+        L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();\r
+        l3ContextBuilder.setId(L3C_ID);\r
+        l3Contexts.add(l3ContextBuilder.build());\r
+        return l3Contexts;\r
     }\r
 \r
-    protected List<L2FloodDomain> l2FloodDomains() {\r
-        SegmentationBuilder segmentationBuilder = new SegmentationBuilder();\r
-        segmentationBuilder.setSegmentationId(1);\r
+    protected List<L2BridgeDomain> getL2BridgeDomainList() {\r
+        List<L2BridgeDomain> l2BridgeDomains = new ArrayList<>();\r
+        L2BridgeDomainBuilder l2BridgeDomainBuilder = new L2BridgeDomainBuilder();\r
+        l2BridgeDomainBuilder.setId(L2BD_ID);\r
+        l2BridgeDomainBuilder.setParent(L3C_ID);\r
+        l2BridgeDomains.add(l2BridgeDomainBuilder.build());\r
+        return l2BridgeDomains;\r
+    }\r
+\r
+    protected List<L2FloodDomain> getL2FloodDomainList(boolean external) {\r
         List<L2FloodDomain> l2FloodDomains = new ArrayList<>();\r
         L2FloodDomainBuilder l2FloodDomainBuilder = new L2FloodDomainBuilder();\r
-        l2FloodDomainBuilder.setId(new L2FloodDomainId("l2id"));\r
-        l2FloodDomainBuilder.addAugmentation(Segmentation.class, segmentationBuilder.build());\r
+        l2FloodDomainBuilder.setId(L2FD_ID);\r
+        if (external) {\r
+            l2FloodDomainBuilder.setId(L2_FD_ID_EXT);\r
+        }\r
+        l2FloodDomainBuilder.setParent(new L2BridgeDomainId(L2BD_ID));\r
+        l2FloodDomainBuilder.addAugmentation(Segmentation.class, buildSegmentation().build());\r
         l2FloodDomains.add(l2FloodDomainBuilder.build());\r
         return l2FloodDomains;\r
     }\r
 \r
-    protected EndpointBuilder endpointBuilder(IpAddress ip, MacAddress mac, NodeConnectorId connector,\r
-                                              EndpointGroupId groupId, L2BridgeDomainId bridgeDomainId) {\r
-        EndpointBuilder endpointBuilder = new EndpointBuilder();\r
-\r
-        // Set tenant\r
-        endpointBuilder.setTenant(new TenantId(TENANT_ID));\r
-\r
-        // Set L3 address\r
-        if (ip != null) {\r
-            List<L3Address> l3Addresses = new ArrayList<>();\r
-            L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();\r
-            l3AddressBuilder.setIpAddress(ip);\r
-            l3Addresses.add(l3AddressBuilder.build());\r
-            endpointBuilder.setL3Address(l3Addresses);\r
-        }\r
+    protected List<L3Address> getL3AddressList(Ipv4Address l3IpAddress, L3ContextId l3ContextId) {\r
+        List<L3Address> l3Addresses = new ArrayList<>();\r
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();\r
+        l3AddressBuilder.setIpAddress(new IpAddress(l3IpAddress));\r
+        l3AddressBuilder.setL3Context(new L3ContextId(l3ContextId));\r
+        l3Addresses.add(l3AddressBuilder.build());\r
+        return l3Addresses;\r
+    }\r
 \r
-        // Set Mac address\r
-        endpointBuilder.setMacAddress(new MacAddress(mac));\r
-        endpointBuilder.setL2Context(bridgeDomainId);\r
-        endpointBuilder.setEndpointGroup(groupId);\r
+    protected List<L3Address> getL3AddressList(Ipv6Address l3IpAddress) {\r
+        List<L3Address> l3Addresses = new ArrayList<>();\r
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();\r
+        l3AddressBuilder.setIpAddress(new IpAddress(l3IpAddress));\r
+        l3Addresses.add(l3AddressBuilder.build());\r
+        return l3Addresses;\r
+    }\r
 \r
-        // Augment node connector\r
+    protected OfOverlayContextBuilder getOfOverlayContext(NodeConnectorId connector) {\r
         OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();\r
-        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(connector));\r
-        ofOverlayContextBuilder.setNodeId(nodeId);\r
-        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());\r
+        ofOverlayContextBuilder.setNodeConnectorId(connector);\r
+        ofOverlayContextBuilder.setNodeId(NODE_ID);\r
+        return ofOverlayContextBuilder;\r
+    }\r
 \r
-        // Set network containment\r
-        endpointBuilder.setNetworkContainment(new NetworkDomainId(DOMAIN_ID));\r
+    protected EndpointBuilder buildEndpoint(Ipv4Address l3IpAddress, MacAddress mac, NodeConnectorId connector) {\r
+        EndpointBuilder endpointBuilder = new EndpointBuilder();\r
+        endpointBuilder.setTenant(TENANT_ID);\r
+        endpointBuilder.setL3Address(getL3AddressList(l3IpAddress, L3C_ID));\r
+        endpointBuilder.setMacAddress(new MacAddress(mac));\r
+        endpointBuilder.setL2Context(new L2BridgeDomainId(L2BD_ID));\r
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);\r
+        endpointBuilder.addAugmentation(OfOverlayContext.class, getOfOverlayContext(connector).build());\r
+        endpointBuilder.setNetworkContainment(NET_DOMAIN_ID);\r
+        return endpointBuilder;\r
+    }\r
 \r
+    protected EndpointBuilder buildEndpoint(Ipv6Address l3IpAddress, MacAddress mac, NodeConnectorId connector) {\r
+        EndpointBuilder endpointBuilder = new EndpointBuilder();\r
+        endpointBuilder.setTenant(TENANT_ID);\r
+        endpointBuilder.setL3Address(getL3AddressList(l3IpAddress));\r
+        endpointBuilder.setMacAddress(new MacAddress(mac));\r
+        endpointBuilder.setL2Context(new L2BridgeDomainId(L2BD_ID));\r
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);\r
+        endpointBuilder.addAugmentation(OfOverlayContext.class, getOfOverlayContext(connector).build());\r
+        endpointBuilder.setNetworkContainment(NET_DOMAIN_ID);\r
         return endpointBuilder;\r
     }\r
 \r
-    protected List<EndpointGroup> endpointGroups() {\r
+    public List<EndpointGroup> getEndpointGroups() {\r
         return ImmutableList.of(\r
-                new EndpointGroupBuilder().setId(eg)\r
-                        .setNetworkDomain(sub)\r
+                new EndpointGroupBuilder().setId(ENDPOINT_GROUP_0)\r
+                        .setNetworkDomain(SUBNET_0)\r
                         .setConsumerNamedSelector(ImmutableList.of(new ConsumerNamedSelectorBuilder()\r
-                                .setName(new SelectorName("cns1")).setContract(ImmutableList.of(cid)).build()))\r
+                                .setName(new SelectorName("cns1")).setContract(ImmutableList.of(CONTRACT_ID)).build()))\r
                         .build(),\r
-                new EndpointGroupBuilder().setId(eg2)\r
-                        .setNetworkDomain(sub2)\r
+                new EndpointGroupBuilder().setId(ENDPOINT_GROUP_1)\r
+                        .setNetworkDomain(SUBNET_1)\r
                         .setProviderNamedSelector(ImmutableList.of(new ProviderNamedSelectorBuilder()\r
-                                .setName(new SelectorName("pns1")).setContract(ImmutableList.of(cid)).build()))\r
+                                .setName(new SelectorName("pns1")).setContract(ImmutableList.of(CONTRACT_ID)).build()))\r
                         .build());\r
     }\r
 \r
-    private SubjectFeatureInstances subjectFeatureInstances() {\r
+    protected SubjectFeatureInstances getSubjectFeatureInstances() {\r
         SubjectFeatureInstancesBuilder builder = new SubjectFeatureInstancesBuilder();\r
         return builder.setClassifierInstance(ImmutableList.of(new ClassifierInstanceBuilder()\r
                 .setName(new ClassifierName("tcp_dst_80"))\r
                 .setClassifierDefinitionId(L4ClassifierDefinition.DEFINITION.getId())\r
                 .setParameterValue(ImmutableList.of(new ParameterValueBuilder().setName(new ParameterName("destport"))\r
-                        .setIntValue(80L)\r
+                        .setIntValue(80L)        // Endpoint\r
+\r
                         .build(), new ParameterValueBuilder().setName(new ParameterName("proto"))\r
                         .setIntValue(6L)\r
                         .build()))\r
-                .build(), new ClassifierInstanceBuilder().setName(new ClassifierName("tcp_src_80"))\r
+                .build(), new ClassifierInstanceBuilder().setName(new ClassifierName(TCP_SRC))\r
                 .setClassifierDefinitionId(Classifier.L4_CL.getId())\r
                 .setParameterValue(ImmutableList.of(new ParameterValueBuilder().setName(new ParameterName("sourceport"))\r
                         .setIntValue(80L)\r
@@ -268,41 +316,26 @@ public abstract class MapperUtilsTest {
                 .build();\r
     }\r
 \r
-    protected TenantBuilder baseTenantBuilder() {\r
-        TenantBuilder tenantBuilder = new TenantBuilder();\r
-        tenantBuilder.setId(tid)\r
-                .setPolicy(new PolicyBuilder().setEndpointGroup(endpointGroups())\r
-                        .setSubjectFeatureInstances(subjectFeatureInstances())\r
-                        .build())\r
-                .setForwardingContext(new ForwardingContextBuilder()\r
-                        .setL3Context(ImmutableList.of(new L3ContextBuilder().setId(l3c).build()))\r
-                        .setL2FloodDomain(l2FloodDomains())\r
-                        .setSubnet(subnet())\r
-                        .build());\r
-        return tenantBuilder;\r
-    }\r
-\r
-    protected List<Subnet> subnet() {\r
+    protected List<Subnet> getSubnetList() {\r
         return ImmutableList.of(\r
-                new SubnetBuilder().setId(sub2)\r
-                        .setParent(fd)\r
+                new SubnetBuilder().setId(SUBNET_0)\r
+                        .setParent(L2FD_ID)\r
                         .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.1.0/24")))\r
                         .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.1.1")))\r
                         .build(),\r
-                new SubnetBuilder().setId(sub)\r
-                        .setParent(fd)\r
+                new SubnetBuilder().setId(SUBNET_1)\r
+                        .setParent(L2FD_ID)\r
                         .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.0.0/24")))\r
                         .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.0.1")))\r
                         .build(),\r
-                new SubnetBuilder().setId(sub3)\r
-                        .setParent(bd)\r
+                new SubnetBuilder().setId(SUBNET_2)\r
+                        .setParent(L2BD_ID)\r
                         .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.2.0/24")))\r
                         .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.2.1")))\r
                         .build(),\r
-                new SubnetBuilder()\r
-                        .setId(ext_sub)\r
+                new SubnetBuilder().setId(SUBNET_EXT)\r
+                        .setParent(L2_FD_ID_EXT)\r
                         .setIpPrefix(new IpPrefix(new Ipv4Prefix("192.168.111.0/24")))\r
-                        .setParent(ext_fd)\r
                         .build());\r
     }\r
 }\r
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperFlowsTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperFlowsTest.java
new file mode 100644 (file)
index 0000000..78dba01
--- /dev/null
@@ -0,0 +1,1215 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowIdUtils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.lang.reflect.Field;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.mockito.Mockito.*;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ OrdinalFactory.class })
+public class DestinationMapperFlowsTest extends MapperUtilsTest {
+
+    private DestinationMapperFlows flows;
+
+    @Before
+    public void init() throws Exception {
+        endpointManager = mock(EndpointManager.class);
+        policyManager = mock(PolicyManager.class);
+        policyInfo = mock(PolicyInfo.class);
+        ctx = mock(OfContext.class);
+        ofWriter = mock(OfWriter.class);
+        tableId = 3;
+        flows = new DestinationMapperFlows(new DestinationMapperUtils(ctx), NODE_ID, tableId);
+        resetPolicyOrdinalCounterValue();
+    }
+
+    @Test
+    public void testDropFlow_noEthertype() {
+        Flow testFlow = buildFlow(new FlowId(DROP_ALL), tableId, 100, null, FlowUtils.dropInstructions()).build();
+
+        flows.dropFlow(100, null, ofWriter);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
+    }
+
+    @Test
+    public void testDropFlow_ipV4Ethertype() {
+        MatchBuilder matchBuilder = new MatchBuilder();
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
+        Match match = matchBuilder.build();
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+                FlowUtils.dropInstructions()).build();
+
+        flows.dropFlow(100, FlowUtils.IPv4, ofWriter);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
+    }
+
+    @Test
+    public void testDropFlow_ipV6Ethertype() {
+        MatchBuilder matchBuilder = new MatchBuilder();
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv6));
+        Match match = matchBuilder.build();
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+                FlowUtils.dropInstructions()).build();
+
+        flows.dropFlow(100, FlowUtils.IPv6, ofWriter);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
+    }
+
+    @Test
+    public void testDropFlow_arpEthertype() {
+        MatchBuilder matchBuilder = new MatchBuilder();
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.ARP));
+        Match match = matchBuilder.build();
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+                FlowUtils.dropInstructions()).build();
+
+        flows.dropFlow(100, FlowUtils.ARP, ofWriter);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
+    }
+
+    @Test
+    public void createExternalL2Flow_exceptionCaught() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        Set<NodeConnectorId> externalConnectors = new HashSet<>();
+        externalConnectors.add(new NodeConnectorId(CONNECTOR_0));
+        externalConnectors.add(new NodeConnectorId(CONNECTOR_1));
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createExternalL2Flow(tableId, 100, endpointBuilder.build(), externalConnectors, ofWriter);
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createExternalL2Flow() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        Set<NodeConnectorId> externalConnectors = new HashSet<>();
+        externalConnectors.add(new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue()));
+        externalConnectors.add(new NodeConnectorId(OPENFLOW + CONNECTOR_1.getValue()));
+        Endpoint endpoint = endpointBuilder.build();
+
+        MatchBuilder matchBuilder = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null, endpoint.getMacAddress(), null));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg4.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+
+        ArrayList<Instruction> instructions = new ArrayList<>();
+        instructions.add(applyActionsIns);
+        instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(instructions);
+
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "externalL2", match);
+        Flow flow = buildFlow(flowId, tableId, 100, match, instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createExternalL2Flow(tableId, 100, endpointBuilder.build(), externalConnectors, ofWriter);
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createExternalL3RoutedFlow_nullIpAddress() {
+        EndpointBuilder gatewayBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        Endpoint gateway = gatewayBuilder.build();
+        Endpoint endpoint = endpointBuilder.build();
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(null);
+        Set<NodeConnectorId> externalConnectors = new HashSet<>();
+        externalConnectors.add(new NodeConnectorId(CONNECTOR_0));
+        externalConnectors.add(new NodeConnectorId(CONNECTOR_1));
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createExternalL3RoutedFlow(tableId, 90, endpoint, gateway, l3AddressBuilder.build(), externalConnectors,
+                ofWriter);
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createExternalL3RoutedFlow_exceptionCaught() {
+        EndpointBuilder gatewayBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        Endpoint gateway = gatewayBuilder.build();
+        Endpoint endpoint = endpointBuilder.build();
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv4Address(IPV4_0)));
+        Set<NodeConnectorId> externalConnectors = new HashSet<>();
+        externalConnectors.add(new NodeConnectorId(CONNECTOR_0));
+        externalConnectors.add(new NodeConnectorId(CONNECTOR_1));
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createExternalL3RoutedFlow(tableId, 90, endpoint, gateway, l3AddressBuilder.build(), externalConnectors,
+                ofWriter);
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createExternalL3RoutedFlow_ipV4() {
+        EndpointBuilder gatewayBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        Endpoint gateway = gatewayBuilder.build();
+        Endpoint endpoint = endpointBuilder.build();
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv4Address(IPV4_0)));
+        Set<NodeConnectorId> externalConnectors = new HashSet<>();
+        externalConnectors.add(new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue()));
+        externalConnectors.add(new NodeConnectorId(OPENFLOW + CONNECTOR_1.getValue()));
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlSrcAction(new MacAddress(MAC_0)));
+        l3ApplyActions.add(setDlDstAction(new MacAddress(MAC_0)));
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+        applyActions.addAll(l3ApplyActions);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, MAC_1, IPv4))
+                .setLayer3Match(new Ipv4MatchBuilder()
+                .setIpv4Destination(new Ipv4Prefix(IPV4_0.getValue() + IP_PREFIX_32)).build());
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        FlowId flowid = FlowIdUtils.newFlowId(tableId, "externalL3", match);
+        Flow flow = buildFlow(flowid, tableId, 90, match, instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createExternalL3RoutedFlow(tableId, 90, endpoint, gateway, l3AddressBuilder.build(), externalConnectors,
+                ofWriter);
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createExternalL3RoutedFlow_ipV6() {
+        EndpointBuilder gatewayBuilder = buildEndpoint(IPV4_1, MAC_0, CONNECTOR_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_2, MAC_1, CONNECTOR_1);
+        Endpoint gateway = gatewayBuilder.build();
+        Endpoint endpoint = endpointBuilder.build();
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv6Address(IPV6_1)));
+        Set<NodeConnectorId> externalConnectors = new HashSet<>();
+        externalConnectors.add(new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue()));
+        externalConnectors.add(new NodeConnectorId(OPENFLOW + CONNECTOR_1.getValue()));
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlSrcAction(new MacAddress(MAC_0)));
+        l3ApplyActions.add(setDlDstAction(new MacAddress(MAC_0)));
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+        applyActions.addAll(l3ApplyActions);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, MAC_1, IPv6))
+                .setLayer3Match(new Ipv6MatchBuilder()
+                .setIpv6Destination(new Ipv6Prefix(IPV6_1.getValue() + IP_PREFIX_128)).build());
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        FlowId flowid = FlowIdUtils.newFlowId(tableId, "externalL3", match);
+        Flow flow = buildFlow(flowid, tableId, 90, match, instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createExternalL3RoutedFlow(tableId, 90, endpoint, gateway, l3AddressBuilder.build(), externalConnectors,
+                ofWriter);
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createLocalL2Flow_exceptionCaught() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_0, CONNECTOR_0);
+        Endpoint endpoint = endpointBuilder.build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createLocalL2Flow(tableId, 80, endpoint, ofWriter);
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createLocalL2Flow() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_0, connectorId);
+        Endpoint endpoint = endpointBuilder.build();
+
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+
+        ArrayList<Instruction> instructions = new ArrayList<>();
+        instructions.add(applyActionsIns);
+        instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(instructions);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, endpoint.getMacAddress(),
+                null));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg4.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "localL2", match), tableId, 80, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createLocalL2Flow(tableId, 80, endpoint, ofWriter);
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createLocalL3RoutedFlow_nullL3Context() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(CONNECTOR_1));
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_0, connectorId);
+        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        Endpoint endpoint = endpointBuilder.build();
+        flows.createLocalL3RoutedFlow(tableId, 80, endpoint, null, null, null, ofWriter);
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createLocalL3RoutedFlow_noMac() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(CONNECTOR_1));
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, connectorId);
+        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        endpointBuilder.setTenant(getTestIndexedTenant().getTenant().getId());
+        endpointBuilder.setMacAddress(null);
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(SUBNET_0));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+
+        flows.createLocalL3RoutedFlow(tableId, 80, endpoint, null, localSubnet, destSubnet, ofWriter);
+        verify(ctx, times(1)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createLocalL3RoutedFlow_sameSubnetIdAndExceptionCaught() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(CONNECTOR_1));
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, connectorId);
+        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        endpointBuilder.setTenant(getTestIndexedTenant().getTenant().getId());
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+
+        flows.createLocalL3RoutedFlow(tableId, 80, endpoint, null, localSubnet, destSubnet, ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createLocalL3RoutedFlow_noIp() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(OPENFLOW + CONNECTOR_1));
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, connectorId);
+        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        endpointBuilder.setTenant(getTestIndexedTenant().getTenant().getId());
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(CONTEXT_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(null);
+        L3Address l3Address = l3AddressBuilder.build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createLocalL3RoutedFlow(tableId, 80, endpoint, l3Address, localSubnet, destSubnet, ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createLocalL3RoutedFlow_ipV4() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        MacAddress destMac = DestinationMapper.ROUTER_MAC;
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(connectorId));
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, connectorId);
+        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        endpointBuilder.setTenant(getTestIndexedTenant().getTenant().getId());
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(CONTEXT_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv4Address(IPV4_0)));
+        L3Address l3Address = l3AddressBuilder.build();
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlDstAction((new MacAddress(MAC_1))));
+        l3ApplyActions.add(decNwTtlAction());
+        l3ApplyActions.add(setDlSrcAction(destMac));
+
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+        applyActions.addAll(l3ApplyActions);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, new MacAddress(destMac), IPv4))
+                .setLayer3Match(new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(IPV4_0.getValue() + IP_PREFIX_32)).build());
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "localL3", match), tableId, 80, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createLocalL3RoutedFlow(tableId, 80, endpoint, l3Address, localSubnet, destSubnet, ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createLocalL3RoutedFlow_ipV6() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        MacAddress destMac = DestinationMapper.ROUTER_MAC;
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(connectorId);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1,MAC_1, connectorId);
+        endpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        endpointBuilder.setTenant(getTestIndexedTenant().getTenant().getId());
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(CONTEXT_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv6Address(IPV6_1)));
+        L3Address l3Address = l3AddressBuilder.build();
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlDstAction((new MacAddress(MAC_1))));
+        l3ApplyActions.add(decNwTtlAction());
+        l3ApplyActions.add(setDlSrcAction(destMac));
+
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+        applyActions.addAll(l3ApplyActions);
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, new MacAddress(destMac), IPv6))
+                .setLayer3Match(new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(IPV6_1.getValue() + IP_PREFIX_128)).build());
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "localL3", match), tableId, 80, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createLocalL3RoutedFlow(tableId, 80, endpoint, l3Address, localSubnet, destSubnet, ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createRemoteL2Flow_exceptionCaught() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, CONNECTOR_0);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL2Flow(tableId, 70, endpointBuilder.build(), null, null, new NodeConnectorId(CONNECTOR_1),
+                ofWriter);
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRemoteL2Flow_ipV4() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_1.getValue());
+        IpAddress ipAddress = new IpAddress(IPV4_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_0);
+        EndpointBuilder peerEndpointBuilder = buildEndpoint(IPV4_1, MAC_0, CONNECTOR_1);
+
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadTunIPv4Action(ipAddress.getIpv4Address().getValue(), false));
+
+        int order = 0;
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(order)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+
+        ArrayList<Instruction> instructions = new ArrayList<>();
+        instructions.add(applyActionsIns);
+        instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(instructions);
+
+        MatchBuilder matchBuilder = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null, new MacAddress(MAC_0), null));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg4.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "remoteL2", match), tableId, 70, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL2Flow(tableId, 70, endpointBuilder.build(), peerEndpointBuilder.build(), ipAddress,
+                connectorId, ofWriter);
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createRemoteL2Flow_ipV6() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_1);
+        IpAddress ipAddress = new IpAddress(new Ipv6Address(IPV6_1));
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, CONNECTOR_0);
+        EndpointBuilder peerEndpointBuilder = buildEndpoint(IPV6_2, MAC_0, CONNECTOR_0);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL2Flow(tableId, 70, endpointBuilder.build(), peerEndpointBuilder.build(), ipAddress,
+                connectorId, ofWriter);
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRemoteL3RoutedFlow_noL3Context() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, CONNECTOR_0);
+        Endpoint endpoint = endpointBuilder.build();
+        flows.createRemoteL3RoutedFlow(tableId, 60, endpoint, null, null, null, null, null, ofWriter);
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRemoteL3RoutedFlow_noMac() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, CONNECTOR_0);
+        endpointBuilder.setMacAddress(null);
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_1)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL3RoutedFlow(tableId, 60, endpoint, null, destSubnet, null, null, localSubnet, ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(2)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRemoteL3RoutedFlow_noIp() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1, MAC_1, CONNECTOR_0);
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_1)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL3RoutedFlow(tableId, 60, endpoint, null, destSubnet, null, null, localSubnet, ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRemoteL3RoutedFlow_incorrectPortId() {
+        IpAddress ipAddress = new IpAddress(new Ipv4Address(IPV4_0));
+        NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV6_1,MAC_1,CONNECTOR_0);
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(SUBNET_0));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_1)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL3RoutedFlow(tableId, 60, endpoint, null, destSubnet, ipAddress, connectorId, localSubnet,
+                ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRemoteL3RoutedFlow_ipV4() {
+        MacAddress routerMac = DestinationMapper.ROUTER_MAC;
+        IpAddress ipAddress = new IpAddress(new Ipv4Address(IPV4_1));
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv4Address(IPV4_1)));
+        L3Address l3Address = l3AddressBuilder.build();
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_0);
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(SUBNET_0));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_1)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlSrcAction(new MacAddress(routerMac)));
+        l3ApplyActions.add(setDlDstAction(new MacAddress(MAC_1)));
+        l3ApplyActions.add(decNwTtlAction());
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadTunIPv4Action(IPV4_1.getValue(), false));
+        applyActions.addAll(l3ApplyActions);
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(0)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(1)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, new MacAddress(routerMac), IPv4))
+                .setLayer3Match(new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(IPV4_1.getValue() + IP_PREFIX_32)).build());
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "remoteL3", match), tableId, 60, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL3RoutedFlow(tableId, 60, endpoint, l3Address, destSubnet, ipAddress, connectorId, localSubnet,
+                ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(eq(NODE_ID), eq(tableId), eq(flow));
+    }
+
+    @Test
+    public void createRemoteL3RoutedFlow_ipV6() {
+        IpAddress ipAddress = new IpAddress(new Ipv6Address(IPV6_1));
+        L3AddressBuilder l3AddressBuilder = new L3AddressBuilder();
+        l3AddressBuilder.setIpAddress(new IpAddress(new Ipv4Address(IPV4_1)));
+        L3Address l3Address = l3AddressBuilder.build();
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_0);
+        Endpoint endpoint = endpointBuilder.build();
+
+        SubnetBuilder destSubnetBuilder = new SubnetBuilder();
+        destSubnetBuilder.setId(new SubnetId(L3C_ID));
+        Subnet destSubnet = destSubnetBuilder.build();
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(SUBNET_0));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_1)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createRemoteL3RoutedFlow(tableId, 60, endpoint, l3Address, destSubnet, ipAddress, connectorId, localSubnet,
+                ofWriter);
+        verify(ctx, times(3)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRouterArpFlow_nullL3SubnetContext() throws Exception {
+        IndexedTenant tenant = getTestIndexedTenant();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId("otherSubnet"));
+        flows.createRouterArpFlow(50, tenant, subnetBuilder.build(), ofWriter);
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createRouterArpFlow_ipV4() throws Exception {
+        IndexedTenant tenant = getTestIndexedTenant();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, ARP))
+                .setLayer3Match(new ArpMatchBuilder().setArpOp(1)
+                        .setArpTargetTransportAddress(new Ipv4Prefix(IPV4_0.getValue() + IP_PREFIX_32)).build());
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 1));
+        Match match = matchBuilder.build();
+
+        List<Action> actions = new ArrayList<>();
+        actions.add(nxMoveEthSrcToEthDstAction());
+        actions.add(setDlSrcAction(new MacAddress(DestinationMapper.ROUTER_MAC)));
+        actions.add(nxLoadArpOpAction(BigInteger.valueOf(2L)));
+        actions.add(nxMoveArpShaToArpThaAction());
+        actions.add(nxLoadArpShaAction(new BigInteger(1, bytesFromHexString(DestinationMapper.ROUTER_MAC.getValue()))));
+        actions.add(nxMoveArpSpaToArpTpaAction());
+        actions.add(nxLoadArpSpaAction(IPV4_0.getValue()));
+        actions.add(outputAction(new NodeConnectorId(NODE_ID.getValue() + ":INPORT")));
+        List<Instruction> instructions = new ArrayList<>();
+        InstructionBuilder instructionBuilder = new InstructionBuilder();
+        instructionBuilder.setInstruction(applyActionIns(actions.toArray(new Action[actions.size()]))).setOrder(0);
+        instructions.add(instructionBuilder.build());
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(instructions);
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "routerarp", match), tableId, 50, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        flows.createRouterArpFlow(50, tenant, subnetBuilder.build(), ofWriter);
+
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ofWriter, times(1)).writeFlow(any(NodeId.class), anyShort(), eq(flow));
+    }
+
+    @Test
+    public void createRouterArpFlow_ipV6() throws Exception {
+        IndexedTenant tenant = getTestIndexedTenant();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv6Address(IPV6_1)));
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+
+        flows.createRouterArpFlow(50, tenant, subnetBuilder.build(), ofWriter);
+
+        verify(ctx, times(1)).getEndpointManager();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createBroadcastFlow() {
+        DestinationMapperUtils utils = new DestinationMapperUtils(ctx);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1);
+        endpointBuilder.setTenant(buildTenant().getId());
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpointBuilder.build());
+
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(1)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+
+        MatchBuilder matchBuilder = new MatchBuilder()
+                .setEthernetMatch(new EthernetMatchBuilder()
+                        .setEthernetDestination(new EthernetDestinationBuilder().setAddress(new MacAddress(MAC_0))
+                                .setMask(new MacAddress(MAC_0)).build())
+                        .build());
+        addNxRegMatch(matchBuilder, FlowUtils.RegMatch.of(NxmNxReg5.class, (long) ordinals.getFdId()));
+        Match match = matchBuilder.build();
+        List<Action> actions = new ArrayList<>();
+        actions.add(nxLoadTunIdAction(BigInteger.valueOf(ordinals.getFdId()), false));
+        actions.add(groupAction((long) ordinals.getFdId()));
+        List<Instruction> instructions = new ArrayList<>();
+        InstructionBuilder instructionBuilder = new InstructionBuilder();
+        instructionBuilder.setInstruction(applyActionIns(actions.toArray(new Action[actions.size()]))).setOrder(0);
+        instructions.add(instructionBuilder.build());
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(instructions);
+
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "broadcast", match), tableId, 40, match,
+                instructionsBuilder.build()).build();
+
+        flows.createBroadcastFlow(40, ordinals, new MacAddress(MAC_0), ofWriter);
+
+        verify(ofWriter, times(1)).writeFlow(any(NodeId.class), anyShort(), eq(flow));
+    }
+
+    @Test
+    public void createL3PrefixFlow_internalExceptionCaught() {
+        EndpointBuilder gatewayEp = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(CONNECTOR_1));
+        gatewayEp.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+
+        IndexedTenant tenant = getTestIndexedTenant();
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+
+        flows.createL3PrefixFlow(tableId, 30, gatewayEp.build(), null, tenant, localSubnet, null, ofWriter);
+        verify(ctx, times(1)).getEndpointManager();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createL3PrefixFlow_externalExceptionCaught() {
+        EndpointBuilder gatewayEpBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(CONNECTOR_1));
+        gatewayEpBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        gatewayEpBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
+
+        TenantBuilder tenantBuilder = new TenantBuilder(getTestIndexedTenant().getTenant());
+        List<ExternalImplicitGroup> externalImplicitGroups = new ArrayList<>();
+        ExternalImplicitGroupBuilder externalImplicitGroupBuilder = new ExternalImplicitGroupBuilder();
+        externalImplicitGroupBuilder.setId(ENDPOINT_GROUP_0);
+        externalImplicitGroups.add(externalImplicitGroupBuilder.build());
+        tenantBuilder.setPolicy(new PolicyBuilder().setExternalImplicitGroup(externalImplicitGroups).build());
+        IndexedTenant tenant = new IndexedTenant(tenantBuilder.build());
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        Set<NodeConnectorId> externalPorts = new HashSet<>();
+        externalPorts.add(new NodeConnectorId(CONNECTOR_0));
+        externalPorts.add(new NodeConnectorId(CONNECTOR_1));
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+
+        flows.createL3PrefixFlow(tableId, 30, gatewayEpBuilder.build(), null, tenant, localSubnet, externalPorts,
+                ofWriter);
+        verify(ctx, times(1)).getEndpointManager();
+        verifyZeroInteractions(ofWriter);
+    }
+
+    @Test
+    public void createL3PrefixFlow_internalIpV4() {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        EndpointBuilder gatewayEp = buildEndpoint(IPV4_0, MAC_0, connectorId);
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(OPENFLOW + CONNECTOR_1.getValue()));
+        gatewayEp.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+
+        EndpointL3PrefixBuilder l3PrefixBuilder = new EndpointL3PrefixBuilder();
+        l3PrefixBuilder.setIpPrefix(new IpPrefix(new Ipv4Prefix(IPV4_0.getValue() + IP_PREFIX_32)));
+        EndpointL3Prefix l3Prefix = l3PrefixBuilder.build();
+
+        IndexedTenant tenant = getTestIndexedTenant();
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlDstAction(new MacAddress(MAC_0)));
+        l3ApplyActions.add(decNwTtlAction());
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(1)));
+        applyActions.addAll(l3ApplyActions);
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(0)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(1)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null,
+                new MacAddress(DestinationMapper.ROUTER_MAC), IPv4));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        Integer prefixLength = Integer.valueOf(l3Prefix.getIpPrefix().getIpv4Prefix().getValue().split("/")[1]);
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "L3prefix", match), tableId, 30 + prefixLength, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createL3PrefixFlow(tableId, 30, gatewayEp.build(), l3Prefix, tenant, localSubnet, null,
+                ofWriter);
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(2)).getEndpointManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(any(NodeId.class), anyShort(), eq(flow));
+    }
+
+    @Test
+    public void createL3PrefixFlow_externalIpv6() throws Exception {
+        NodeConnectorId connectorId = new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue());
+        EndpointBuilder gatewayEpBuilder = buildEndpoint(IPV6_1, MAC_0, connectorId);
+
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(OPENFLOW + CONNECTOR_1));
+        gatewayEpBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        gatewayEpBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
+
+        TenantBuilder tenantBuilder = new TenantBuilder(getTestIndexedTenant().getTenant());
+        List<ExternalImplicitGroup> externalImplicitGroups = new ArrayList<>();
+        ExternalImplicitGroupBuilder externalImplicitGroupBuilder = new ExternalImplicitGroupBuilder();
+        externalImplicitGroupBuilder.setId(ENDPOINT_GROUP_0);
+        externalImplicitGroups.add(externalImplicitGroupBuilder.build());
+        tenantBuilder.setPolicy(new PolicyBuilder().setExternalImplicitGroup(externalImplicitGroups).build());
+        IndexedTenant tenant = new IndexedTenant(tenantBuilder.build());
+
+        SubnetBuilder localSubnetBuilder = new SubnetBuilder();
+        localSubnetBuilder.setId(new SubnetId(L3C_ID));
+        localSubnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv6Address(IPV6_2)));
+        Subnet localSubnet = localSubnetBuilder.build();
+
+        Set<NodeConnectorId> externalPorts = new HashSet<>();
+        externalPorts.add(new NodeConnectorId(OPENFLOW + CONNECTOR_0.getValue()));
+        externalPorts.add(new NodeConnectorId(OPENFLOW + CONNECTOR_1.getValue()));
+
+        EndpointL3PrefixBuilder l3PrefixBuilder = new EndpointL3PrefixBuilder();
+        l3PrefixBuilder.setIpPrefix(new IpPrefix(new Ipv6Prefix(IPV6_1.getValue() + IP_PREFIX_128)));
+        EndpointL3Prefix l3Prefix = l3PrefixBuilder.build();
+
+        List<Action> l3ApplyActions = new ArrayList<>();
+        l3ApplyActions.add(setDlDstAction(new MacAddress(MAC_0)));
+        l3ApplyActions.add(decNwTtlAction());
+        List<Action> applyActions = new ArrayList<>();
+        applyActions.add(nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(1)));
+        applyActions.add(nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(0)));
+        applyActions.add(nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(0)));
+        applyActions.addAll(l3ApplyActions);
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(0)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
+        Instruction gotoTable = new InstructionBuilder().setOrder(1)
+                .setInstruction(gotoTableIns(tableId))
+                .build();
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        l3instructions.add(applyActionsIns);
+        l3instructions.add(gotoTable);
+        InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
+        instructionsBuilder.setInstruction(l3instructions);
+
+        MatchBuilder matchBuilder = new MatchBuilder().setEthernetMatch(ethernetMatch(null,
+                new MacAddress(DestinationMapper.ROUTER_MAC), IPv6));
+        addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, (long) 0));
+        Match match = matchBuilder.build();
+
+        Integer prefixLength = Integer.valueOf(l3Prefix.getIpPrefix().getIpv6Prefix().getValue().split("/")[1]);
+        Flow flow = buildFlow(FlowIdUtils.newFlowId(tableId, "L3prefix", match), tableId, 30 + prefixLength, match,
+                instructionsBuilder.build()).build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        flows.createL3PrefixFlow(tableId, 30, gatewayEpBuilder.build(), l3Prefix, tenant, localSubnet, externalPorts,
+                ofWriter);
+
+        verify(ctx, times(4)).getTenant(any(TenantId.class));
+        verify(ctx, times(3)).getEndpointManager();
+        verify(ctx, times(2)).getCurrentPolicy();
+        verify(ofWriter, times(1)).writeFlow(any(NodeId.class), anyShort(), eq(flow));
+    }
+
+    private void resetPolicyOrdinalCounterValue() throws  Exception {
+        // TODO find better way, maybe fixed test method order?
+        Field field = OrdinalFactory.class.getDeclaredField("policyOrdinal");
+        field.setAccessible(true);
+        field.set(null, new AtomicInteger(1));
+    }
+}
\ No newline at end of file
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperTest.java
new file mode 100644 (file)
index 0000000..40b3d08
--- /dev/null
@@ -0,0 +1,433 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination;
+
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.opendaylight.groupbasedpolicy.dto.EgKey;
+import org.opendaylight.groupbasedpolicy.dto.EpKey;
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.PolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.mockito.Mockito.*;
+
+public class DestinationMapperTest extends MapperUtilsTest {
+
+    private DestinationMapper destinationMapper;
+
+    @Before
+    public void init() {
+        tableId = 3;
+        endpointManager = mock(EndpointManager.class);
+        policyManager = mock(PolicyManager.class);
+        switchManager = mock(SwitchManager.class);
+        policyInfo = mock(PolicyInfo.class);
+        ctx = mock(OfContext.class);
+        ofWriter = mock(OfWriter.class);
+        destinationMapper = new DestinationMapper(ctx, tableId);
+    }
+
+    @Test
+    public void getTableId() {
+        assertTrue(destinationMapper.getTableId() == tableId);
+    }
+
+    @Test
+    public void syncFlows() throws Exception {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getPolicyManager()).thenReturn(policyManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        destinationMapper.syncFlows(flows, endpointBuilder.build(), null, ofWriter);
+
+        // Verify usage
+        verify(ctx, times(2)).getTenant(any(TenantId.class));
+        verify(ctx, times(5)).getEndpointManager();
+        verify(ctx, times(2)).getPolicyManager();
+        verify(ctx, times(2)).getCurrentPolicy();
+
+        //Verify order
+        InOrder order = inOrder(flows);
+        order.verify(flows, times(1)).dropFlow(anyInt(), anyLong(), eq(ofWriter));
+        order.verify(flows, times(1)).createBroadcastFlow(anyInt(), any(OrdinalFactory.EndpointFwdCtxOrdinals.class),
+                any(MacAddress.class), eq(ofWriter));
+    }
+
+    @Test
+    public void syncExternalEndpointFlows_L2Flow() {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        // External ports
+        Set<NodeConnectorId> externalPorts = new HashSet<>();
+        externalPorts.add(CONNECTOR_0);
+        externalPorts.add(CONNECTOR_1);
+        // Endpoint
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        // Peer endpoint
+        EndpointBuilder peerEndpointBuilder = buildEndpoint(IPV4_2, MAC_0, CONNECTOR_0);
+        // External Implicit groups
+        List<ExternalImplicitGroup> externalImplicitGroups = new ArrayList<>();
+        ExternalImplicitGroupBuilder externalImplicitGroupBuilder = new ExternalImplicitGroupBuilder();
+        externalImplicitGroupBuilder.setId(ENDPOINT_GROUP_0);
+        externalImplicitGroups.add(externalImplicitGroupBuilder.build());
+        TenantBuilder peerTenantBuilder = buildTenant();
+        peerTenantBuilder.setPolicy(new PolicyBuilder()
+                .setEndpointGroup(getEndpointGroups())
+                .setSubjectFeatureInstances(getSubjectFeatureInstances())
+                .setExternalImplicitGroup(externalImplicitGroups)
+                .build());
+        Endpoint peerEndpoint = peerEndpointBuilder.build();
+        Collection<Endpoint> peerEndpoints = new ArrayList<>();
+        peerEndpoints.add(peerEndpoint);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(peerTenantBuilder.build()));
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getPolicyManager()).thenReturn(policyManager);
+        when(ctx.getSwitchManager()).thenReturn(switchManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+        when(endpointManager.getEndpointsForGroup(any(EgKey.class))).thenReturn(peerEndpoints);
+        when(endpointManager.getEndpointsForNode(any(NodeId.class))).thenReturn(peerEndpoints);
+        when(switchManager.getExternalPorts(any(NodeId.class))).thenReturn(externalPorts);
+
+        destinationMapper.syncEndpointFlows(flows, NODE_ID, endpointBuilder.build(), ofWriter);
+
+        // Verify usage
+        verify(ctx, times(11)).getTenant(any(TenantId.class));
+        verify(ctx, times(6)).getEndpointManager();
+        verify(ctx, times(1)).getPolicyManager();
+        verify(ctx, times(4)).getCurrentPolicy();
+        verify(flows, times(1)).createExternalL2Flow(anyShort(), anyInt(), any(Endpoint.class),
+                anySetOf(NodeConnectorId.class), eq(ofWriter));
+    }
+
+    @Test
+    public void syncExternalEndpointFlows_L3Flow() {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        // L3 Endpoint prefix
+        Collection<EndpointL3Prefix> endpointL3PrefixCollection = new HashSet<>();
+        List<EndpointL3Gateways> endpointL3GatewaysList = new ArrayList<>();
+        EndpointL3PrefixBuilder endpointL3PrefixBuilder = new EndpointL3PrefixBuilder();
+        EndpointL3GatewaysBuilder endpointL3GatewaysBuilder = new EndpointL3GatewaysBuilder();
+        endpointL3GatewaysList.add(endpointL3GatewaysBuilder.build());
+        endpointL3PrefixBuilder.setEndpointL3Gateways(endpointL3GatewaysList);
+        endpointL3PrefixCollection.add(endpointL3PrefixBuilder.build());
+        // External ports
+        Set<NodeConnectorId> externalPorts = new HashSet<>();
+        externalPorts.add(new NodeConnectorId(CONNECTOR_0));
+        externalPorts.add(new NodeConnectorId(CONNECTOR_1));
+        // Endpoint
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        endpointBuilder.setL3Address(getL3AddressList(IPV4_1, L3C_ID));
+        endpointBuilder.setNetworkContainment(new NetworkDomainId(SUBNET_0));
+        Endpoint endpoint = endpointBuilder.build();
+        // Peer
+        EndpointBuilder peerEndpointBuilder = buildEndpoint(IPV4_2, MAC_0, CONNECTOR_0);
+        peerEndpointBuilder.setNetworkContainment(new NetworkDomainId(SUBNET_0));
+        // External implicit groups
+        List<Subnet> subnets = new ArrayList<>();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_0));
+        subnetBuilder.setParent(new ContextId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_2)));
+        subnets.add(subnetBuilder.build());
+        List<L3Context> l3Contexts = new ArrayList<>();
+        L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
+        l3ContextBuilder.setId(L3C_ID);
+        l3Contexts.add(l3ContextBuilder.build());
+        List<ExternalImplicitGroup> externalImplicitGroups = new ArrayList<>();
+        ExternalImplicitGroupBuilder externalImplicitGroupBuilder = new ExternalImplicitGroupBuilder();
+        externalImplicitGroupBuilder.setId(ENDPOINT_GROUP_0);
+        externalImplicitGroups.add(externalImplicitGroupBuilder.build());
+        ForwardingContextBuilder forwardingContextBuilder = new ForwardingContextBuilder();
+        forwardingContextBuilder.setSubnet(subnets);
+        forwardingContextBuilder.setL3Context(l3Contexts);
+        TenantBuilder peerTenantBuilder = buildTenant();
+        peerTenantBuilder.setForwardingContext(forwardingContextBuilder.build());
+        peerTenantBuilder.setPolicy(new PolicyBuilder()
+                .setSubjectFeatureInstances(getSubjectFeatureInstances())
+                .setEndpointGroup(getEndpointGroups())
+                .setExternalImplicitGroup(externalImplicitGroups)
+                .build());
+        Tenant peerTenant = peerTenantBuilder.build();
+        peerEndpointBuilder.setNetworkContainment(new NetworkDomainId(SUBNET_1));
+        Endpoint peerEndpoint = peerEndpointBuilder.build();
+        Collection<Endpoint> peerEndpoints = new ArrayList<>();
+        peerEndpoints.add(peerEndpoint);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(peerTenant));
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getPolicyManager()).thenReturn(policyManager);
+        when(ctx.getSwitchManager()).thenReturn(switchManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+        when(endpointManager.getEndpointsForGroup(any(EgKey.class))).thenReturn(peerEndpoints);
+        when(endpointManager.getEndpointsForNode(any(NodeId.class))).thenReturn(peerEndpoints);
+        when(endpointManager.getEndpointsL3PrefixForTenant(any(TenantId.class))).thenReturn(endpointL3PrefixCollection);
+        when(endpointManager.getL3Endpoint(any(L3ContextId.class), any(IpAddress.class), any(TenantId.class)))
+                .thenReturn(buildL3Endpoint(IPV4_1, IPV4_2, MAC_0, L2BD_ID.getValue()).build());
+        when(endpointManager.getEndpoint(any(EpKey.class))).thenReturn(endpoint);
+        when(switchManager.getExternalPorts(any(NodeId.class))).thenReturn(externalPorts);
+
+        destinationMapper.syncEndpointFlows(flows, NODE_ID, endpoint, ofWriter);
+
+        // Verify usage
+        verify(ctx, times(13)).getTenant(any(TenantId.class));
+        verify(ctx, times(9)).getEndpointManager();
+        verify(ctx, times(1)).getPolicyManager();
+        verify(ctx, times(4)).getCurrentPolicy();
+        verify(flows, times(1)).createExternalL3RoutedFlow(anyShort(), anyInt(), any(Endpoint.class), any(Endpoint.class),
+                any(L3Address.class), anySetOf(NodeConnectorId.class), eq(ofWriter));
+    }
+
+    @Test
+    public void syncLocalEndpointFlows() {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        // Endpoint
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        endpointBuilder.setNetworkContainment(SUBNET_0);
+        // Peer
+        EndpointBuilder peerEndpointBuilder = buildEndpoint(IPV4_2, MAC_0, CONNECTOR_0);
+        // Subnets, l3Context and forwarding context
+        List<Subnet> subnets = new ArrayList<>();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_0));
+        subnetBuilder.setParent(new ContextId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_2)));
+        subnets.add(subnetBuilder.build());
+        List<L3Context> l3Contexts = new ArrayList<>();
+        L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
+        l3ContextBuilder.setId(L3C_ID);
+        l3Contexts.add(l3ContextBuilder.build());
+        ForwardingContextBuilder forwardingContextBuilder = new ForwardingContextBuilder();
+        forwardingContextBuilder.setSubnet(subnets);
+        forwardingContextBuilder.setL3Context(l3Contexts);
+        TenantBuilder peerTenantBuilder = new TenantBuilder(getTestIndexedTenant().getTenant());
+        peerTenantBuilder.setForwardingContext(forwardingContextBuilder.build());
+        Tenant peerTenant = peerTenantBuilder.build();
+        peerEndpointBuilder.setNetworkContainment(new NetworkDomainId(SUBNET_0));
+        Endpoint peerEndpoint = peerEndpointBuilder.build();
+        Collection<Endpoint> peerEndpoints = new ArrayList<>();
+        peerEndpoints.add(peerEndpoint);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(peerTenant));
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getPolicyManager()).thenReturn(policyManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+        when(endpointManager.getEndpointsForGroup(any(EgKey.class))).thenReturn(peerEndpoints);
+        when(endpointManager.getEndpointsForNode(any(NodeId.class))).thenReturn(peerEndpoints);
+
+        destinationMapper.syncFlows(flows, endpointBuilder.build(), NODE_ID, ofWriter);
+
+        // Verify usage
+        verify(ctx, times(18)).getTenant(any(TenantId.class));
+        verify(ctx, times(9)).getEndpointManager();
+        verify(ctx, times(2)).getPolicyManager();
+        verify(ctx, times(4)).getCurrentPolicy();
+
+        // Verify order
+        InOrder order = inOrder(flows);
+        order.verify(flows, times(1)).createLocalL2Flow(anyShort(), anyInt(), any(Endpoint.class), eq(ofWriter));
+        order.verify(flows, times(1)).createLocalL3RoutedFlow(anyShort(), anyInt(), any(Endpoint.class),
+                any(L3Address.class), any(Subnet.class), any(Subnet.class), eq(ofWriter));
+    }
+
+    @Test
+    public void syncRemoteEndpointFlows() {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        // Endpoint
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        // Peer
+        EndpointBuilder peerEndpointBuilder = buildEndpoint(IPV4_2, MAC_0, CONNECTOR_0);
+        // Subnets, l3Context and forwarding context
+        List<Subnet> subnets = new ArrayList<>();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_0));
+        subnetBuilder.setParent(new ContextId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_2)));
+        subnets.add(subnetBuilder.build());
+        List<L3Context> l3Contexts = new ArrayList<>();
+        L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
+        l3ContextBuilder.setId(L3C_ID);
+        l3Contexts.add(l3ContextBuilder.build());
+        ForwardingContextBuilder forwardingContextBuilder = new ForwardingContextBuilder();
+        forwardingContextBuilder.setSubnet(subnets);
+        forwardingContextBuilder.setL3Context(l3Contexts);
+        TenantBuilder peerTenantBuilder = buildTenant();
+        peerTenantBuilder.setForwardingContext(forwardingContextBuilder.build());
+        Tenant peerTenant = peerTenantBuilder.build();
+        // Augmentation
+        OfOverlayContextBuilder ofOverlayContextBuilder = new OfOverlayContextBuilder();
+        ofOverlayContextBuilder.setNodeConnectorId(new NodeConnectorId(CONNECTOR_0));
+        ofOverlayContextBuilder.setNodeId(new NodeId("remoteNodeID"));
+        peerEndpointBuilder.setNetworkContainment(new NetworkDomainId(SUBNET_0));
+        peerEndpointBuilder.addAugmentation(OfOverlayContext.class, ofOverlayContextBuilder.build());
+        Endpoint peerEndpoint = peerEndpointBuilder.build();
+        Collection<Endpoint> peerEndpoints = new ArrayList<>();
+        peerEndpoints.add(peerEndpoint);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(peerTenant));
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getPolicyManager()).thenReturn(policyManager);
+        when(ctx.getSwitchManager()).thenReturn(switchManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+        when(endpointManager.getEndpointsForGroup(any(EgKey.class))).thenReturn(peerEndpoints);
+        when(endpointManager.getEndpointsForNode(any(NodeId.class))).thenReturn(peerEndpoints);
+        when(switchManager.getTunnelIP(any(NodeId.class), eq(TunnelTypeVxlan.class)))
+                .thenReturn(new IpAddress(new Ipv4Address(IPV4_2)));
+        when(switchManager.getTunnelPort(any(NodeId.class), eq(TunnelTypeVxlan.class)))
+                .thenReturn(new NodeConnectorId(CONNECTOR_2));
+
+        destinationMapper.syncEndpointFlows(flows, NODE_ID, endpointBuilder.build(), ofWriter);
+
+        // Verify usage
+        verify(ctx, times(13)).getTenant(any(TenantId.class));
+        verify(ctx, times(5)).getEndpointManager();
+        verify(ctx, times(1)).getPolicyManager();
+        verify(ctx, times(3)).getCurrentPolicy();
+
+        // Verify order
+        InOrder order = inOrder(flows);
+        order.verify(flows, times(1)).createRemoteL2Flow(anyShort(), anyInt(), any(Endpoint.class), any(Endpoint.class),
+                any(IpAddress.class), any(NodeConnectorId.class), eq(ofWriter));
+        order.verify(flows, times(1)).createRemoteL3RoutedFlow(anyShort(), anyInt(), any(Endpoint.class),
+                any(L3Address.class), any(Subnet.class), any(IpAddress.class), any(NodeConnectorId.class),
+                any(Subnet.class), eq(ofWriter));
+    }
+
+    @Test
+    public void syncArpFlow() throws Exception {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        // Subnets, l3Context and forwarding context
+        List<L3Context> l3Contexts = new ArrayList<>();
+        L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
+        l3ContextBuilder.setId(L3C_ID);
+        l3Contexts.add(l3ContextBuilder.build());
+        HashSet<Subnet> subnets = new HashSet<>();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_0));
+        subnetBuilder.setParent(new ContextId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_2)));
+        subnets.add(subnetBuilder.build());
+        ForwardingContextBuilder forwardingContextBuilder = new ForwardingContextBuilder();
+        forwardingContextBuilder.setSubnet(new ArrayList<>(subnets));
+        forwardingContextBuilder.setL3Context(l3Contexts);
+        TenantBuilder tenantBuilder = buildTenant();
+        tenantBuilder.setForwardingContext(forwardingContextBuilder.build());
+        Tenant tenant = tenantBuilder.build();
+        destinationMapper.subnetsByTenant.put(tenant.getId(), subnets);
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(tenant));
+
+        destinationMapper.syncArpFlow(flows, tenant.getId(), ofWriter);
+
+        verify(ctx, times(1)).getTenant(any(TenantId.class));
+        verify(flows, times(1)).createRouterArpFlow(anyInt(), any(IndexedTenant.class), any(Subnet.class), eq(ofWriter));
+    }
+
+    @Test
+    public void syncL3PrefixFlow() {
+        DestinationMapperFlows flows = mock(DestinationMapperFlows.class);
+        // Subnets, l3Context and forwarding context
+        List<L3Context> l3Contexts = new ArrayList<>();
+        L3ContextBuilder l3ContextBuilder = new L3ContextBuilder();
+        l3ContextBuilder.setId(L3C_ID);
+        l3Contexts.add(l3ContextBuilder.build());
+        HashSet<Subnet> subnets = new HashSet<>();
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_0));
+        subnetBuilder.setParent(new ContextId(L3C_ID));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(IPV4_2));
+        subnets.add(subnetBuilder.build());
+        ForwardingContextBuilder forwardingContextBuilder = new ForwardingContextBuilder();
+        forwardingContextBuilder.setL3Context(l3Contexts);
+        forwardingContextBuilder.setSubnet(new ArrayList<>(subnets));
+        TenantBuilder tenantBuilder = buildTenant();
+        tenantBuilder.setForwardingContext(forwardingContextBuilder.build());
+        Tenant tenant = tenantBuilder.build();
+        Collection<Endpoint> endpoints = new ArrayList<>();
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
+        endpointBuilder.setNetworkContainment(new NetworkDomainId(SUBNET_0));
+        Endpoint endpoint = endpointBuilder.build();
+        endpoints.add(endpoint);
+
+        ArrayList<EndpointL3Prefix> l3Prefixes = new ArrayList<>();
+        EndpointL3PrefixBuilder prefixBuilder = new EndpointL3PrefixBuilder();
+        List<EndpointL3Gateways> endpointL3GatewaysList = new ArrayList<>();
+        EndpointL3GatewaysBuilder endpointL3GatewaysBuilder = new EndpointL3GatewaysBuilder();
+        endpointL3GatewaysBuilder.setIpAddress(new IpAddress(new Ipv4Address(IPV4_1)));
+        endpointL3GatewaysBuilder.setL3Context(L3C_ID);
+        endpointL3GatewaysList.add(endpointL3GatewaysBuilder.build());
+        prefixBuilder.setEndpointL3Gateways(endpointL3GatewaysList);
+        l3Prefixes.add(prefixBuilder.build());
+
+        EndpointL3 endpointL3 = buildL3Endpoint(IPV4_0, IPV4_2, MAC_2, L2).build();
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(tenant));
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getSwitchManager()).thenReturn(switchManager);
+        when(ctx.getPolicyManager()).thenReturn(policyManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+        when(endpointManager.getEndpointsForNode(any(NodeId.class))).thenReturn(endpoints);
+        when(endpointManager.getL3Endpoint(any(L3ContextId.class), any(IpAddress.class), any(TenantId.class)))
+                .thenReturn(endpointL3);
+        when(endpointManager.getL2EndpointFromL3(any(EndpointL3.class))).thenReturn(endpoint);
+
+        destinationMapper.syncL3PrefixFlow(flows, l3Prefixes, null, NODE_ID, ofWriter);
+
+        verify(ctx, times(5)).getTenant(any(TenantId.class));
+        verify(ctx, times(4)).getEndpointManager();
+        verify(ctx, times(1)).getSwitchManager();
+        verify(ctx, times(1)).getPolicyManager();
+        verify(ctx, times(1)).getCurrentPolicy();
+        verify(flows, times(1)).createL3PrefixFlow(anyShort(), anyInt(), any(Endpoint.class), any(EndpointL3Prefix.class),
+                any(IndexedTenant.class), any(Subnet.class), anySetOf(NodeConnectorId.class), eq(ofWriter));
+    }
+
+}
\ No newline at end of file
diff --git a/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperUtilsTest.java b/renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/destination/DestinationMapperUtilsTest.java
new file mode 100644 (file)
index 0000000..1702c9f
--- /dev/null
@@ -0,0 +1,330 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.destination;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.groupbasedpolicy.dto.EpKey;
+import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.*;
+
+public class DestinationMapperUtilsTest extends MapperUtilsTest {
+
+    private DestinationMapperUtils utils;
+
+    @Before
+    public void init() {
+        endpointManager = mock(EndpointManager.class);
+        policyInfo = mock(PolicyInfo.class);
+        ctx = mock(OfContext.class);
+        utils = new DestinationMapperUtils(ctx);
+    }
+
+    @Test
+    public void getSubnets() {
+        EndpointBuilder endpointBuilder = new EndpointBuilder();
+        HashSet<Subnet> emptyArray = utils.getSubnets(endpointBuilder.build().getTenant());
+        assertTrue(emptyArray.equals(Collections.emptySet()));
+
+        List<Subnet> subnets = getSubnetList();
+        Tenant tenant = buildTenant().build();
+        endpointBuilder.setTenant(tenant.getId());
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(tenant));
+
+        HashSet<Subnet> result = utils.getSubnets(endpointBuilder.build().getTenant());
+        List<Subnet> resultAsList = new ArrayList<>(result);
+        assertTrue(subnets.containsAll(resultAsList));
+    }
+
+    @Test
+    public void getL3ContextForSubnet_nullTenant() {
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_2));
+        L3Context l3Context = utils.getL3ContextForSubnet(null, subnetBuilder.build());
+        assertNull(l3Context);
+    }
+
+    @Test
+    public void getL3ContextForSubnet_nullResult() {
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId("otherSubnet"));
+        L3Context l3Context = utils.getL3ContextForSubnet(getTestIndexedTenant(), subnetBuilder.build());
+        assertNull(l3Context);
+    }
+
+    @Test
+    public void getL3ContextForSubnet_l3Context() {
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(L3C_ID));
+
+        // expected result
+        L3ContextBuilder expectedL3Context = new L3ContextBuilder();
+        expectedL3Context.setId(new L3ContextId(L3C_ID));
+
+        L3Context l3Context = utils.getL3ContextForSubnet(getTestIndexedTenant(), subnetBuilder.build());
+        assertEquals(l3Context, expectedL3Context.build());
+    }
+
+    @Test
+    public void getEpNetworkContainment_getNull() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1);
+        endpointBuilder.setNetworkContainment(null);
+
+        NetworkDomainId result = utils.getEPNetworkContainment(endpointBuilder.build(), null);
+        assertNull(result);
+    }
+
+    @Test
+    public void getEpNetworkContainment_getDomainIdFromEpg() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1);
+        endpointBuilder.setNetworkContainment(null);
+        EndpointGroupBuilder endpointGroupBuilder = new EndpointGroupBuilder();
+        endpointGroupBuilder.setId(ENDPOINT_GROUP_0);
+        endpointGroupBuilder.setNetworkDomain(new NetworkDomainId(NET_DOMAIN_ID));
+        endpointBuilder.setEndpointGroup(endpointGroupBuilder.build().getId());
+
+        NetworkDomainId result = utils.getEPNetworkContainment(endpointBuilder.build(), getTestIndexedTenant());
+        assertEquals(result, new SubnetId(SUBNET_0));
+    }
+
+    @Test
+    public void getEpNetworkContainment_getDomainIdFromEndpoint() {
+        String domainId = "domainId";
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1);
+        endpointBuilder.setNetworkContainment(new NetworkDomainId(domainId));
+
+        NetworkDomainId result = utils.getEPNetworkContainment(endpointBuilder.build(), getTestIndexedTenant());
+        assertEquals(result, new NetworkDomainId(domainId));
+    }
+
+    @Test
+    public void getLocalSubnets() {
+        Collection<Endpoint> endpoints = new ArrayList<>();
+        EndpointBuilder epWithoutSubnet = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1);
+        epWithoutSubnet.setTenant(null);
+        EndpointBuilder epWithSubnet = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_1);
+        TenantBuilder tenantBuilder = new TenantBuilder(buildTenant().build());
+        Tenant tenant = tenantBuilder.build();
+        epWithSubnet.setTenant(tenant.getId());
+        epWithSubnet.setNetworkContainment(new NetworkDomainId(SUBNET_0));
+        epWithSubnet.setTenant(tenant.getId());
+        epWithSubnet.setNetworkContainment(new NetworkDomainId(SUBNET_1));
+        endpoints.add(epWithoutSubnet.build());
+        endpoints.add(epWithSubnet.build());
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getTenant(null)).thenReturn(null);
+        when(ctx.getTenant(tenant.getId())).thenReturn(new IndexedTenant(tenant));
+        when(endpointManager.getEndpointsForNode(NODE_ID)).thenReturn(endpoints);
+
+        List<Subnet> subnets = utils.getLocalSubnets(NODE_ID);
+        verify(endpointManager, times(1)).getEndpointsForNode(any(NodeId.class));
+        assertTrue(subnets.size() == 1);
+    }
+
+    @Test
+    public void getL2EpOfSubnetGateway_nullCase() {
+        Endpoint result = utils.getL2EpOfSubnetGateway(buildTenant().getId(), null);
+        assertNull(result);
+    }
+
+    @Test
+    public void getL2EpOfSubnetGateway_nullL3Prefix() {
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_0));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(endpointManager.getEndpointsL3PrefixForTenant(buildTenant().getId())).thenReturn(null);
+
+        Endpoint result = utils.getL2EpOfSubnetGateway(buildTenant().getId(), subnetBuilder.build());
+        assertNull(result);
+    }
+
+    @Test
+    public void getL2EpOfSubnetGateway_emptyL3Prefix() {
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_2));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(endpointManager.getEndpointsL3PrefixForTenant(buildTenant().getId()))
+                .thenReturn(new ArrayList<EndpointL3Prefix>());
+
+        Endpoint result = utils.getL2EpOfSubnetGateway(buildTenant().getId(), subnetBuilder.build());
+        assertNull(result);
+    }
+
+    @Test
+    public void getL2EpOfSubnetGateway() {
+        SubnetBuilder subnetBuilder = new SubnetBuilder();
+        subnetBuilder.setId(new SubnetId(SUBNET_1));
+        subnetBuilder.setVirtualRouterIp(new IpAddress(new Ipv4Address(IPV4_0)));
+
+        // L3 Prefix
+        Collection<EndpointL3Prefix> l3PrefixCollection = new ArrayList<>();
+        EndpointL3PrefixBuilder endpointL3PrefixBuilder = new EndpointL3PrefixBuilder();
+        List<EndpointL3Gateways> endpointL3GatewaysList = new ArrayList<>();
+        EndpointL3GatewaysBuilder endpointL3GatewaysBuilder = new EndpointL3GatewaysBuilder();
+        endpointL3GatewaysList.add(endpointL3GatewaysBuilder.build());
+        endpointL3PrefixBuilder.setEndpointL3Gateways(endpointL3GatewaysList);
+        endpointL3GatewaysBuilder.setL3Context(new L3ContextBuilder().setId(new L3ContextId("l3cId")).build().getId());
+        l3PrefixCollection.add(endpointL3PrefixBuilder.build());
+
+        // L3 Endpoint
+        EndpointL3Builder endpointL3Builder = new EndpointL3Builder();
+        endpointL3Builder.setL2Context(new L2BridgeDomainBuilder().setId(new L2BridgeDomainId("bdId")).build().getId());
+        endpointL3Builder.setMacAddress(new MacAddress(MAC_0));
+
+        // Endpoint
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(endpointManager.getEndpointsL3PrefixForTenant(buildTenant().getId())).thenReturn(l3PrefixCollection);
+        when(endpointManager.getL3Endpoint(any(L3ContextId.class), any(IpAddress.class),
+                any(TenantId.class))).thenReturn(endpointL3Builder.build());
+        when(endpointManager.getEndpoint(any(EpKey.class))).thenReturn(endpointBuilder.build());
+
+        Endpoint result = utils.getL2EpOfSubnetGateway(buildTenant().getId(), subnetBuilder.build());
+        verify(endpointManager, times(1)).getEndpointsL3PrefixForTenant(any(TenantId.class));
+        verify(endpointManager, times(1)).getL3Endpoint(any(L3ContextId.class), any(IpAddress.class),
+                Mockito.any(TenantId.class));
+        verify(endpointManager, times(1)).getEndpoint(any(EpKey.class));
+        assertNotNull(result);
+    }
+
+    @Test
+    public void routerPortMac_noL3ContextId() {
+        L3ContextBuilder contextBuilder = new L3ContextBuilder();
+        MacAddress result = utils.routerPortMac(contextBuilder.build(), new IpAddress(new Ipv4Address(IPV4_0)),
+                buildTenant().getId());
+        assertEquals(result, DestinationMapper.ROUTER_MAC);
+    }
+
+    @Test
+    public void routerPortMac_nullEp() {
+        L3ContextBuilder contextBuilder = new L3ContextBuilder();
+        contextBuilder.setId(new L3ContextId("l3id"));
+        L3Context context = contextBuilder.build();
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(endpointManager.getL3Endpoint(any(L3ContextId.class), any(IpAddress.class), any(TenantId.class)))
+                .thenReturn(null);
+
+        MacAddress result = utils.routerPortMac(context, new IpAddress(new Ipv4Address(IPV4_0)),
+                buildTenant().getId());
+
+        verify(endpointManager, times(1)).getL3Endpoint(any(L3ContextId.class), any(IpAddress.class),
+                any(TenantId.class));
+        assertEquals(result, DestinationMapper.ROUTER_MAC);
+    }
+
+    @Test
+    public void routerPortMac() {
+        L3ContextBuilder contextBuilder = new L3ContextBuilder();
+        contextBuilder.setId(new L3ContextId("l3id"));
+        L3Context context = contextBuilder.build();
+        EndpointL3Builder endpointL3Builder = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, L2);
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(endpointManager.getL3Endpoint(any(L3ContextId.class), any(IpAddress.class), any(TenantId.class)))
+                .thenReturn(endpointL3Builder.build());
+
+        MacAddress result = utils.routerPortMac(context, new IpAddress(new Ipv4Address(IPV4_0)),
+                buildTenant().getId());
+
+        verify(endpointManager, times(1)).getL3Endpoint(any(L3ContextId.class), any(IpAddress.class),
+                any(TenantId.class));
+        assertEquals(result, new MacAddress(MAC_0));
+    }
+
+    @Test
+    public void getAllEndpointGroups() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
+        List<EndpointGroupId> endpointGroups = new ArrayList<>();
+        EndpointGroupBuilder endpointGroupBuilder = new EndpointGroupBuilder();
+        endpointGroupBuilder.setId(ENDPOINT_GROUP_1);
+        endpointGroups.add(endpointGroupBuilder.build().getId());
+        endpointBuilder.setEndpointGroups(endpointGroups);
+
+        Set<EndpointGroupId> result = utils.getAllEndpointGroups(endpointBuilder.build());
+        assertTrue(result.size() == 2);
+    }
+
+    @Test
+    public void getEndpointOrdinals_exceptionCaught() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpointBuilder.build());
+        assertNull(ordinals);
+    }
+
+    @Test
+    public void getEndpointOrdinals() {
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
+
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+
+        OrdinalFactory.EndpointFwdCtxOrdinals ordinals = utils.getEndpointOrdinals(endpointBuilder.build());
+        assertEquals(ordinals.getEp().toString(), new EpKey(new L2ContextId(L2BD_ID), new MacAddress(MAC_0)).toString());
+        assertEquals(ordinals.getNetworkContainment(), NET_DOMAIN_ID);
+    }
+
+    @Test
+    public void getIndexedTenant() {
+        TenantBuilder tenantBuilder = buildTenant();
+        tenantBuilder.setId(TENANT_ID);
+        when(ctx.getTenant(TENANT_ID)).thenReturn(new IndexedTenant(tenantBuilder.build()));
+        IndexedTenant result = utils.getIndexedTenant(TENANT_ID);
+        assertTrue(result.getTenant().getId().equals(TENANT_ID));
+    }
+}
\ No newline at end of file
index c1d627a277fa8facd974f2ffe7edca8ca8e635a7..7e4cc096be140f881ed4cd0ed6b1e7b1f0f4de5b 100644 (file)
@@ -19,7 +19,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.M
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
@@ -31,10 +32,7 @@ import static org.mockito.Mockito.*;
 
 public class EgressNatMapperFlowsTest extends MapperUtilsTest {
 
-    private static final String DROP = "drop";
-    private static final String DROP_ALL = "dropAll";
     private static final String EGRESS_NAT = "EgressNat|";
-    private final NodeId nodeId = new NodeId(NODE_ID);
     private EgressNatMapperFlows flows;
     private short tableId;
 
@@ -42,16 +40,16 @@ public class EgressNatMapperFlowsTest extends MapperUtilsTest {
     public void init() {
         tableId = 5;
         ofWriter = mock(OfWriter.class);
-        flows = new EgressNatMapperFlows(nodeId, tableId);
+        flows = new EgressNatMapperFlows(NODE_ID, tableId);
     }
 
     @Test
     public void testDropFlow_noEthertype() {
-        Flow testFlow = flowBuilder(new FlowId(DROP_ALL), tableId, 100, null,
+        Flow testFlow = buildFlow(new FlowId(DROP_ALL), tableId, 100, null,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, null, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -59,11 +57,11 @@ public class EgressNatMapperFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.IPv4, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -71,11 +69,11 @@ public class EgressNatMapperFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv6));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.IPv6, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -83,32 +81,34 @@ public class EgressNatMapperFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.ARP));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.ARP, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testNatFlows_noAugmentation() {
-        EndpointL3 endpointL3 = endpointL3Builder(null, IPV4_1, MAC_0, L2, false).build();
-        flows.natFlows((short) 6, endpointL3, 100, ofWriter);
+        EndpointL3Builder endpointL3Builder = buildL3Endpoint(IPV4_1, IPV4_0, MAC_0, L2);
+        endpointL3Builder.addAugmentation(NatAddress.class, null);
+        flows.natFlows((short) 6, endpointL3Builder.build(), 100, ofWriter);
         verifyZeroInteractions(ofWriter);
     }
 
     @Test
     public void testNatFlows_ipv4() {
-        EndpointL3 endpointL3 = endpointL3Builder(IPV4_1, IPV4_2, MAC_0, L2, false).build();
+        EndpointL3 endpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, L2).build();
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4))
-                .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(IPV4_2 + IP_PREFIX_32)).build());
+                .setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(IPV4_1.getValue() + IP_PREFIX_32))
+                        .build());
         FlowUtils.addNxRegMatch(matchBuilder, FlowUtils.RegMatch.of(NxmNxReg6.class, (long) 0));
         Match match = matchBuilder.build();
 
         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
         InstructionBuilder apply = new InstructionBuilder();
-        apply.setOrder(0).setInstruction(FlowUtils.applyActionIns(FlowUtils.setIpv4SrcAction(new Ipv4Address(IPV4_1))));
+        apply.setOrder(0).setInstruction(FlowUtils.applyActionIns(FlowUtils.setIpv4SrcAction(new Ipv4Address(IPV4_0))));
         InstructionBuilder goTo = new InstructionBuilder();
         goTo.setOrder(1).setInstruction(FlowUtils.gotoTableIns((short) 6));
         List<Instruction> instructions = new ArrayList<>();
@@ -116,19 +116,20 @@ public class EgressNatMapperFlowsTest extends MapperUtilsTest {
         instructions.add(goTo.build());
         instructionsBuilder.setInstruction(instructions);
 
-        Flow testFlow = flowBuilder(new FlowId(EGRESS_NAT + new IpAddress(new Ipv4Address(IPV4_2)) + "|" +
-                new IpAddress(new Ipv4Address(IPV4_1))), tableId, 90, match, instructionsBuilder.build()).build();
+        Flow testFlow = buildFlow(new FlowId(EGRESS_NAT + new IpAddress(new Ipv4Address(IPV4_1)) + "|" +
+                new IpAddress(new Ipv4Address(IPV4_0))), tableId, 90, match, instructionsBuilder.build()).build();
 
         flows.natFlows((short) 6, endpointL3, 90, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testNatFlows_ipv6() {
-        EndpointL3 endpointL3 = endpointL3Builder(IPV6_1, IPV6_2, MAC_0, L2, true).build();
+        EndpointL3 endpointL3 = buildL3Endpoint(IPV6_1, IPV6_2, MAC_0, L2).build();
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv6))
-                .setLayer3Match(new Ipv6MatchBuilder().setIpv6Source(new Ipv6Prefix(IPV6_2 + IP_PREFIX_128)).build());
+                .setLayer3Match(new Ipv6MatchBuilder().setIpv6Source(new Ipv6Prefix(IPV6_2.getValue() +
+                        IP_PREFIX_128)).build());
         FlowUtils.addNxRegMatch(matchBuilder, FlowUtils.RegMatch.of(NxmNxReg6.class, (long) 0));
         Match match = matchBuilder.build();
 
@@ -142,11 +143,11 @@ public class EgressNatMapperFlowsTest extends MapperUtilsTest {
         instructions.add(goTo.build());
         instructionsBuilder.setInstruction(instructions);
 
-        Flow testFlow = flowBuilder(new FlowId(EGRESS_NAT + new IpAddress(new Ipv6Address(IPV6_2)) + "|" +
+        Flow testFlow = buildFlow(new FlowId(EGRESS_NAT + new IpAddress(new Ipv6Address(IPV6_2)) + "|" +
                 new IpAddress(new Ipv6Address(IPV6_1))), tableId, 80, match, instructionsBuilder.build()).build();
 
         flows.natFlows((short) 6, endpointL3, 80, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
 }
index a4d577d1993e4a1459ef2eb61a4c0f9b4f8a3498..6b53830a8202099e8d7ebffd9e0220e47852c231 100644 (file)
@@ -50,11 +50,10 @@ public class EgressNatMapperTest extends MapperUtilsTest {
         EgressNatMapper mapper = new EgressNatMapper(ctx, tableId);
 
         // Endpoint
-        Endpoint endpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_1), null, null).build();
+        Endpoint endpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_1).build();
 
         // L3 endpoints
-        EndpointL3 endpointL3 = endpointL3Builder(IPV4_1, IPV4_2, MAC_0, L2, false).build();
+        EndpointL3 endpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, L2).build();
         List<EndpointL3> endpointsL3 = new ArrayList<>();
         endpointsL3.add(endpointL3);
 
index dd7f11627206110f35130f5728b7907b497209a8..4a4403b4e780d6a122a02ff6f65b25d2a639932a 100755 (executable)
@@ -8,52 +8,55 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.external;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import com.google.common.collect.ImmutableList;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockOfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.MockEndpointManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.MockSwitchManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.SegmentationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContextBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomainBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import com.google.common.collect.ImmutableSet;
-
-import java.util.ArrayList;
-import java.util.List;
+        import static org.mockito.Matchers.any;
+        import static org.mockito.Mockito.mock;
+        import static org.mockito.Mockito.times;
+        import static org.mockito.Mockito.verify;
+        import static org.mockito.Mockito.when;
+
+        import org.junit.Assert;
+        import org.junit.Before;
+        import org.junit.Test;
+        import org.junit.runner.RunWith;
+        import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
+        import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockOfContext;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.MockEndpointManager;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.MockSwitchManager;
+        import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+        import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+        import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+        import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressBuilder;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContextBuilder;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+        import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+        import org.powermock.api.mockito.PowerMockito;
+        import org.powermock.core.classloader.annotations.PrepareForTest;
+        import org.powermock.modules.junit4.PowerMockRunner;
+
+        import com.google.common.collect.ImmutableSet;
+
+        import java.util.Collection;
+        import java.util.HashSet;
+        import java.util.Set;
 
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({PolicyManager.class})
@@ -62,52 +65,21 @@ public class ExternalMapperTest extends MapperUtilsTest {
     private ExternalMapper mapper;
 
     private short tableId;
-    private NodeId nodeId;
-    private OfWriter ofWriter;
-    private MockEndpointManager endpointManagerMock;
-    private MockPolicyManager policyManagerMock;
-    private MockSwitchManager switchManagerMock;
-    private MockOfContext ctxMock;
-
-    private NodeConnectorId nodeConnectorId = new NodeConnectorId("openflow:1:1");
-    private MacAddress mac = new MacAddress("00:00:00:00:00:03");
-    private NatAddress natAddr = new NatAddressBuilder()
-        .setNatAddress(new IpAddress(new Ipv4Address("192.168.111.52")))
-        .build();
-
-    private EndpointL3 natL3Ep = new EndpointL3Builder()
-        .setTenant(tid)
-        .setL3Context(l3c)
-        .setMacAddress(mac)
-        .setL2Context(bd)
-        .setIpAddress(new IpAddress(new Ipv4Address("10.0.0.3")))
-        .addAugmentation(NatAddress.class, natAddr)
-        .build();
-
-    private Endpoint l2Ep = new EndpointBuilder()
-        .setTenant(tid)
-        .setMacAddress(mac)
-        .setL2Context(bd)
-        .setNetworkContainment(ext_sub)
-        .setEndpointGroup(eg)
-        .build();
+    private Ipv4Address natAddr = new Ipv4Address("192.168.111.52");
+
 
     @Before
     public void initialisation() {
         PowerMockito.stub(PowerMockito.method(PolicyManager.class, "setSfcTableOffset")).toReturn(true);
 
-        endpointManagerMock = new MockEndpointManager();
-        policyManagerMock = new MockPolicyManager(endpointManagerMock);
-        switchManagerMock = new MockSwitchManager();
-        ctxMock = new MockOfContext(null,
-                policyManagerMock,
-                switchManagerMock,
-                endpointManagerMock,
-                             null);
+        endpointManager = mock(EndpointManager.class);
+        policyManager = mock(PolicyManager.class);
+        switchManager = mock(SwitchManager.class);
+        policyInfo = mock(PolicyInfo.class);
+        ctx = mock(OfContext.class);
         tableId = 6;
-        nodeId = mock(NodeId.class);
         ofWriter = mock(OfWriter.class);
-        mapper = new ExternalMapper(ctxMock, tableId);
+        mapper = new ExternalMapper(ctx, tableId);
     }
 
     @Test
@@ -117,34 +89,52 @@ public class ExternalMapperTest extends MapperUtilsTest {
 
     @Test
     public void testSync() throws Exception {
-        SegmentationBuilder segmentationBuilder = new SegmentationBuilder();
-        segmentationBuilder.setSegmentationId(1);
-        List<L2FloodDomain> l2FloodDomains = new ArrayList<>();
-        L2FloodDomainBuilder l2FloodDomainBuilder = new L2FloodDomainBuilder();
-        l2FloodDomainBuilder.setId(new L2FloodDomainId(ext_fd));
-        l2FloodDomainBuilder.addAugmentation(Segmentation.class, segmentationBuilder.build());
-        l2FloodDomains.add(l2FloodDomainBuilder.build());
-        ctxMock.addTenant(baseTenantBuilder().setForwardingContext(new ForwardingContextBuilder()
-                .setL3Context(ImmutableList.of(new L3ContextBuilder().setId(l3c).build()))
-                .setL2FloodDomain(l2FloodDomains)
-                .setSubnet(subnet()).build()).build());
-        endpointManagerMock.addL3Endpoint(natL3Ep);
-        l2Ep = new EndpointBuilder(l2Ep)
-                .addAugmentation(OfOverlayContext.class, new OfOverlayContextBuilder()
-                        .setNodeId(nodeId)
-                        .build())
-                .build();
-        endpointManagerMock.addEndpoint(l2Ep);
-        switchManagerMock.addSwitch(nodeId, null, ImmutableSet.of(nodeConnectorId), null);
-        mapper.sync(l2Ep, ofWriter);
+        //External Ports
+        Set<Long> externalPorts = new HashSet<>();
+        externalPorts.add(Long.valueOf(CONNECTOR_1.getValue()));
+        // Modified tenant
+        TenantBuilder tenantBuilder = buildTenant();
+        tenantBuilder.setForwardingContext(new ForwardingContextBuilder()
+                .setL2FloodDomain(getL2FloodDomainList(true))
+                .setL2BridgeDomain(getL2BridgeDomainList())
+                .setL3Context(getL3ContextList())
+                .setSubnet(getSubnetList()).build())
+                .build().getId();
+        Tenant tenant = tenantBuilder.build();
+        // L2 Endpoint
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0)
+                .setNetworkContainment(L2_FD_ID_EXT)
+                .setL2Context(L2BD_ID);
+        // L3 Endpoint with Nat
+        EndpointL3Builder endpointL3Builder = buildL3Endpoint(natAddr, IPV4_1, MAC_0, null)
+                .setL2Context(L2BD_ID);
+        endpointL3Builder.setTenant(tenant.getId());
+        Collection<EndpointL3> l3EndpointsWithNat = new HashSet<>();
+        l3EndpointsWithNat.add(endpointL3Builder.build());
+
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(new IndexedTenant(tenant));
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getSwitchManager()).thenReturn(switchManager);
+        when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
+        when(endpointManager.getEndpointNodeId(any(Endpoint.class))).thenReturn(NODE_ID);
+        when(endpointManager.getL3EndpointsWithNat()).thenReturn(l3EndpointsWithNat);
+        when(switchManager.getExternalPortNumbers(any(NodeId.class))).thenReturn(externalPorts);
+
+        mapper.sync(endpointBuilder.build(), ofWriter);
+
         verify(ofWriter, times(4)).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
     }
 
     @Test
     public void testSync_NoExternalPorts() throws Exception {
         // we still need ExternalMapper flows (default output and default drop) to be generated
-        ctxMock.addTenant(baseTenantBuilder().build());
-        mapper.sync(l2Ep, ofWriter);
+        EndpointBuilder endpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
+
+        when(ctx.getEndpointManager()).thenReturn(endpointManager);
+        when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
+        when(endpointManager.getEndpointNodeId(any(Endpoint.class))).thenReturn(NODE_ID);
+
+        mapper.sync(endpointBuilder.build(), ofWriter);
         verify(ofWriter, times(2)).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
     }
-}
+}
\ No newline at end of file
index 2608452c9bfa522e68fedf801eb2942f1ed806e0..b16dace4ddf3085e780f99974d7248b54c2b1843 100644 (file)
@@ -17,8 +17,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTe
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -31,10 +29,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
@@ -51,38 +49,32 @@ import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtil
 
 public class IngressNatMapperFlowsTest extends MapperUtilsTest {
 
-    private static final String GOTO_DESTINATION_MAPPER = "gotoDestinationMapper";
-    private static final String INGRESS_NAT = "IngressNat";
-    private static final String INGRESS_ARP = "outside-ip-arp";
-    private static final String IN_PORT = ":INPORT";
-    private static final String INBOUND_EXTERNAL_IP = "inbound-external-ip";
-    private static final String INBOUND_EXTERNAL_ARP = "inbound-external-arp";
     private IngressNatMapperFlows flows;
 
     @Before
-    public void init() {
+    public void init() throws Exception {
         ctx = mock(OfContext.class);
         ofWriter = mock(OfWriter.class);
         endpointManager = mock(EndpointManager.class);
         policyManager = mock(PolicyManager.class);
         policyInfo = mock(PolicyInfo.class);
         tableId = 1;
-        flows = new IngressNatMapperFlows(nodeId, tableId);
+        flows = new IngressNatMapperFlows(NODE_ID, tableId);
         OrdinalFactory.resetPolicyOrdinalValue();
     }
 
     @Test
     public void testBaseFlow() {
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(GOTO_DESTINATION_MAPPER), tableId, 50, null,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId("gotoDestinationMapper"), tableId, 50, null,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.baseFlow((short) 2, 50, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testNatFlow_noAugmentation() {
-        EndpointL3 testEndpointL3 = endpointL3Builder(null, null, null, null, false).build();
+        EndpointL3 testEndpointL3 = new EndpointL3Builder().build();
 
         flows.createNatFlow((short) 3, testEndpointL3, null, 60, ofWriter);
         verifyZeroInteractions(ctx);
@@ -91,12 +83,11 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
 
     @Test
     public void testNatFlow() throws Exception {
-        EndpointL3 testEndpointL3 = endpointL3Builder(IPV4_1, IPV4_2, null, null, false).build();
-        Endpoint testEndpoint = endpointBuilder(null, new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_0), null, null).build();
+        EndpointL3 testEndpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, null).build();
+        Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
 
         OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
@@ -104,12 +95,12 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
         InOrder order = inOrder(ctx);
         order.verify(ctx, times(1)).getEndpointManager();
         order.verify(ctx, times(1)).getCurrentPolicy();
-        verify(ctx, times(2)).getTenant(new TenantId(TENANT_ID));
+        verify(ctx, times(2)).getTenant(TENANT_ID);
         assertNotNull(ordinals);
 
         List<Instruction> instructions = new ArrayList<>();
-        Action[] ipActions = {FlowUtils.setIpv4DstAction(new Ipv4Address(IPV4_2)),
-                FlowUtils.setDlDstAction(null)};
+        Action[] ipActions = {FlowUtils.setIpv4DstAction(new Ipv4Address(IPV4_1)),
+                FlowUtils.setDlDstAction(new MacAddress(MAC_0))};
         Action[] ordinalsAction = {FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1)),
                 FlowUtils.nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0)),
                 FlowUtils.nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(0)),
@@ -123,34 +114,33 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
         instructionsBuilder.setInstruction(instructions);
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        matchBuilder.setLayer3Match(new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(IPV4_1 +
+        matchBuilder.setLayer3Match(new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(IPV4_0.getValue() +
                 IP_PREFIX_32)).build());
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
 
-        Flow testFlow = flowBuilder(new FlowId(INGRESS_NAT + "|" + new IpAddress(new Ipv4Address(IPV4_1)).toString() +
-                        "|" + new IpAddress(new Ipv4Address(IPV4_2)).toString() + "|" + "null"), tableId, 60, matchBuilder.build(),
-                instructionsBuilder.build()).build();
-
+        Flow testFlow = buildFlow(new FlowId("IngressNat" + "|" + new IpAddress(new Ipv4Address(IPV4_0)).toString() +
+                        "|" + new IpAddress(new Ipv4Address(IPV4_1)).toString() + "|" + new MacAddress(MAC_0)), tableId,
+                60, matchBuilder.build(), instructionsBuilder.build()).build();
         flows.createNatFlow((short) 2, testEndpointL3, ordinals, 60, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testArpFlow_noAugmentation() {
-        EndpointL3 testEndpointL3 = endpointL3Builder(null, null, null, null, false).build();
+        EndpointL3 testEndpointL3 = new EndpointL3Builder().build();
 
-        flows.createArpFlow(indexedTenantBuilder(), testEndpointL3, 60, ofWriter);
+        flows.createArpFlow(getTestIndexedTenant(), testEndpointL3, 60, ofWriter);
         verifyZeroInteractions(ctx);
         verifyZeroInteractions(ofWriter);
     }
 
     @Test
     public void testArpFlow() {
-        EndpointL3 testEndpointL3 = endpointL3Builder(IPV4_1, IPV4_2, MAC_0, null, false).build();
+        EndpointL3 testEndpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, null).build();
         List<Instruction> instructions = new ArrayList<>();
         Action[] arpActions = {nxMoveEthSrcToEthDstAction(), setDlSrcAction(new MacAddress(MAC_0)),
                 nxLoadArpOpAction(BigInteger.valueOf(2L)), nxMoveArpShaToArpThaAction(), nxLoadArpShaAction(new BigInteger("0")),
-                nxMoveArpSpaToArpTpaAction(), nxLoadArpSpaAction(IPV4_1), outputAction(new NodeConnectorId(NODE_ID + IN_PORT))};
+                nxMoveArpSpaToArpTpaAction(), nxLoadArpSpaAction(IPV4_0.getValue()), outputAction(new NodeConnectorId(NODE_ID.getValue() + ":INPORT"))};
         instructions.add(new InstructionBuilder().setOrder(0)
                 .setInstruction(FlowUtils.applyActionIns(ArrayUtils.addAll(arpActions))).build());
         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
@@ -158,24 +148,23 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
 
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.ARP));
-        matchBuilder.setLayer3Match(new ArpMatchBuilder().setArpOp(1).setArpTargetTransportAddress(new Ipv4Prefix(IPV4_1
+        matchBuilder.setLayer3Match(new ArpMatchBuilder().setArpOp(1).setArpTargetTransportAddress(new Ipv4Prefix(IPV4_0.getValue()
                 + IP_PREFIX_32)).build());
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, INGRESS_ARP, match),
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "outside-ip-arp", match),
                 tableId, 60, match, instructionsBuilder.build()).build();
 
-        flows.createArpFlow(indexedTenantBuilder(), testEndpointL3, 60, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        flows.createArpFlow(getTestIndexedTenant(), testEndpointL3, 60, ofWriter);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testIngressExternalNatFlow() throws Exception {
-        Endpoint testEndpoint = endpointBuilder(new IpAddress(new Ipv6Address(IPV6_1)), new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_0), null, null).build();
+        Endpoint testEndpoint = buildEndpoint(IPV4_1, MAC_0, CONNECTOR_0).build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
 
         OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
@@ -183,7 +172,7 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
         InOrder order = inOrder(ctx);
         order.verify(ctx, times(1)).getEndpointManager();
         order.verify(ctx, times(1)).getCurrentPolicy();
-        verify(ctx, times(2)).getTenant(new TenantId(TENANT_ID));
+        verify(ctx, times(2)).getTenant(TENANT_ID);
         assertNotNull(ordinals);
 
         List<Instruction> instructions = new ArrayList<>();
@@ -200,25 +189,25 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
         instructionsBuilder.setInstruction(instructions);
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv6));
-        matchBuilder.setLayer3Match(new Ipv6MatchBuilder().setIpv6Source(new Ipv6Prefix(IPV6_1 + IP_PREFIX_128)).build());
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
+        matchBuilder.setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(IPV4_1.getValue()
+                + IP_PREFIX_32)).build());
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, INBOUND_EXTERNAL_IP, match), tableId, 50, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "inbound-external-ip", match), tableId, 50, match,
                 instructionsBuilder.build()).build();
 
         flows.createIngressExternalNatFlows((short) 2, testEndpoint, ordinals, 50, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
 
     }
 
     @Test
     public void testIngressExternalArpFlow() throws Exception {
-        Endpoint testEndpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_0), null, null).build();
+        Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
 
         OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
@@ -226,7 +215,7 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
         InOrder order = inOrder(ctx);
         order.verify(ctx, times(1)).getEndpointManager();
         order.verify(ctx, times(1)).getCurrentPolicy();
-        verify(ctx, times(2)).getTenant(new TenantId(TENANT_ID));
+        verify(ctx, times(2)).getTenant(TENANT_ID);
         assertNotNull(ordinals);
 
         List<Instruction> instructions = new ArrayList<>();
@@ -246,11 +235,11 @@ public class IngressNatMapperFlowsTest extends MapperUtilsTest {
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(new MacAddress(MAC_0), null, FlowUtils.ARP));
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, INBOUND_EXTERNAL_ARP, match), tableId, 30, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "inbound-external-arp", match), tableId, 30, match,
                 instructionsBuilder.build()).build();
 
         flows.createIngressExternalArpFlows((short) 0, testEndpoint, ordinals, 30, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
 }
index 09031062b6bb5af990a58e819d9438bd659d12d1..a82862b71a8ff93d3d0bea87c87e1e44c9a738cb 100644 (file)
@@ -22,14 +22,10 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -40,8 +36,6 @@ import static org.mockito.Mockito.*;
 
 public class IngressNatMapperTest extends MapperUtilsTest {
 
-    private static final String EPG_ID = "dummy epg id";
-
     @Before
     public void init() {
         ctx = mock(OfContext.class);
@@ -56,22 +50,21 @@ public class IngressNatMapperTest extends MapperUtilsTest {
     public void testSyncFlows() throws Exception {
 
         // Endpoints
-        Endpoint endpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_0), null, null).build();
+        Endpoint endpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
         List<Endpoint> endpoints = new ArrayList<>();
         endpoints.add(endpoint);
 
         // L3 endpoints
-        EndpointL3 endpointL3 = endpointL3Builder(IPV4_1, IPV4_2, MAC_0, L2, false).build();
+        EndpointL3 endpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, L2).build();
         List<EndpointL3> endpointsL3 = new ArrayList<>();
         endpointsL3.add(endpointL3);
 
         // EgKEy set
         Set<EgKey> egKeys = new HashSet<>();
-        egKeys.add(new EgKey(new TenantId(TENANT_ID), new EndpointGroupId(EPG_ID)));
+        egKeys.add(new EgKey(TENANT_ID, ENDPOINT_GROUP_1));
 
         when(ctx.getPolicyManager()).thenReturn(policyManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
         when(endpointManager.getL3EndpointsWithNat()).thenReturn(endpointsL3);
         when(endpointManager.getEndpoint(Mockito.any(EpKey.class))).thenReturn(endpoint);
index fc2f5c733a47e30bb4bcb75a82d137296b4a3bb9..ca6c6eb9fa8ecd8a3077e06bf4a6cb4670bd7089 100755 (executable)
@@ -41,7 +41,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.MockSwitchManag
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
@@ -51,6 +50,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.nodes.node.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
@@ -102,27 +102,27 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
     private final int allowTunnelFlows = 1;
     private final int layer4flowsIPv4 = 1;
     private final int layer4flowsIPv6 = 1;
-    private final int dropAllFlow = 1;
-    private final int arpFlows = 1;
-    private MockEndpointManager endpointManagerMock;
-    private MockPolicyManager policyManagerMock;
-    private MockSwitchManager switchManagerMock;
-    private MockOfContext ctxMock;
+    private static final String TCP_DST = "tcp_dst_80";
 
     private NodeConnectorId tunnelId =
-            new NodeConnectorId(nodeId.getValue() + ":42");
+            new NodeConnectorId(NODE_ID.getValue() + ":42");
+    private NodeConnectorId nodeConnector = new NodeConnectorId(NODE_ID.getValue() + CONNECTOR_0);
     @Before
     public void setup() throws Exception {
         PowerMockito.stub(PowerMockito.method(PolicyManager.class, "setSfcTableOffset")).toReturn(true);
 
-        endpointManagerMock = new MockEndpointManager();
-        policyManagerMock = new MockPolicyManager(endpointManagerMock);
-        switchManagerMock = new MockSwitchManager();
-        ctxMock = new MockOfContext(null, policyManagerMock, switchManagerMock, endpointManagerMock, null);
-        table = new PolicyEnforcer(ctxMock, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER());
+        endpointManager = new MockEndpointManager();
+        policyManager = new MockPolicyManager(endpointManager);
+        switchManager = new MockSwitchManager();
+        ctx = new MockOfContext(null,
+                             policyManager,
+                             switchManager,
+                             endpointManager,
+                             null);
+        table = new PolicyEnforcer(ctx, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER());
 
-        switchManagerMock.addSwitch(
-                nodeId,
+        ((MockSwitchManager)switchManager).addSwitch(
+                NODE_ID,
                 tunnelId,
                 Collections.<NodeConnectorId>emptySet(),
                 new OfOverlayNodeConfigBuilder().setTunnel(
@@ -134,31 +134,35 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
 
     @Test
     public void testSameEg() throws Exception {
-        Endpoint ep1 = endpointBuilder(new IpAddress(IPV4_1.toCharArray()), new MacAddress(MAC_0), nodeConnectorId, eg, bd)
-                .build();
-        endpointManagerMock.addEndpoint(ep1);
-        Endpoint ep2 = endpointBuilder(new IpAddress(IPV4_2.toCharArray()), new MacAddress(MAC_1), nodeConnectorId, eg, bd)
-                .build();
-        endpointManagerMock.addEndpoint(ep2);
-        ctxMock.addTenant(baseTenantBuilder().setPolicy(new PolicyBuilder(baseTenantBuilder().getPolicy())
+        EndpointBuilder ep1Builder = buildEndpoint(IPV4_0, MAC_0, nodeConnector);
+        ep1Builder.setEndpointGroup(ENDPOINT_GROUP_0);
+        ep1Builder.setL2Context(L2BD_ID);
+        Endpoint ep1 = ep1Builder.build();
+        ((MockEndpointManager)endpointManager).addEndpoint(ep1);
+        EndpointBuilder ep2Builder = buildEndpoint(IPV4_1,MAC_1, nodeConnector);
+        ep2Builder.setEndpointGroup(ENDPOINT_GROUP_1);
+        ep2Builder.setL2Context(L2BD_ID);
+        Endpoint ep2 = ep2Builder.build();
+        ((MockEndpointManager)endpointManager).addEndpoint(ep2);
+        ((MockOfContext)ctx).addTenant(buildTenant().setPolicy(new PolicyBuilder(buildTenant().getPolicy())
             .setContract(ImmutableList.of(baseContract(null).build())).build()).build());
 
         ofWriter = new OfWriter();
         table.sync(ep1, ofWriter);
-        assertTrue(!ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER())
+        assertTrue(!ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER())
             .getFlow()
             .isEmpty());
         int count = 0;
         HashMap<String, Flow> flowMap = new HashMap<>();
-        for (Flow f : ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER()).getFlow()) {
+        for (Flow f : ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()).getFlow()) {
             flowMap.put(f.getId().getValue(), f);
             if (isAllowSameEpg(f)) {
                 count += 1;
             }
         }
         assertEquals(sameEpgFlows, count);
-        int totalFlows = sameEpgFlows + allowTunnelFlows + dropAllFlow;
-        assertEquals(totalFlows, ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER())
+        int totalFlows = sameEpgFlows + allowTunnelFlows + layer4flowsIPv4 + layer4flowsIPv6;
+        assertEquals(totalFlows, ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER())
             .getFlow()
             .size());
     }
@@ -178,27 +182,27 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
     @Test
     public void doTestRule() throws Exception {
         Rule rule1 = new RuleBuilder().setActionRef(
-                ImmutableList.of(new ActionRefBuilder().setName(new ActionName("allow")).build()))
+                ImmutableList.of(new ActionRefBuilder().setName(new ActionName(ALLOW)).build()))
             .setClassifierRef(
-                    createClassifierRefs(ImmutableMap.of("tcp_dst_80", Direction.In, "tcp_src_80",
+                    createClassifierRefs(ImmutableMap.of(TCP_DST, Direction.In, TCP_SRC,
                             Direction.In)))
             .build();
         Rule rule2 = new RuleBuilder().setActionRef(
-                ImmutableList.of(new ActionRefBuilder().setName(new ActionName("allow")).build()))
+                ImmutableList.of(new ActionRefBuilder().setName(new ActionName(ALLOW)).build()))
             .setClassifierRef(
-                    createClassifierRefs(ImmutableMap.of("tcp_dst_80", Direction.In, "tcp_src_80",
+                    createClassifierRefs(ImmutableMap.of(TCP_DST, Direction.In, TCP_SRC,
                             Direction.Out)))
             .build();
         Rule rule3 = new RuleBuilder().setActionRef(
-                ImmutableList.of(new ActionRefBuilder().setName(new ActionName("allow")).build()))
+                ImmutableList.of(new ActionRefBuilder().setName(new ActionName(ALLOW)).build()))
             .setClassifierRef(
-                    createClassifierRefs(ImmutableMap.of("tcp_dst_80", Direction.In, "tcp_src_80",
+                    createClassifierRefs(ImmutableMap.of(TCP_DST, Direction.In, TCP_SRC,
                             Direction.Out, "ether_type", Direction.In)))
             .build();
         Rule rule4 = new RuleBuilder().setActionRef(
-                ImmutableList.of(new ActionRefBuilder().setName(new ActionName("allow")).build()))
+                ImmutableList.of(new ActionRefBuilder().setName(new ActionName(ALLOW)).build()))
             .setClassifierRef(
-                    createClassifierRefs(ImmutableMap.of("tcp_dst_80", Direction.In, "tcp_dst_90",
+                    createClassifierRefs(ImmutableMap.of(TCP_DST, Direction.In, "tcp_dst_90",
                             Direction.In)))
             .build();
 
@@ -219,22 +223,26 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
     }
 
     private int doTestDifferentEg(List<Subject> subjects) throws Exception {
-        Endpoint ep1 = endpointBuilder(new IpAddress(IPV4_1.toCharArray()), new MacAddress(MAC_0), nodeConnectorId, eg, bd)
-                .build();
-        endpointManagerMock.addEndpoint(ep1);
-        Endpoint ep2 = endpointBuilder(new IpAddress(IPV4_2.toCharArray()), new MacAddress(MAC_1), nodeConnectorId, eg2, bd)
-                .build();
-        endpointManagerMock.addEndpoint(ep2);
-        ctxMock.addTenant(baseTenantBuilder().setPolicy(new PolicyBuilder(baseTenantBuilder().getPolicy())
+        EndpointBuilder ep1Builder = buildEndpoint(IPV4_0, MAC_0, nodeConnector);
+        ep1Builder.setEndpointGroup(ENDPOINT_GROUP_0);
+        ep1Builder.setL2Context(L2BD_ID);
+        Endpoint ep1 = ep1Builder.build();
+        ((MockEndpointManager)endpointManager).addEndpoint(ep1);
+        EndpointBuilder ep2Builder = buildEndpoint(IPV4_1, MAC_1, nodeConnector);
+        ep2Builder.setEndpointGroup(ENDPOINT_GROUP_1);
+        ep2Builder.setL2Context(L2BD_ID);
+        Endpoint ep2 = ep2Builder.build();
+        ((MockEndpointManager)endpointManager).addEndpoint(ep2);
+        ((MockOfContext)ctx).addTenant(buildTenant().setPolicy(new PolicyBuilder(buildTenant().getPolicy())
             .setContract(ImmutableList.of(baseContract(subjects).build())).build()).build());
 
         ofWriter = new OfWriter();
         table.sync(ep1, ofWriter);
-        assertTrue(!ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER())
+        assertTrue(!ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER())
             .getFlow()
             .isEmpty());
         int count = 0;
-        for (Flow f : ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER()).getFlow()) {
+        for (Flow f : ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()).getFlow()) {
             if (isAllowSameEpg(f)) {
                 count += 1;
             } else if (f.getMatch() != null && Objects.equals(tunnelId, f.getMatch().getInPort())) {
@@ -280,16 +288,21 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
         Condition cond1 = new ConditionBuilder().setName(new ConditionName("cond1")).build();
         Condition cond2 = new ConditionBuilder().setName(new ConditionName("cond2")).build();
 
-        Endpoint ep1 = endpointBuilder(new IpAddress(IPV4_1.toCharArray()), new MacAddress(MAC_0), nodeConnectorId, eg, bd)
-                .setCondition(ImmutableList.of(cond1.getName())).build();
-        endpointManagerMock.addEndpoint(ep1);
-        Endpoint ep2 = endpointBuilder(new IpAddress(IPV4_2.toCharArray()), new MacAddress(MAC_1), nodeConnectorId, eg2, bd)
-            .setCondition(ImmutableList.of(cond1.getName(), cond2.getName()))
-            .build();
-        endpointManagerMock.addEndpoint(ep2);
+        EndpointBuilder ep1Builder = buildEndpoint(IPV4_0, MAC_0, nodeConnector);
+        ep1Builder.setEndpointGroup(ENDPOINT_GROUP_0);
+        ep1Builder.setL2Context(L2BD_ID);
+        ep1Builder.setCondition(ImmutableList.of(cond1.getName())).build();
+        Endpoint ep1 = ep1Builder.build();
+        ((MockEndpointManager)endpointManager).addEndpoint(ep1);
+        EndpointBuilder ep2Builder = buildEndpoint(IPV4_1,MAC_1, nodeConnector);
+        ep2Builder.setEndpointGroup(ENDPOINT_GROUP_1);
+        ep2Builder.setL2Context(L2BD_ID);
+        ep2Builder.setCondition(ImmutableList.of(cond1.getName(), cond2.getName())).build();
+        Endpoint ep2 = ep2Builder.build();
+        ((MockEndpointManager)endpointManager).addEndpoint(ep2);
 
-        TenantBuilder tb = baseTenantBuilder().setPolicy(new PolicyBuilder(baseTenantBuilder().getPolicy()).setContract(
-                ImmutableList.of(new ContractBuilder().setId(cid)
+        TenantBuilder tb = buildTenant().setPolicy(new PolicyBuilder(buildTenant().getPolicy()).setContract(
+                ImmutableList.of(new ContractBuilder().setId(CONTRACT_ID)
                     .setSubject(ImmutableList.of(baseSubject(Direction.Out).build()))
                     .setClause(
                             ImmutableList.of(new ClauseBuilder().setName(new ClauseName("test"))
@@ -310,12 +323,12 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
                                                     .build())).build())
                                 .build()))
                     .build())).build());
-        ctxMock.addTenant(tb.build());
+        ((MockOfContext)ctx).addTenant(tb.build());
 
-        PolicyInfo policy = ctxMock.getCurrentPolicy();
-        List<ConditionName> ep1c = endpointManagerMock.getConditionsForEndpoint(ep1);
+        PolicyInfo policy = ctx.getCurrentPolicy();
+        List<ConditionName> ep1c = endpointManager.getConditionsForEndpoint(ep1);
         ConditionGroup cg1 = policy.getEgCondGroup(new EgKey(tb.getId(), ep1.getEndpointGroup()), ep1c);
-        List<ConditionName> ep2c = endpointManagerMock.getConditionsForEndpoint(ep2);
+        List<ConditionName> ep2c = endpointManager.getConditionsForEndpoint(ep2);
         ConditionGroup cg2 = policy.getEgCondGroup(new EgKey(tb.getId(), ep2.getEndpointGroup()), ep2c);
         int cg1Id = OrdinalFactory.getCondGroupOrdinal(cg1);
         int cg2Id = OrdinalFactory.getCondGroupOrdinal(cg2);
@@ -332,12 +345,14 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
         ofWriter = new OfWriter();
         table.sync(ep1, ofWriter);
         // one layer4 flow for each direction
-        int totalFlows = sameEpgFlows + allowTunnelFlows + layer4flowsIPv4 + layer4flowsIPv6 + arpFlows + dropAllFlow;;
-        assertEquals(totalFlows, ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER())
+        int dropAllFlow = 1;
+        int arpFlows = 1;
+        int totalFlows = sameEpgFlows + allowTunnelFlows + layer4flowsIPv4 + layer4flowsIPv6 + arpFlows + dropAllFlow;
+        assertEquals(totalFlows, ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER())
             .getFlow()
             .size());
         HashMap<String, Flow> flowMap = new HashMap<>();
-        for (Flow f : ofWriter.getTableForNode(nodeId, ctxMock.getPolicyManager().getTABLEID_POLICY_ENFORCER()).getFlow()) {
+        for (Flow f : ofWriter.getTableForNode(NODE_ID, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()).getFlow()) {
             flowMap.put(f.getId().getValue(), f);
             if (f.getMatch() != null && f.getMatch().getEthernetMatch() != null) {
                 count++;
@@ -384,11 +399,11 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
     }
 
     protected ContractBuilder baseContract(List<Subject> subjects) {
-        ContractBuilder contractBuilder = new ContractBuilder().setId(cid).setSubject(subjects);
+        ContractBuilder contractBuilder = new ContractBuilder().setId(CONTRACT_ID).setSubject(subjects);
         // TODO refactor
         if (subjects == null) {
             return contractBuilder.setClause(ImmutableList.of(new ClauseBuilder().setName(new ClauseName("test"))
-                .setSubjectRefs(ImmutableList.<SubjectName>of(new SubjectName("s1")))
+                .setSubjectRefs(ImmutableList.of(new SubjectName("s1")))
                 .build()));
         }
         List<SubjectName> subjectNames = new ArrayList<>();
@@ -405,12 +420,12 @@ public class PolicyEnforcerTest extends MapperUtilsTest {
             .setName(new SubjectName("s1"))
             .setRule(ImmutableList.of(new RuleBuilder()
                 .setActionRef(ImmutableList.of(new ActionRefBuilder()
-                    .setName(new ActionName("allow"))
+                    .setName(new ActionName(ALLOW))
                     .build()))
                 .setClassifierRef(ImmutableList.of(new ClassifierRefBuilder()
-                    .setName(new ClassifierName("tcp_dst_80"))
+                    .setName(new ClassifierName(TCP_DST))
                     .setDirection(direction)
-                    .setInstanceName(new ClassifierName("tcp_dst_80"))
+                    .setInstanceName(new ClassifierName(TCP_DST))
                     .build()))
                 .build()));
     }
index e4d7e45e69c0da5dddb9c38311fd04ca01b91581..76fc292e2981bfb7475c0f34d1f91eca8c69da1a 100644 (file)
@@ -9,7 +9,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTe
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -33,28 +32,23 @@ import static org.mockito.Mockito.*;
 
 public class PortSecurityFlowsTest extends MapperUtilsTest {
 
-    private static final String DROP_ALL = "dropAll";
-    private static final String DROP = "drop";
-    private static final String ALLOW = "allow";
     private static final String L3 = "L3";
     private static final String DHCP = "dhcp";
-    private static final String ALLOW_EXTERNAL = "allowExternal";
-    private static final String ALLOW_EXTERNAL_POP_VLAN = "allowExternalPopVlan";
     private PortSecurityFlows flows;
 
     @Before
     public void init() {
         tableId = 0;
         ofWriter = mock(OfWriter.class);
-        flows = new PortSecurityFlows(nodeId, tableId);
+        flows = new PortSecurityFlows(NODE_ID, tableId);
     }
 
     @Test
     public void testDropFlow_noEthertype() {
-        Flow testFlow = flowBuilder(new FlowId(DROP_ALL), tableId, 100, null, FlowUtils.dropInstructions()).build();
+        Flow testFlow = buildFlow(new FlowId(DROP_ALL), tableId, 100, null, FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, null, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -62,11 +56,11 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.IPv4, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -74,11 +68,11 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv6));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.IPv6, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -86,11 +80,11 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.ARP));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.ARP, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -99,11 +93,11 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setInPort(new NodeConnectorId(String.valueOf(VXLAN_PORT)));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, ALLOW, match), tableId, 300, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, ALLOW, match), tableId, 300, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.allowFromTunnelFlow((short) 2, 300, new NodeConnectorId(CONNECTOR_0), ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
 
     }
 
@@ -113,83 +107,71 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setInPort(new NodeConnectorId(String.valueOf(VXLAN_PORT)));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, ALLOW, match), tableId, 300, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, ALLOW, match), tableId, 300, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.allowFromTunnelFlow((short) 2, 300, new NodeConnectorId(CONNECTOR_1), ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
 
     }
 
     @Test
     public void testL3flow_ipv4() {
-        IpAddress ipAddress = new IpAddress(new Ipv4Address(IPV4_1));
-        MacAddress macAddress = new MacAddress(MAC_0);
-        NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_0);
-        Endpoint testEp = endpointBuilder(ipAddress, macAddress, connectorId, null, null).build();
+        Endpoint testEp = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(macAddress, null, FlowUtils.IPv4))
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(MAC_0, null, FlowUtils.IPv4))
                 .setLayer3Match(new Ipv4MatchBuilder()
-                        .setIpv4Source(new Ipv4Prefix(ipAddress.getIpv4Address().getValue() + IP_PREFIX_32)).build())
-                .setInPort(connectorId);
+                        .setIpv4Source(new Ipv4Prefix(IPV4_0.getValue() + IP_PREFIX_32)).build())
+                .setInPort(new NodeConnectorId(CONNECTOR_0));
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, L3, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, L3, match), tableId, 100, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.l3Flow((short) 2, testEp, new NodeConnectorId(CONNECTOR_0), new MacAddress(MAC_0), 100, false, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testL3flow_ipv4Arp() {
-        IpAddress ipAddress = new IpAddress(new Ipv4Address(IPV4_1));
-        MacAddress macAddress = new MacAddress(MAC_1);
-        NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_1);
-        Endpoint testEp = endpointBuilder(ipAddress, macAddress, connectorId, null, null).build();
+        Endpoint testEp = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1).build();
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(macAddress, null, FlowUtils.ARP))
-                .setLayer3Match(new ArpMatchBuilder().setArpSourceTransportAddress(new Ipv4Prefix(ipAddress
-                        .getIpv4Address().getValue() + IP_PREFIX_32)).build())
-                .setInPort(connectorId);
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(MAC_1, null, FlowUtils.ARP))
+                .setLayer3Match(new ArpMatchBuilder().setArpSourceTransportAddress(new Ipv4Prefix(IPV4_0.getValue()
+                        + IP_PREFIX_32)).build())
+                .setInPort(new NodeConnectorId(CONNECTOR_1));
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, L3, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, L3, match), tableId, 100, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.l3Flow((short) 2, testEp, new NodeConnectorId(CONNECTOR_1), new MacAddress(MAC_1), 100, true, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testL3flow_ipv6() {
-        IpAddress ipAddress = new IpAddress(new Ipv6Address(IPV6_1));
-        MacAddress macAddress = new MacAddress(MAC_0);
-        NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_0);
-        Endpoint testEp = endpointBuilder(ipAddress, macAddress, connectorId, null, null).build();
+        Endpoint testEp = buildEndpoint(IPV6_1, MAC_0, CONNECTOR_0).build();
 
         MatchBuilder matchBuilder = new MatchBuilder();
-        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(macAddress, null, FlowUtils.IPv6))
+        matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(MAC_0, null, FlowUtils.IPv6))
                 .setLayer3Match(new Ipv6MatchBuilder()
-                        .setIpv6Source(new Ipv6Prefix(ipAddress.getIpv6Address().getValue() + IP_PREFIX_128)).build())
-                .setInPort(connectorId);
+                        .setIpv6Source(new Ipv6Prefix(IPV6_1.getValue() + IP_PREFIX_128)).build())
+                .setInPort(new NodeConnectorId(CONNECTOR_0));
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, L3, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, L3, match), tableId, 100, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.l3Flow((short) 2, testEp, new NodeConnectorId(CONNECTOR_0), new MacAddress(MAC_0), 100, false, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void testL3flow_ipv6Arp() {
-        IpAddress ipAddress = new IpAddress(new Ipv6Address(IPV6_1));
-        MacAddress macAddress = new MacAddress(MAC_1);
-        NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_1);
-        Endpoint testEp = endpointBuilder(ipAddress, macAddress, connectorId, null, null).build();
+        Endpoint testEp = buildEndpoint(IPV6_1, MAC_1, CONNECTOR_1).build();
 
         flows.l3Flow((short) 2, testEp, new NodeConnectorId(CONNECTOR_1), new MacAddress(MAC_1), 100, true, ofWriter);
         verifyZeroInteractions(ofWriter);
@@ -197,7 +179,7 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
 
     @Test
     public void testL3DhcpDoraFlow() {
-        IpAddress ipAddress = new IpAddress(new Ipv4Address(DHCP_IP));
+        IpAddress ipAddress = new IpAddress(new Ipv4Address("255.255.255.255"));
         MacAddress macAddress = new MacAddress(MAC_1);
         NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_1);
 
@@ -208,11 +190,11 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
                 .setInPort(connectorId);
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DHCP, match), tableId, 50, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DHCP, match), tableId, 50, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.l3DhcpDoraFlow((short) 2, new NodeConnectorId(CONNECTOR_1), new MacAddress(MAC_1), 50, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -225,11 +207,11 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
                 .setInPort(connectorId);
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, L2, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, L2, match), tableId, 100, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
 
         flows.l2flow((short) 2, new NodeConnectorId(CONNECTOR_0), new MacAddress(MAC_0), 100, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -248,13 +230,13 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
         instructionsBuilder.setInstruction(instructions);
 
-        List<L2FloodDomain> l2FloodDomains = l2FloodDomains();
+        List<L2FloodDomain> l2FloodDomains = getL2FloodDomainList(false);
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, ALLOW_EXTERNAL_POP_VLAN, match), tableId, 200, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "allowExternalPopVlan", match), tableId, 200, match,
                 instructionsBuilder.build()).build();
 
         flows.popVlanTagsOnExternalPortFlows((short) 0, connectorId, l2FloodDomains, 200, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -265,9 +247,9 @@ public class PortSecurityFlowsTest extends MapperUtilsTest {
         matchBuilder.setInPort(connectorId);
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, ALLOW_EXTERNAL, match), tableId, 250, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "allowExternal", match), tableId, 250, match,
                 FlowUtils.gotoTableInstructions((short) 2)).build();
         flows.allowFromExternalPortFlow((short) 2, connectorId, 250, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 }
index aecfa3ae82c5eb888c8cc908b0802f4478c011f2..eb4ea9de0ca14af6b26602c0a632e93655a3ecdb 100644 (file)
@@ -10,8 +10,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
@@ -31,6 +29,7 @@ public class PortSecurityTest extends MapperUtilsTest {
     @Before
     public void init() {
         ctx = mock(OfContext.class);
+        tableId = 1;
         policyManager = mock(PolicyManager.class);
         switchManager = mock(SwitchManager.class);
         endpointManager = mock(EndpointManager.class);
@@ -39,34 +38,30 @@ public class PortSecurityTest extends MapperUtilsTest {
 
     @Test
     public void testSyncFlows() throws Exception {
-        Short tableId = 0;
-        IpAddress ipAddress = new IpAddress(new Ipv4Address(IPV4_1));
-        MacAddress macAddress = new MacAddress(MAC_0);
-        NodeConnectorId connectorId = new NodeConnectorId(CONNECTOR_0);
 
         // Node connectors
         Set<NodeConnectorId> connectors = new HashSet<>();
         connectors.add(new NodeConnectorId(CONNECTOR_0));
 
         // Prepare endpoint
-        EndpointBuilder endpointBuilder = new EndpointBuilder(endpointBuilder(ipAddress, macAddress, connectorId,
-                null, null).build());
-        endpointBuilder.setTenant(indexedTenantBuilder().getTenant().getId());
+        EndpointBuilder endpointBuilder = new EndpointBuilder(buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0)
+                .build());
+        endpointBuilder.setTenant(getTestIndexedTenant().getTenant().getId());
         Endpoint endpoint = endpointBuilder.build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
         when(ctx.getSwitchManager()).thenReturn(switchManager);
         when(ctx.getPolicyManager()).thenReturn(policyManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(endpointManager.getEndpointNodeConnectorId(Mockito.any(Endpoint.class)))
                 .thenReturn(new NodeConnectorId(CONNECTOR_0));
-        when(switchManager.getTunnelPort(nodeId, TunnelTypeVxlan.class)).thenReturn(new NodeConnectorId(CONNECTOR_0));
-        when(switchManager.getTunnelPort(nodeId, TunnelTypeVxlanGpe.class)).thenReturn(new NodeConnectorId(CONNECTOR_1));
+        when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlan.class)).thenReturn(new NodeConnectorId(CONNECTOR_0));
+        when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(new NodeConnectorId(CONNECTOR_1));
         when(switchManager.getExternalPorts(Mockito.any(NodeId.class))).thenReturn(connectors);
 
         PortSecurityFlows flows = mock(PortSecurityFlows.class);
         PortSecurity portSecurity = new PortSecurity(ctx, tableId);
-        portSecurity.syncFlows(flows, nodeId, endpoint, ofWriter);
+        portSecurity.syncFlows(flows, NODE_ID, endpoint, ofWriter);
 
         // Verify usage
         verify(flows, times(4)).dropFlow(Mockito.anyInt(), Mockito.anyLong(), eq(ofWriter));
@@ -81,7 +76,7 @@ public class PortSecurityTest extends MapperUtilsTest {
         verify(flows, times(1)).l2flow(Mockito.anyShort(), Mockito.any(NodeConnectorId.class),
                 Mockito.any(MacAddress.class), Mockito.anyInt(), eq(ofWriter));
         verify(flows, times(1)).popVlanTagsOnExternalPortFlows(Mockito.anyShort(), Mockito.any(NodeConnectorId.class),
-                eq(l2FloodDomains()), Mockito.anyInt(), eq(ofWriter));
+                eq(getL2FloodDomainList(false)), Mockito.anyInt(), eq(ofWriter));
         verify(flows, times(1)).allowFromExternalPortFlow(Mockito.anyShort(), Mockito.any(NodeConnectorId.class),
                 Mockito.anyInt(), eq(ofWriter));
 
@@ -108,7 +103,7 @@ public class PortSecurityTest extends MapperUtilsTest {
         order.verify(ctx, times(1)).getSwitchManager();
         order.verify(ctx, times(2)).getTenant(Mockito.any(TenantId.class));
         order.verify(flows, times(1)).popVlanTagsOnExternalPortFlows(Mockito.anyShort(), Mockito.any(NodeConnectorId.class),
-                eq(l2FloodDomains()), Mockito.anyInt(), eq(ofWriter));
+                eq(getL2FloodDomainList(false)), Mockito.anyInt(), eq(ofWriter));
         order.verify(flows, times(1)).allowFromExternalPortFlow(Mockito.anyShort(), Mockito.any(NodeConnectorId.class),
                 Mockito.anyInt(), eq(ofWriter));
     }
index eccef1cb710a61f5470d5ea696d39518f1b78d50..ebf4480d05d524c246eea9202bafefc89bba78cd 100644 (file)
@@ -12,8 +12,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowIdUtils;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
@@ -32,11 +30,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 
-import java.lang.reflect.Field;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import static org.junit.Assert.assertNotNull;
 import static org.mockito.Mockito.*;
@@ -44,11 +40,6 @@ import static org.mockito.Mockito.*;
 
 public class SourceMapperFlowsTest extends MapperUtilsTest {
 
-    private static final String DROP = "drop";
-    private static final String DROP_ALL = "dropAll";
-    private static final String TUNNEL = "tunnel";
-    private static final String FLOOD_ID = "tunnelFdId";
-
     private SourceMapperFlows flows;
 
     @Before
@@ -58,16 +49,16 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         endpointManager = mock(EndpointManager.class);
         policyInfo = mock(PolicyInfo.class);
         ofWriter = mock(OfWriter.class);
-        flows = new SourceMapperFlows(nodeId, tableId);
+        flows = new SourceMapperFlows(NODE_ID, tableId);
         OrdinalFactory.resetPolicyOrdinalValue();
     }
 
     @Test
     public void dropFlow_noEthertype() {
-        Flow testFlow = flowBuilder(new FlowId(DROP_ALL), tableId, 100, null, FlowUtils.dropInstructions()).build();
+        Flow testFlow = buildFlow(new FlowId(DROP_ALL), tableId, 100, null, FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, null, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -75,11 +66,11 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.IPv4, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -87,11 +78,11 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv6));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.IPv6, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
@@ -99,20 +90,19 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         MatchBuilder matchBuilder = new MatchBuilder();
         matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.ARP));
         Match match = matchBuilder.build();
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, DROP, match), tableId, 100, match,
                 FlowUtils.dropInstructions()).build();
 
         flows.dropFlow(100, FlowUtils.ARP, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void synchronizeEp() throws Exception {
-        Endpoint testEndpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_1),
-                new NodeConnectorId(CONNECTOR_1), null, null).build();
+        Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_1).build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
 
         OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
@@ -120,7 +110,7 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         InOrder order = inOrder(ctx);
         order.verify(ctx, times(1)).getEndpointManager();
         order.verify(ctx, times(1)).getCurrentPolicy();
-        verify(ctx, times(2)).getTenant(new TenantId(TENANT_ID));
+        verify(ctx, times(2)).getTenant(TENANT_ID);
         assertNotNull(ordinals);
 
         Action reg0 = FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1));
@@ -145,20 +135,19 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
                 .setInPort(new NodeConnectorId(CONNECTOR_1));
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, "ep", match), tableId, 90, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "ep", match), tableId, 90, match,
                 instructionsBuilder.build()).build();
 
         flows.synchronizeEp((short) 3, 90, ordinals, new MacAddress(MAC_1), new NodeConnectorId(CONNECTOR_1), ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void createTunnelFlow() throws Exception {
-        Endpoint testEndpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_0), null, null).build();
+        Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
 
         OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
@@ -166,7 +155,7 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         InOrder order = inOrder(ctx);
         order.verify(ctx, times(1)).getEndpointManager();
         order.verify(ctx, times(1)).getCurrentPolicy();
-        verify(ctx, times(2)).getTenant(new TenantId(TENANT_ID));
+        verify(ctx, times(2)).getTenant(TENANT_ID);
         assertNotNull(ordinals);
 
         Action reg0 = FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1));
@@ -189,20 +178,19 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         FlowUtils.addNxTunIdMatch(matchBuilder, 2);
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, TUNNEL, match), tableId, 80, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "tunnel", match), tableId, 80, match,
                 instructionsBuilder.build()).build();
 
         flows.createTunnelFlow((short) 3, 80, new NodeConnectorId(CONNECTOR_0), ordinals, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 
     @Test
     public void createBroadcastFlow() throws Exception {
-        Endpoint testEndpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_0),
-                new NodeConnectorId(CONNECTOR_1), null, null).build();
+        Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_1).build();
 
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
 
         OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
@@ -210,7 +198,7 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         InOrder order = inOrder(ctx);
         order.verify(ctx, times(1)).getEndpointManager();
         order.verify(ctx, times(1)).getCurrentPolicy();
-        verify(ctx, times(2)).getTenant(new TenantId(TENANT_ID));
+        verify(ctx, times(2)).getTenant(TENANT_ID);
         assertNotNull(ordinals);
 
         Action reg5 = FlowUtils.nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(0));
@@ -229,10 +217,10 @@ public class SourceMapperFlowsTest extends MapperUtilsTest {
         FlowUtils.addNxTunIdMatch(matchBuilder, 0);
         Match match = matchBuilder.build();
 
-        Flow testFlow = flowBuilder(FlowIdUtils.newFlowId(tableId, FLOOD_ID, match), tableId, 80, match,
+        Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "tunnelFdId", match), tableId, 80, match,
                 instructionsBuilder.build()).build();
 
         flows.createBroadcastFlow((short) 3, 80, new NodeConnectorId(CONNECTOR_1), ordinals, ofWriter);
-        verify(ofWriter, times(1)).writeFlow(nodeId, tableId, testFlow);
+        verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
     }
 }
\ No newline at end of file
index 9a093addd1a0706f1e0e0295beb45eb35296b4bd..0b61f1899fa364711ca8153b9f08c3376e3f4f0c 100644 (file)
@@ -13,8 +13,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointMan
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
@@ -47,27 +45,25 @@ public class SourceMapperTest extends MapperUtilsTest {
 
     @Test
     public void syncFlows_tunnelPortTest() {
-        Endpoint endpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_1)), new MacAddress(MAC_1),
-                new NodeConnectorId(CONNECTOR_0), null, null).build();
+        Endpoint endpoint = buildEndpoint(IPV4_0, MAC_1, CONNECTOR_0).build();
         EndpointBuilder endpointBuilder = new EndpointBuilder(endpoint);
-        endpointBuilder.setEndpointGroup(new EndpointGroupId(EPG_ID));
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_1);
 
         // List of other endpoints (one entry is good enough)
         HashSet<Endpoint> otherEndpoints = new HashSet<>();
-        Endpoint otherEndpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_2)), new MacAddress(MAC_1),
-                new NodeConnectorId(CONNECTOR_1), null, null).build();
+        Endpoint otherEndpoint = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1).build();
         EndpointBuilder otherEndpointBuilder = new EndpointBuilder(otherEndpoint);
-        otherEndpointBuilder.setEndpointGroup(new EndpointGroupId(ENDPOINT_GROUP_0));
+        otherEndpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
         List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
-        endpointGroupIds.add(new EndpointGroupId(ENDPOINT_GROUP_1));
-        endpointGroupIds.add(new EndpointGroupId(ENDPOINT_GROUP_2));
+        endpointGroupIds.add(ENDPOINT_GROUP_1);
+        endpointGroupIds.add(ENDPOINT_GROUP_2);
         otherEndpointBuilder.setEndpointGroups(endpointGroupIds);
         otherEndpoints.add(otherEndpointBuilder.build());
 
         // NodeId set
         Set<NodeId> nodeIds = new HashSet<>();
-        nodeIds.add(nodeId);
-        nodeIds.add(new NodeId("some Id"));
+        nodeIds.add(NODE_ID);
+        nodeIds.add(new NodeId("someNodeId"));
 
         SourceMapper sourceMapper = new SourceMapper(ctx, tableId);
 
@@ -75,20 +71,20 @@ public class SourceMapperTest extends MapperUtilsTest {
         when(ctx.getSwitchManager()).thenReturn(switchManager);
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(policyManager.getTABLEID_DESTINATION_MAPPER()).thenReturn((short) 3);
-        when(switchManager.getTunnelPort(nodeId, TunnelTypeVxlan.class)).thenReturn(new NodeConnectorId(CONNECTOR_1));
+        when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlan.class)).thenReturn(new NodeConnectorId(CONNECTOR_1));
         when(endpointManager.getEndpointsForGroup(Mockito.any(EgKey.class))).thenReturn(otherEndpoints);
 
         SourceMapperFlows flows = mock(SourceMapperFlows.class);
 
-        sourceMapper.syncFlows(flows, endpointBuilder.build(), nodeId, ofWriter);
+        sourceMapper.syncFlows(flows, endpointBuilder.build(), NODE_ID, ofWriter);
 
         // Verify method usage
         verify(ctx, times(3)).getEndpointManager();
         verify(ctx, times(5)).getTenant(Mockito.any(TenantId.class));
         verify(ctx.getPolicyManager(), times(1)).getTABLEID_DESTINATION_MAPPER();
-        verify(ctx.getSwitchManager(), times(1)).getTunnelPort(nodeId, TunnelTypeVxlan.class);
+        verify(ctx.getSwitchManager(), times(1)).getTunnelPort(NODE_ID, TunnelTypeVxlan.class);
         verify(ctx.getEndpointManager(), times(1)).getEndpointsForGroup(Mockito.any(EgKey.class));
 
         // Verify order
@@ -108,13 +104,12 @@ public class SourceMapperTest extends MapperUtilsTest {
 
     @Test
     public void syncFlows_endpointGroupsOnly() {
-        Endpoint endpoint = endpointBuilder(new IpAddress(new Ipv4Address(IPV4_2)), new MacAddress(MAC_1),
-                new NodeConnectorId(CONNECTOR_1), null, null).build();
+        Endpoint endpoint = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1).build();
         EndpointBuilder endpointBuilder = new EndpointBuilder(endpoint);
-        endpointBuilder.setEndpointGroup(new EndpointGroupId(ENDPOINT_GROUP_0));
+        endpointBuilder.setEndpointGroup(ENDPOINT_GROUP_0);
         List<EndpointGroupId> endpointGroupIds = new ArrayList<>();
-        endpointGroupIds.add(new EndpointGroupId(ENDPOINT_GROUP_1));
-        endpointGroupIds.add(new EndpointGroupId(ENDPOINT_GROUP_2));
+        endpointGroupIds.add(ENDPOINT_GROUP_1);
+        endpointGroupIds.add(ENDPOINT_GROUP_2);
         endpointBuilder.setEndpointGroups(endpointGroupIds);
 
         SourceMapper sourceMapper = new SourceMapper(ctx, tableId);
@@ -123,17 +118,17 @@ public class SourceMapperTest extends MapperUtilsTest {
         when(ctx.getSwitchManager()).thenReturn(switchManager);
         when(ctx.getEndpointManager()).thenReturn(endpointManager);
         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
-        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(indexedTenantBuilder());
+        when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
         when(policyManager.getTABLEID_DESTINATION_MAPPER()).thenReturn((short) 3);
 
         SourceMapperFlows flows = mock(SourceMapperFlows.class);
 
-        sourceMapper.syncFlows(flows, endpointBuilder.build(), nodeId, ofWriter);
+        sourceMapper.syncFlows(flows, endpointBuilder.build(), NODE_ID, ofWriter);
 
         // Verify OfContext method usage
         verify(ctx, times(3)).getTenant(Mockito.any(TenantId.class));
         verify(ctx.getPolicyManager(), times(1)).getTABLEID_DESTINATION_MAPPER();
-        verify(ctx.getSwitchManager(), times(1)).getTunnelPort(nodeId, TunnelTypeVxlan.class);
+        verify(ctx.getSwitchManager(), times(1)).getTunnelPort(NODE_ID, TunnelTypeVxlan.class);
 
         // Verify order
         InOrder order = inOrder(ctx, flows);