Adding multiple EPG capability to EPs and IntraEPG policy 12/17812/10
authorKeith Burns (alagalah) <alagalah@gmail.com>
Sun, 8 Feb 2015 18:56:05 +0000 (10:56 -0800)
committerKeith Burns (alagalah) <alagalah@gmail.com>
Fri, 10 Apr 2015 01:17:19 +0000 (18:17 -0700)
Change-Id: I00ed21b0765912c689c57c72c1b4463544bf1a73
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
23 files changed:
.gitignore
commons/parent/pom.xml
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/endpoint/EndpointRpcRegistry.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/resolver/InheritanceUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/resolver/PolicyResolver.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/EndpointManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/SwitchManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.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/GroupTable.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OfTable.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OrdinalFactory.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PortSecurity.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/SourceMapper.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapperTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowTableTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/GroupTableTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OfTableTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcerTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PortSecurityTest.java [changed mode: 0644->0755]
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/SourceMapperTest.java [changed mode: 0644->0755]

index f2a64ab8f9646c1ad8a6da2345a79e38d173407b..4fb945a4be68099096f4e1270df00e1802b86c62 100644 (file)
@@ -18,3 +18,5 @@ target
 .settings
 MANIFEST.MF
 renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/resolver/
+.gitignore
+.checkstyle
index 5fbec5608d909d63206a00a76a88407d80b38d16..ec175f1c46e22d9d069dc87c43408602fd250080 100644 (file)
@@ -23,6 +23,7 @@
     <openflowplugin.distribution.version>0.1.0-SNAPSHOT</openflowplugin.distribution.version>
     <openflowplugin-nicira.version>0.1.0-SNAPSHOT</openflowplugin-nicira.version>
     <openflowjava.distribution.version>0.6.0-SNAPSHOT</openflowjava.distribution.version>
+    <restconf.project.version>1.2.0-SNAPSHOT</restconf.project.version>
     <config.configfile.directory>etc/opendaylight/karaf</config.configfile.directory>
     <groupbasedpolicy.project.version>0.2.0-SNAPSHOT</groupbasedpolicy.project.version>
     <config.groupbasedpolicy.ofoverlayconfigfile>15-groupbasedpolicy-ofoverlay.xml</config.groupbasedpolicy.ofoverlayconfigfile>
index f5c4a58ea38658abc50a6d5c803b8b26cc7952e6..e94f2f17975b6c9ade4df161e929383a7991a944 100644 (file)
@@ -178,7 +178,7 @@ public class EndpointRpcRegistry implements EndpointService {
             });
         }
 
-        // XXX TODO - age out endpoint data and remove
+        // TODO Be alagalah - age out endpoint data and remove
         // endpoint group/condition mappings with no conditions
     }
 
index 47e5d2ff74129acfe06b38b0a2624bc27ca6e819..e49fd2e2b844d8142143be7f3b71bf0983580fd1 100644 (file)
@@ -47,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ContractBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup.IntraGroupPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
@@ -86,6 +87,8 @@ import com.google.common.collect.ImmutableList;
  * Utilities useful for resolving the inheritance rules for the various objects
  * in the system
  *
+ * @author readams
+ *
  */
 public class InheritanceUtils {
     /**
@@ -162,6 +165,7 @@ public class InheritanceUtils {
         HashMap<SelectorName, ProviderNamedSelector> resolvedPns =
                 new HashMap<>();
         NetworkDomainId domain = unresolvedEg.getNetworkDomain();
+        IntraGroupPolicy igp = unresolvedEg.getIntraGroupPolicy();
 
         if (unresolvedEg.getConsumerTargetSelector() != null) {
             for (ConsumerTargetSelector s : unresolvedEg.getConsumerTargetSelector()) {
@@ -212,6 +216,9 @@ public class InheritanceUtils {
             if (domain == null) {
                 domain = parent.getNetworkDomain();
             }
+            if (igp == null) {
+                igp = parent.getIntraGroupPolicy();
+            }
         }
 
         // Note: do not set parent, or any of the values that only exist
@@ -219,11 +226,13 @@ public class InheritanceUtils {
         EndpointGroup resolvedEg = new EndpointGroupBuilder()
                 .setId(unresolvedEg.getId())
                 .setDescription(unresolvedEg.getDescription())
+                .setName(unresolvedEg.getName())
                 .setConsumerTargetSelector(ImmutableList.copyOf(resolvedCts.values()))
                 .setConsumerNamedSelector(ImmutableList.copyOf(resolvedCns.values()))
                 .setProviderTargetSelector(ImmutableList.copyOf(resolvedPts.values()))
                 .setProviderNamedSelector(ImmutableList.copyOf(resolvedPns.values()))
                 .setNetworkDomain(domain)
+                .setIntraGroupPolicy(igp)
                 .build();
         resolvedEgs.put(resolvedEg.getId(), resolvedEg);
     }
index 1c3aca97c920737d3477ad3079ad89e6b727b650..6371f10a30f2d5150fff309c6257ee2d87680642 100644 (file)
@@ -83,24 +83,20 @@ import com.google.common.util.concurrent.ListenableFuture;
  * The policy resolver is a utility for renderers to help in resolving
  * group-based policy into a form that is easier to apply to the actual network.
  *
- * <p>
  * For any pair of endpoint groups, there is a set of rules that could apply to
  * the endpoints on that group based on the policy configuration. The exact list
  * of rules that apply to a given pair of endpoints depends on the conditions
  * that are active on the endpoints.
  *
- * <p>
  * We need to be able to query against this policy model, enumerate the relevant
  * classes of traffic and endpoints, and notify renderers when there are changes
  * to policy as it applies to active sets of endpoints and endpoint groups.
  *
- * <p>
  * The policy resolver will maintain the necessary state for all tenants in its
  * control domain, which is the set of tenants for which policy listeners have
  * been registered.
  *
  */
-
 public class PolicyResolver implements AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(PolicyResolver.class);
 
@@ -672,7 +668,8 @@ public class PolicyResolver implements AutoCloseable {
             selectSubjects(Table<EgKey, EgKey,
                     List<ContractMatch>> contractMatches,
                     Map<EgKey, Set<ConditionSet>> egConditions) {
-        // Note that it's possible to further simplify the resulting policy
+        // TODO: Note that it's possible to further simplify the resulting
+        // policy
         // in the case of things like repeated rules, condition sets that
         // cover other condition sets, etc. This would be a good thing to do
         // at some point
index 735076320e17b90e07153b91af21179456b60150..e45165bf16f8470d013f0c58a82d36bfaca4ef6e 100644 (file)
@@ -8,9 +8,9 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -27,7 +27,6 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.endpoint.EndpointRpcRegistry;
 import org.opendaylight.groupbasedpolicy.endpoint.EpKey;
@@ -36,11 +35,11 @@ import org.opendaylight.groupbasedpolicy.resolver.EgKey;
 import org.opendaylight.groupbasedpolicy.util.SetUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 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.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
-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.EndpointL3Builder;
@@ -65,9 +64,6 @@ import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.CheckedFuture;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
 
 /**
  * Keep track of endpoints on the system. Maintain an index of endpoints and
@@ -78,6 +74,8 @@ import com.google.common.util.concurrent.Futures;
  * In order to render the policy, we need to be able to efficiently enumerate
  * all endpoints on a particular switch and also all the switches containing
  * each particular endpoint group
+ *
+ * @author readams
  */
 public class EndpointManager implements AutoCloseable, DataChangeListener
 {
@@ -96,8 +94,11 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
 
     private final ConcurrentHashMap<EpKey, Endpoint> endpoints =
             new ConcurrentHashMap<>();
-    private final ConcurrentHashMap<NodeId, ConcurrentMap<EgKey, Set<EpKey>>> endpointsByNode =
+    private final ConcurrentHashMap<NodeId, ConcurrentMap<EgKey, Set<EpKey>>> endpointsByGroupByNode =
+            new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<NodeId, Set<EpKey>> endpointsByNode =
             new ConcurrentHashMap<>();
+
     private final ConcurrentHashMap<EgKey, Set<EpKey>> endpointsByGroup =
             new ConcurrentHashMap<>();
 
@@ -154,7 +155,7 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
      * @return a collection of {@link Endpoint} objects.
      */
     public Set<EgKey> getGroupsForNode(NodeId nodeId) {
-        Map<EgKey, Set<EpKey>> nodeEps = endpointsByNode.get(nodeId);
+        Map<EgKey, Set<EpKey>> nodeEps = endpointsByGroupByNode.get(nodeId);
         if (nodeEps == null)
             return Collections.emptySet();
         return Collections.unmodifiableSet(nodeEps.keySet());
@@ -163,17 +164,17 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
     /**
      * Get the set of nodes
      *
-     * @param nodeId
-     *            the nodeId of the switch to get endpoints for
-     * @return a collection of {@link Endpoint} objects.
+     * @param egKey
+     *            the egKey of the endpointgroup to get nodes for
+     * @return a collection of {@link NodeId} objects.
      */
     public Set<NodeId> getNodesForGroup(final EgKey egKey) {
-        return Collections.unmodifiableSet(Sets.filter(endpointsByNode.keySet(),
+        return Collections.unmodifiableSet(Sets.filter(endpointsByGroupByNode.keySet(),
                 new Predicate<NodeId>() {
                     @Override
                     public boolean apply(NodeId input) {
                         Map<EgKey, Set<EpKey>> nodeEps =
-                                endpointsByNode.get(input);
+                                endpointsByGroupByNode.get(input);
                         return (nodeEps != null &&
                         nodeEps.containsKey(egKey));
                     }
@@ -190,8 +191,11 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
      *            the group to look up
      * @return the endpoints
      */
-    public Collection<Endpoint> getEPsForNode(NodeId nodeId, EgKey eg) {
-        Map<EgKey, Set<EpKey>> nodeEps = endpointsByNode.get(nodeId);
+    public Collection<Endpoint> getEndpointsForNode(NodeId nodeId, EgKey eg) {
+        // TODO: alagalah Create method findEndpointsByNode() that uses
+        // datastore
+
+        Map<EgKey, Set<EpKey>> nodeEps = endpointsByGroupByNode.get(nodeId);
         if (nodeEps == null)
             return Collections.emptyList();
         Collection<EpKey> ebn = nodeEps.get(eg);
@@ -202,6 +206,54 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
                         indexTransform));
     }
 
+    /**
+     * Get the endpoints on a particular node
+     *
+     * @param nodeId
+     *            the node ID to look up
+     * @return the endpoints
+     */
+    public Collection<Endpoint> getEndpointsForNode(final NodeId nodeId) {
+        // TODO: alagalah Create method findEndpointsByNode() that uses
+        // datastore. See commented code below.
+
+        Collection<Endpoint> epsByNode = Collections.emptyList();
+        // Blocking for test.
+        // // Predicate for filtering only the endpoints we need for this nodeID
+        // //TODO: This pulls from datastore. Will be more performant to update
+        // // endpointByNode in updateEndpoint.
+        // Predicate<Endpoint> predicate = new Predicate<Endpoint>() {
+        // @Override
+        // public boolean apply(Endpoint ep) {
+        // return
+        // ep.getAugmentation(OfOverlayContext.class).getNodeId().getValue().equals(nodeId.getValue());
+        // }
+        // };
+        //
+        // Optional<Endpoints> epResult;
+        // final InstanceIdentifier<Endpoints> endpointsIid =
+        // InstanceIdentifier.builder(Endpoints.class).build();
+        // try {
+        // epResult =
+        // dataProvider.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL,
+        // endpointsIid).get();
+        // if(epResult.isPresent()) {
+        // Endpoints endpoints = epResult.get();
+        // epsByNode =
+        // Collections2.filter((Collection<Endpoint>)endpoints.getEndpoint(),predicate);
+        // }
+        // } catch (InterruptedException | ExecutionException e) {
+        // LOG.error("Caught exception in getEPsForNode");
+        // }
+        Collection<EpKey> ebn = endpointsByNode.get(nodeId);
+        if (ebn == null)
+            return Collections.emptyList();
+        return Collections.unmodifiableCollection(Collections2
+                .transform(ebn,
+                        indexTransform));
+
+    }
+
     /**
      * Get the endpoint object for the given key
      *
@@ -247,7 +299,8 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
      * @return the list of {@link ConditionName}
      */
     public List<ConditionName> getCondsForEndpoint(Endpoint endpoint) {
-        // XXX TODO consider group conditions as well. Also need to notify
+        // TODO Be alagalah From Helium: consider group conditions as well. Also
+        // need to notify
         // endpoint updated if the endpoint group conditions change
         if (endpoint.getCondition() != null)
             return endpoint.getCondition();
@@ -322,6 +375,11 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
         }
     }
 
+    // TODO: alagalah Investigate using the internal project listener structure
+    // for this. ie Endpoint should listen to
+    // SwitchManager updates and update the EP maps accordingly (update
+    // Endpoint). Removal should include the overloaded
+    // method updateEndpoint(Node node)
     private class NodesListener implements DataChangeListener {
         @Override
         public void onDataChanged(
@@ -331,8 +389,7 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
                     continue;
                 Node node = (Node) dao;
                 if (node.getNodeConnector() != null) {
-                    executor.execute(new UpdateEndpoint(node));
-                    return;
+                    updateEndpoint(node);
                 }
             }
             for (DataObject dao : change.getUpdatedData().values()) {
@@ -340,115 +397,83 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
                     continue;
                 Node node = (Node) dao;
                 if (node.getNodeConnector() != null) {
-                    executor.execute(new UpdateEndpoint(node));
-                    return;
+                    updateEndpoint(node);
                 }
             }
         }
     }
 
-    private class UpdateEndpoint implements Runnable {
-        private final Node node;
-        private final InstanceIdentifier<Endpoints> endpointsIid;
+    // TODO Li alagalah move this near to other updateEndpoint()
+    private void updateEndpoint(Node node) {
+        final InstanceIdentifier<Endpoints> endpointsIid = InstanceIdentifier.builder(Endpoints.class).build();
 
-        public UpdateEndpoint(Node node) {
-            this.node = node;
-            this.endpointsIid = InstanceIdentifier.builder(Endpoints.class).build();
-        }
-
-        @Override
-        public void run() {
-            Optional<Endpoints> epResult;
-            EpKey epKey = null;
-            for (NodeConnector nc : node.getNodeConnector()) {
-                FlowCapableNodeConnector fcnc = nc
-                        .getAugmentation(FlowCapableNodeConnector.class);
-                try {
-                    epResult = dataProvider.newReadOnlyTransaction()
-                            .read(LogicalDatastoreType.OPERATIONAL, endpointsIid).get();
-                    if (epResult.isPresent()) {
-                        Endpoints endpoints = epResult.get();
-                        if (endpoints.getEndpoint() != null) {
-                            WriteTransaction tx = dataProvider.newWriteOnlyTransaction();
-                            Boolean isEmpty = true;
-                            for (Endpoint ep : endpoints.getEndpoint()) {
-                                // 2. Search for portname
-                                OfOverlayContext currentAugmentation = ep.getAugmentation(OfOverlayContext.class);
-                                if (ep.getPortName().getValue().equals(fcnc.getName())) {
-                                    NodeId nodeId;
-                                    NodeConnectorId nodeConnectorId;
-                                    try {
-                                        nodeId = currentAugmentation.getNodeId();
-                                        nodeConnectorId = currentAugmentation.getNodeConnectorId();
-                                    } catch (Exception e) {
-                                        nodeId = null;
-                                        nodeConnectorId = null;
-                                    }
-                                    Boolean process = false;
-                                    if (nodeId == null && nodeConnectorId == null) {
-                                        LOG.debug("ep NodeID and NC ID Both null");
+        Optional<Endpoints> epResult;
+        EpKey epKey = null;
+        for (NodeConnector nc : node.getNodeConnector()) {
+            FlowCapableNodeConnector fcnc = nc
+                    .getAugmentation(FlowCapableNodeConnector.class);
+            try {
+                epResult = dataProvider.newReadOnlyTransaction().read(LogicalDatastoreType.OPERATIONAL, endpointsIid)
+                        .get();
+                if (epResult.isPresent()) {
+                    Endpoints endpoints = epResult.get();
+                    if (endpoints.getEndpoint() != null) {
+                        Boolean isEmpty = true;
+                        for (Endpoint ep : endpoints.getEndpoint()) {
+                            // 2. Search for portname
+                            OfOverlayContext currentAugmentation = ep.getAugmentation(OfOverlayContext.class);
+                            if (ep.getPortName() != null && fcnc.getName() != null
+                                    && ep.getPortName().getValue().equals(fcnc.getName())) {
+                                NodeId nodeId;
+                                NodeConnectorId nodeConnectorId;
+                                try {
+                                    nodeId = currentAugmentation.getNodeId();
+                                    nodeConnectorId = currentAugmentation.getNodeConnectorId();
+                                } catch (Exception e) {
+                                    nodeId = null;
+                                    nodeConnectorId = null;
+                                }
+                                Boolean process = false;
+                                if (nodeId == null && nodeConnectorId == null) {
+                                    LOG.debug("ep NodeID and NC ID Both null");
+                                    process = true;
+                                }
+                                if (nodeId != null && nodeConnectorId != null) {
+                                    if (!(nodeConnectorId.getValue().equals(nc.getId().getValue()))) {
+                                        LOG.debug("ep NodeID and NC ID Both NOT null but epNCID !=nodeNCID");
                                         process = true;
                                     }
+                                }
+                                if (process) {
+                                    WriteTransaction tx = dataProvider.newWriteOnlyTransaction();
+                                    // 3. Update endpoint
+                                    EndpointBuilder epBuilder = new EndpointBuilder(ep);
+                                    OfOverlayContextBuilder ofOverlayAugmentation = new OfOverlayContextBuilder();
+                                    ofOverlayAugmentation.setNodeId(node.getId());
+                                    ofOverlayAugmentation.setNodeConnectorId(nc.getId());
+                                    epBuilder.addAugmentation(OfOverlayContext.class, ofOverlayAugmentation.build());
+                                    epBuilder.setL3Address(ep.getL3Address());
+                                    InstanceIdentifier<Endpoint> iidEp = InstanceIdentifier.builder(Endpoints.class)
+                                            .child(Endpoint.class, ep.getKey()).build();
+                                    tx.put(LogicalDatastoreType.OPERATIONAL, iidEp, epBuilder.build());
+                                    tx.submit().get();
+                                    epKey = new EpKey(ep.getKey().getL2Context(), ep.getKey().getMacAddress());
+                                    notifyEndpointUpdated(epKey);
+                                    LOG.debug("Values:");
+                                    LOG.debug("node: Node ID:" + node.getId().getValue());
+                                    LOG.debug("node: NodeConnectorID: " + nc.getId().getValue());
                                     if (nodeId != null && nodeConnectorId != null) {
-                                        if (!(nodeConnectorId.getValue().equals(nc.getId().getValue()))) {
-                                            LOG.debug("ep NodeID and NC ID Both NOT null but epNCID !=nodeNCID");
-                                            process = true;
-                                        }
-                                    }
-                                    if (process) {
-                                        // 3. Update endpoint
-                                        EndpointBuilder epBuilder = new EndpointBuilder(ep);
-                                        OfOverlayContextBuilder ofOverlayAugmentation = new OfOverlayContextBuilder();
-                                        ofOverlayAugmentation.setNodeId(node.getId());
-                                        ofOverlayAugmentation.setNodeConnectorId(nc.getId());
-                                        epBuilder
-                                                .addAugmentation(OfOverlayContext.class, ofOverlayAugmentation.build());
-                                        // TODO Hack to remove:
-                                        List<L3Address> l3Addresses = new ArrayList<>();
-                                        for (L3Address l3Address : ep.getL3Address()) {
-                                            L3AddressBuilder l3AB = new L3AddressBuilder();
-                                            l3AB.setIpAddress(l3Address.getIpAddress()).setL3Context(
-                                                    l3Address.getL3Context());
-                                            l3Addresses.add(l3AB.build());
-                                        }
-                                        epBuilder.setL3Address(l3Addresses);
-                                        InstanceIdentifier<Endpoint> iidEp = InstanceIdentifier
-                                                .builder(Endpoints.class).child(Endpoint.class, ep.getKey()).build();
-                                        tx.put(LogicalDatastoreType.OPERATIONAL, iidEp, epBuilder.build());
-                                        epKey = new EpKey(ep.getKey().getL2Context(), ep.getKey().getMacAddress());
-                                        LOG.debug("Values:");
-                                        LOG.debug("node: Node ID:" + node.getId().getValue());
-                                        LOG.debug("node: NodeConnectorID: " + nc.getId().getValue());
-                                        if (nodeId != null && nodeConnectorId != null) {
-                                            LOG.debug("ep: nodeID:" + nodeId.getValue());
-                                            LOG.debug("ep: nodeConnectorID:" + nodeConnectorId.getValue());
-                                        }
-                                        isEmpty = false;
+                                        LOG.debug("ep: nodeID:" + nodeId.getValue());
+                                        LOG.debug("ep: nodeConnectorID:" + nodeConnectorId.getValue());
                                     }
+                                    isEmpty = false;
                                 }
                             }
-                            if (!isEmpty) {
-                                CheckedFuture<Void, TransactionCommitFailedException> f = tx.submit();
-                                notifyEndpointUpdated(epKey);
-                                Futures.addCallback(f, new FutureCallback<Void>() {
-                                    @Override
-                                    public void onFailure(Throwable t) {
-                                        LOG.error("Could not over-write endpoint with augmentation", t);
-                                    }
-
-                                    @Override
-                                    public void onSuccess(Void result) {
-                                        LOG.debug("Success over-writing endpoint augmentation");
-                                    }
-                                });
-                            } else {
-                                LOG.debug("UpdateEndpoint: Empty list");
-                            }
                         }
                     }
-                } catch (InterruptedException | ExecutionException e) {
-                    LOG.error("Caught exception in UpdateEndpoint", e);
                 }
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Exception in UpdateEndpoint", e);
             }
         }
     }
@@ -485,7 +510,7 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
 
     private boolean validEp(Endpoint endpoint) {
         return (endpoint != null && endpoint.getTenant() != null &&
-                endpoint.getEndpointGroup() != null &&
+                (endpoint.getEndpointGroup() != null || endpoint.getEndpointGroups() != null) &&
                 endpoint.getL2Context() != null && endpoint.getMacAddress() != null);
     }
 
@@ -506,18 +531,32 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
         return new EpKey(endpoint.getL2Context(), endpoint.getMacAddress());
     }
 
-    private EgKey getEgKey(Endpoint endpoint) {
+    public EgKey getEgKey(Endpoint endpoint) {
         if (!validEp(endpoint))
             return null;
         return new EgKey(endpoint.getTenant(), endpoint.getEndpointGroup());
     }
 
+    public Set<EgKey> getEgKeysForEndpoint(Endpoint ep) {
+        Set<EgKey> egKeys = new HashSet<EgKey>();
+
+        if (ep.getEndpointGroup() != null) {
+            egKeys.add(new EgKey(ep.getTenant(), ep.getEndpointGroup()));
+        }
+        if (ep.getEndpointGroups() != null) {
+            for (EndpointGroupId epgId : ep.getEndpointGroups()) {
+                egKeys.add(new EgKey(ep.getTenant(), epgId));
+            }
+        }
+        return egKeys;
+    }
+
     private Set<EpKey> getEpNGSet(NodeId location, EgKey eg) {
-        ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByNode.get(location);
+        ConcurrentMap<EgKey, Set<EpKey>> map = endpointsByGroupByNode.get(location);
         if (map == null) {
             map = new ConcurrentHashMap<>();
             ConcurrentMap<EgKey, Set<EpKey>> old =
-                    endpointsByNode.putIfAbsent(location, map);
+                    endpointsByGroupByNode.putIfAbsent(location, map);
             if (old != null)
                 map = old;
         }
@@ -535,72 +574,248 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
      * Update the endpoint indexes. Set newEp to null to remove.
      */
     protected void updateEndpoint(Endpoint oldEp, Endpoint newEp) {
-        // XXX TODO only keep track of endpoints that are attached
+        // TODO Be alagalah From Helium only keep track of endpoints that are
+        // attached
         // to switches that are actually connected to us
+
+        // TODO Li alagalah: This needs a major clean up and refactor. For now
+        // it works.
         NodeId oldLoc = getLocation(oldEp);
         NodeId newLoc = getLocation(newEp);
-
-        EgKey oldKey = getEgKey(oldEp);
-        EgKey newKey = getEgKey(newEp);
-
-        EpKey epKey = getEpKey(oldEp);
-        if (epKey == null)
-            epKey = getEpKey(newEp);
-        if (epKey == null)
-            return;
+        // EgKey oldEgKey = getEgKey(oldEp);
+        EpKey oldEpKey = getEpKey(oldEp);
+        EpKey newEpKey = getEpKey(newEp);
 
         boolean notifyOldLoc = false;
         boolean notifyNewLoc = false;
         boolean notifyOldEg = false;
         boolean notifyNewEg = false;
 
-        if (newEp != null)
-            endpoints.put(epKey, newEp);
-
-        if (oldLoc != null && oldKey != null &&
-                (newLoc == null || !oldLoc.equals(newLoc) ||
-                        newKey == null || !oldKey.equals(newKey))) {
-            ConcurrentMap<EgKey, Set<EpKey>> map =
-                    endpointsByNode.get(oldLoc);
-            Set<EpKey> eps = map.get(oldKey);
-            eps.remove(epKey);
-            map.remove(oldKey, Collections.emptySet());
-            endpointsByNode.remove(oldLoc, EMPTY_MAP);
-            notifyOldLoc = true;
-        }
-        if (oldKey != null &&
-                (newKey == null || !oldKey.equals(newKey))) {
-            Set<EpKey> gns = getEpGSet(oldKey);
-            gns.remove(epKey);
-            notifyOldEg = true;
-        }
+        // When newLoc and oldLoc are null there is nothing to do
+        if (!(newLoc == null && oldLoc == null)) {
 
-        if (newLoc != null && newKey != null) {
-            Set<EpKey> eps = getEpNGSet(newLoc, newKey);
-            eps.add(epKey);
-            LOG.debug("Endpoint {} added to node {}", epKey, newLoc);
-            notifyNewLoc = true;
-        }
-        if (newKey != null) {
-            Set<EpKey> gns = getEpGSet(newKey);
-            gns.add(epKey);
-            LOG.debug("Endpoint {} added to group {}", epKey, newKey);
-            notifyNewEg = true;
-        }
+            Set<EndpointGroupId> newEpgIds = new HashSet<EndpointGroupId>();
+            TenantId tenantId = null;
+            if (newEp != null) {
+                if (newEp.getEndpointGroups() != null) {
+                    newEpgIds.addAll(newEp.getEndpointGroups());
+                }
+                if (newEp.getEndpointGroup() != null) {
+                    newEpgIds.add(newEp.getEndpointGroup());
+                }
+                tenantId = newEp.getTenant();
+            }
+
+            Set<EndpointGroupId> oldEpgIds = new HashSet<EndpointGroupId>();
+            if (oldEp != null) {
+                if (oldEp.getEndpointGroups() != null) {
+                    oldEpgIds.addAll(oldEp.getEndpointGroups());
+                }
+                if (oldEp.getEndpointGroup() != null) {
+                    oldEpgIds.add(oldEp.getEndpointGroup());
+                }
+            }
 
-        if (newEp == null)
-            endpoints.remove(epKey);
+            /*
+             * maintainIndex(endpointsByNode,oldEp,newEp) Maintain following
+             * maps endpoints - <EpKey, Endpoint> endpointsByGroupByNode -
+             * <NodeId, ConcurrentMap<EgKey, Set<EpKey>>> endpointsByNode -
+             * <NodeId,Set<EpKey>> endpointsByGroup ConcurrentHashMap<EgKey,
+             * Set<EpKey>>
+             */
+
+            // Maintain "endpoints" map
+            if (newEp != null) {
+                endpoints.put(newEpKey, newEp);
+            } else {
+                endpoints.remove(oldEpKey);
+            }
 
-        notifyEndpointUpdated(epKey);
+            /*
+             * New endpoint with location information
+             */
+            if (oldEp == null && newEp != null && newLoc != null) {
+                // Update endpointsByNode
+                if (endpointsByNode.get(newLoc) == null) {
+                    // TODO: alagalah cleaner way with checking epsNode
+                    // then do this.
+                    Set<EpKey> epsNode = new HashSet<EpKey>();
+                    epsNode.add(newEpKey);
+                    endpointsByNode.put(newLoc, epsNode);
+                } else {
+                    Set<EpKey> epsNode = endpointsByNode.get(newLoc);
+                    epsNode.add(newEpKey);
+                }
+                // Update endpointsByGroupByNode and endpointsByGroup
+                for (EndpointGroupId newEpgId : newEpgIds) {
+                    // endpointsByGroupByNode
+                    EgKey newEgKey = new EgKey(tenantId, newEpgId);
+                    Set<EpKey> eps = getEpNGSet(newLoc, newEgKey);
+                    eps.add(newEpKey);
+                    // endpointsByGroup
+                    Set<EpKey> geps = endpointsByGroup.get(newEgKey);
+                    if (geps == null) {
+                        geps = new HashSet<>();
+                    }
+                    geps.add(newEpKey);
+                    endpointsByGroup.put(newEgKey, geps);
+                    LOG.debug("Endpoint {} added to node {}", newEpKey, newLoc);
 
-        if (notifyOldLoc)
-            notifyNodeEndpointUpdated(oldLoc, epKey);
-        if (notifyNewLoc)
-            notifyNodeEndpointUpdated(newLoc, epKey);
-        if (notifyOldEg)
-            notifyGroupEndpointUpdated(oldKey, epKey);
-        if (notifyNewEg)
-            notifyGroupEndpointUpdated(newKey, epKey);
+                }
+
+                notifyNewLoc = true;
+                notifyNewEg = true;
+            }
+
+            /*
+             * Removed endpoint
+             */
+            if (oldEp != null && newEp == null) {
+                // Update endpointsByNode
+                Set<EpKey> epsNode = endpointsByNode.get(oldLoc);
+                if (epsNode != null) {
+                    epsNode.remove(oldEpKey);
+                    if (epsNode.isEmpty())
+                        endpointsByNode.remove(oldLoc);
+                }
+                // Update endpointsByGroupByNode
+                // Update endpointsByGroup
+                // Get map of EPGs and their Endpoints for Node
+                ConcurrentMap<EgKey, Set<EpKey>> map =
+                        endpointsByGroupByNode.get(oldLoc);
+                // For each EPG in the removed endpoint...
+                for (EndpointGroupId oldEpgId : newEpgIds) {
+                    EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
+                    // Get list of endpoints for EPG
+                    Set<EpKey> eps = map.get(oldEgKey);
+                    // Remove the endpoint from the map
+                    if (eps != null) {
+                        eps.remove(oldEpKey);
+                        if (eps.isEmpty())
+                            map.remove(oldEgKey, Collections.emptySet());
+                    }
+                    // endpointsByGroup
+                    Set<EpKey> geps = endpointsByGroup.get(oldEgKey);
+                    if (geps != null) {
+                        geps.remove(oldEpKey);
+                        if (geps.isEmpty())
+                            endpointsByGroup.remove(oldEgKey);
+                    }
+                }
+                // If map is empty, no more EPGs on this node, remove node from
+                // map
+                if (map.isEmpty())
+                    endpointsByGroupByNode.remove(oldLoc, EMPTY_MAP);
+                notifyOldLoc = true;
+                notifyOldEg = true;
+            }
+
+            /*
+             * Moved endpoint (from node to node or from NULL to node)
+             */
+            if ((oldEp != null && newEp != null && oldEpKey != null && newEpKey != null) &&
+                    (oldEpKey.toString().equals(newEpKey.toString()))) {
+                // old and new Endpoints have same key. (same endpoint)
+
+                /*
+                 * Remove old endpoint if moved.
+                 */
+                if (oldLoc != null && !(oldLoc.getValue().equals(newLoc.getValue()))) {
+                    // This is an endpoint that has moved, remove from old node
+                    Set<EpKey> epsNode = endpointsByNode.get(oldLoc);
+                    if (epsNode != null) {
+                        epsNode.remove(oldEpKey);
+                        if (epsNode.isEmpty())
+                            endpointsByNode.remove(oldLoc);
+                    }
+                    // Update endpointsByGroupByNode
+                    // Get map of EPGs and their Endpoints for Node
+                    ConcurrentMap<EgKey, Set<EpKey>> map =
+                            endpointsByGroupByNode.get(oldLoc);
+                    // For each EPG in the removed endpoint...
+                    for (EndpointGroupId oldEpgId : oldEpgIds) {
+                        EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
+                        // Get list of endpoints for EPG
+                        Set<EpKey> eps = map.get(oldEgKey);
+                        // Remove the endpoint from the map
+                        if (eps != null) {
+                            eps.remove(oldEpKey);
+                            if (eps.isEmpty())
+                                map.remove(oldEgKey, Collections.emptySet());
+                        }
+                        // endpointsByGroup
+                        Set<EpKey> geps = endpointsByGroup.get(oldEgKey);
+                        if (geps != null)
+                        {
+                            geps.remove(oldEpKey);
+                            if (geps.isEmpty())
+                                endpointsByGroup.remove(oldEgKey);
+                        }
+                    }
+                    // If map is empty, no more EPGs on this node, remove node
+                    // from map
+                    if (map.isEmpty())
+                        endpointsByGroupByNode.remove(oldLoc, EMPTY_MAP);
+                    notifyOldLoc = true;
+                    notifyOldEg = true;
+                }
+
+                /*
+                 * Add new endpoint
+                 */
+                // Update endpointsByNode
+                if (endpointsByNode.get(newLoc) == null) {
+                    Set<EpKey> newEpsNode = new HashSet<EpKey>();
+                    newEpsNode.add(newEpKey);
+                    endpointsByNode.put(newLoc, newEpsNode);
+                } else {
+                    Set<EpKey> newEpsNode = endpointsByNode.get(newLoc);
+                    newEpsNode.add(newEpKey);
+                }
+                notifyNewLoc = true;
+
+                // Update endpointsByGroupByNode
+                // Update endpointsByGroup
+                for (EndpointGroupId newEpgId : newEpgIds) {
+                    EgKey newEgKey = new EgKey(tenantId, newEpgId);
+                    Set<EpKey> eps = getEpNGSet(newLoc, newEgKey);
+                    eps.add(newEpKey);
+                    // endpointsByGroup
+                    Set<EpKey> geps = endpointsByGroup.get(newEgKey);
+                    if (geps == null) {
+                        geps = new HashSet<>();
+                    }
+                    geps.add(newEpKey);
+                    endpointsByGroup.put(newEgKey, geps);
+                    notifyNewEg = true;
+
+                    LOG.debug("Endpoint {} added to node {}", newEpKey, newLoc);
+                }
+
+            }
+
+            if (newEp != null)
+                notifyEndpointUpdated(newEpKey);
+            else
+                notifyEndpointUpdated(oldEpKey);
+
+            // TODO alagalah NEXt: ensure right notification flags are set.
+            if (notifyOldLoc)
+                notifyNodeEndpointUpdated(oldLoc, oldEpKey);
+            if (notifyNewLoc)
+                notifyNodeEndpointUpdated(newLoc, newEpKey);
+            if (notifyOldEg)
+                for (EndpointGroupId oldEpgId : oldEpgIds) {
+                    EgKey oldEgKey = new EgKey(oldEp.getTenant(), oldEpgId);
+                    notifyGroupEndpointUpdated(oldEgKey, oldEpKey);
+                }
+            if (notifyNewEg)
+                for (EndpointGroupId newEpgId : newEpgIds) {
+                    EgKey newEgKey = new EgKey(newEp.getTenant(), newEpgId);
+                    notifyGroupEndpointUpdated(newEgKey, newEpKey);
+                }
+
+        }
     }
 
     private OfOverlayContextBuilder checkAugmentation(RegisterEndpointInput input) {
@@ -623,7 +838,7 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
         return ictxBuilder;
     }
 
-    // A wrapper class around node, noeConnector info so we can pass a final
+    // A wrapper class around node, nodeConnector info so we can pass a final
     // object inside OnSuccess anonymous inner class
     private static class NodeInfo {
         NodeConnector nodeConnector;
@@ -687,7 +902,7 @@ public class EndpointManager implements AutoCloseable, DataChangeListener
                     }
                 }
             } catch (InterruptedException | ExecutionException e) {
-                LOG.error("Could not fetch Node Augmentation", e);
+                LOG.error("Caught exception in fetchAugmentation portName", e);
             }
 
         }
index 63c71232c9aa9f3a4ad8c714434a50f98d258aa8..0a5c1d2d6b85fb536e0f5c21b51de9e52c5ddd12 100644 (file)
@@ -8,8 +8,9 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay;
 
-import java.util.Collections;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionService;
@@ -19,31 +20,30 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorCompletionService;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.endpoint.EpKey;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.DestinationMapper;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OfTable;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PortSecurity;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.SourceMapper;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.SubjectFeatures;
-import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyListener;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyScope;
-import org.opendaylight.groupbasedpolicy.util.SetUtils;
 import org.opendaylight.groupbasedpolicy.util.SingletonTask;
-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.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig.LearningMode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -52,27 +52,28 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 
 /**
- * Manage policies on switches by subscribing to updates from the 
- * policy resolver and information about endpoints from the endpoint 
+ * Manage policies on switches by subscribing to updates from the
+ * policy resolver and information about endpoints from the endpoint
  * registry
- * @author readams
  */
-public class PolicyManager 
+public class PolicyManager
      implements SwitchListener, PolicyListener, EndpointListener {
-    private static final Logger LOG = 
+    private static final Logger LOG =
             LoggerFactory.getLogger(PolicyManager.class);
 
     private final SwitchManager switchManager;
     private final PolicyResolver policyResolver;
-    
+
     private final PolicyScope policyScope;
-    
-    private final AtomicReference<Dirty> dirty;
-    
+
     private final ScheduledExecutorService executor;
     private final SingletonTask flowUpdateTask;
+    private final DataBroker dataBroker;
 
     /**
      * The flow tables that make up the processing pipeline
@@ -85,39 +86,24 @@ public class PolicyManager
      */
     private final static int FLOW_UPDATE_DELAY = 250;
 
-    /**
-     * Counter used to allocate ordinal values for forwarding contexts
-     * and VNIDs
-     */
-    private final AtomicInteger policyOrdinal = new AtomicInteger(1);
-    
-    /**
-     * Keep track of currently-allocated ordinals
-     */
-    // XXX For the endpoint groups, we need a globally unique ordinal, so
-    // should ultimately involve some sort of distributed agreement
-    // or a leader to allocate them.  For now we'll just use a counter and
-    // this local map.  Also theoretically need to garbage collect periodically
-    private final ConcurrentMap<String, Integer> ordinals = 
-            new ConcurrentHashMap<>();
-    // XXX - need to garbage collect
-    private final ConcurrentMap<ConditionGroup, Integer> cgOrdinals = 
-            new ConcurrentHashMap<>();
-            
+
+
     public PolicyManager(DataBroker dataBroker,
                          PolicyResolver policyResolver,
                          SwitchManager switchManager,
-                         EndpointManager endpointManager, 
+                         EndpointManager endpointManager,
                          RpcProviderRegistry rpcRegistry,
                          ScheduledExecutorService executor) {
         super();
         this.switchManager = switchManager;
         this.executor = executor;
         this.policyResolver = policyResolver;
+        this.dataBroker = dataBroker;
+
 
         if (dataBroker != null) {
             WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-            t.put(LogicalDatastoreType.OPERATIONAL, 
+            t.put(LogicalDatastoreType.OPERATIONAL,
                   InstanceIdentifier
                       .builder(SubjectFeatureDefinitions.class)
                       .build(),
@@ -126,7 +112,7 @@ public class PolicyManager
         }
 
         OfContext ctx = new OfContext(dataBroker, rpcRegistry,
-                                        this, policyResolver, switchManager, 
+                                        this, policyResolver, switchManager,
                                         endpointManager, executor);
         flowPipeline = ImmutableList.of(new PortSecurity(ctx),
                                         new GroupTable(ctx),
@@ -138,12 +124,10 @@ public class PolicyManager
         if (switchManager != null)
             switchManager.registerListener(this);
         endpointManager.registerListener(this);
-        
-        dirty = new AtomicReference<>(new Dirty());
-        
+
         flowUpdateTask = new SingletonTask(executor, new FlowUpdateTask());
         scheduleUpdate();
-        
+
         LOG.debug("Initialized OFOverlay policy manager");
     }
 
@@ -153,18 +137,19 @@ public class PolicyManager
 
     @Override
     public void switchReady(final NodeId nodeId) {
+        //TODO Apr15 alagalah : OVSDB CRUD tunnels may go here.
 //        WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-//        
+//
 //        NodeBuilder nb = new NodeBuilder()
 //            .setId(nodeId)
-//            .addAugmentation(FlowCapableNode.class, 
+//            .addAugmentation(FlowCapableNode.class,
 //                             new FlowCapableNodeBuilder()
 //                                .build());
-//        t.merge(LogicalDatastoreType.CONFIGURATION, 
+//        t.merge(LogicalDatastoreType.CONFIGURATION,
 //                FlowUtils.createNodePath(nodeId),
 //                nb.build(), true);
 //        ListenableFuture<Void> result = t.submit();
-//        Futures.addCallback(result, 
+//        Futures.addCallback(result,
 //                            new FutureCallback<Void>() {
 //            @Override
 //            public void onSuccess(Void result) {
@@ -177,41 +162,36 @@ public class PolicyManager
 //                LOG.error("Could not add switch {}", nodeId, t);
 //            }
 //        });
-        
+
     }
 
     @Override
     public void switchRemoved(NodeId sw) {
         // XXX TODO purge switch flows
-        dirty.get().addNode(sw);
         scheduleUpdate();
     }
-    
+
     @Override
     public void switchUpdated(NodeId sw) {
-        dirty.get().addNode(sw);
         scheduleUpdate();
     }
 
     // ****************
     // EndpointListener
     // ****************
-    
+
     @Override
     public void endpointUpdated(EpKey epKey) {
-        dirty.get().addEndpoint(epKey);
         scheduleUpdate();
     }
 
     @Override
     public void nodeEndpointUpdated(NodeId nodeId, EpKey epKey){
-        dirty.get().addNodeEp(nodeId, epKey);
         scheduleUpdate();
     }
 
     @Override
     public void groupEndpointUpdated(EgKey egKey, EpKey epKey) {
-        dirty.get().addEndpointGroupEp(egKey, epKey);
         policyScope.addToScope(egKey.getTenantId(), egKey.getEgId());
         scheduleUpdate();
     }
@@ -219,12 +199,9 @@ public class PolicyManager
     // **************
     // PolicyListener
     // **************
-    
+
     @Override
     public void policyUpdated(Set<EgKey> updatedConsumers) {
-        for (EgKey key : updatedConsumers) {
-            dirty.get().addEndpointGroup(key);
-        }
         scheduleUpdate();
     }
 
@@ -240,89 +217,93 @@ public class PolicyManager
         // No-op for now
     }
 
-    /**
-     * Get a unique ordinal for the given condition group, suitable for
-     * use in the data plane.  This is unique only for this node, and not 
-     * globally.
-     * @param cg the {@link ConditionGroup}
-     * @return the unique ID
-     */
-    public int getCondGroupOrdinal(final ConditionGroup cg) {
-        if (cg == null) return 0;
-        Integer ord = cgOrdinals.get(cg);
-        if (ord == null) {
-            ord = policyOrdinal.getAndIncrement();
-            Integer old = cgOrdinals.putIfAbsent(cg, ord);
-            if (old != null) ord = old; 
-        }
-        return ord.intValue();
-    }
-    
-    /**
-     * Get a 32-bit context ordinal suitable for use in the OF data plane
-     * for the given policy item. 
-     * @param tenantId the tenant ID of the element
-     * @param id the unique ID for the element
-     * @return the 32-bit ordinal value
-     */
-    public int getContextOrdinal(final TenantId tenantId, 
-                                 final UniqueId id) throws Exception {
-        if (tenantId == null || id == null) return 0;
-        return getContextOrdinal(tenantId.getValue() + "|" + id.getValue());
-    }
 
-    /**
-     * Get a 32-bit context ordinal suitable for use in the OF data plane
-     * for the given policy item.
-     * @param id the unique ID for the element
-     * @return the 32-bit ordinal value
-     */
-    public int getContextOrdinal(final String id) throws Exception {
 
-        Integer ord = ordinals.get(id);
-        if (ord == null) {
-            ord = policyOrdinal.getAndIncrement();
-            Integer old = ordinals.putIfAbsent(id, ord);
-            if (old != null) ord = old;
-        }
-        return ord.intValue();
-    }
-    
     // **************
     // Implementation
     // **************
 
+    public class FlowMap{
+        private ConcurrentMap<InstanceIdentifier<Table>, TableBuilder> flowMap = new ConcurrentHashMap<>();
+
+        public FlowMap() {
+        }
+
+        public TableBuilder getTableForNode(NodeId nodeId, short tableId) {
+            InstanceIdentifier<Table> tableIid = FlowUtils.createTablePath(nodeId, tableId);
+            if(this.flowMap.get(tableIid) == null) {
+                this.flowMap.put(tableIid, new TableBuilder().setId(tableId));
+                this.flowMap.get(tableIid).setFlow(new ArrayList<Flow>());
+            }
+            return this.flowMap.get(tableIid);
+        }
+
+        public void writeFlow(NodeId nodeId,short tableId, Flow flow) {
+            TableBuilder tableBuilder = this.getTableForNode(nodeId, tableId);
+            if (!tableBuilder.getFlow().contains(flow)) {
+                tableBuilder.getFlow().add(flow);
+            }
+        }
+
+        public void commitToDataStore() {
+            if (dataBroker != null) {
+                WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+                for( Entry<InstanceIdentifier<Table>, TableBuilder> entry : flowMap.entrySet()) {
+                    t.put(LogicalDatastoreType.CONFIGURATION,
+                          entry.getKey(), entry.getValue().build(),true);
+                }
+
+                CheckedFuture<Void, TransactionCommitFailedException> f = t.submit();
+                Futures.addCallback(f, new FutureCallback<Void>() {
+                    @Override
+                    public void onFailure(Throwable t) {
+                        LOG.error("Could not write flow table.", t);
+                    }
+
+                    @Override
+                    public void onSuccess(Void result) {
+                        LOG.debug("Flow table updated.");
+                    }
+                });
+            }
+        }
+
+     }
+
     private void scheduleUpdate() {
         if (switchManager != null) {
             LOG.trace("Scheduling flow update task");
             flowUpdateTask.reschedule(FLOW_UPDATE_DELAY, TimeUnit.MILLISECONDS);
         }
     }
-    
+
     /**
      * Update the flows on a particular switch
      */
     private class SwitchFlowUpdateTask implements Callable<Void> {
-        private final Dirty dirty;
-        private final NodeId nodeId;
+        private FlowMap flowMap;
 
-        public SwitchFlowUpdateTask(Dirty dirty, NodeId nodeId) {
+        public SwitchFlowUpdateTask(FlowMap flowMap) {
             super();
-            this.dirty = dirty;
-            this.nodeId = nodeId;
+            this.flowMap = flowMap;
         }
 
         @Override
         public Void call() throws Exception {
-            if (!switchManager.isSwitchReady(nodeId)) return null;
-            PolicyInfo info = policyResolver.getCurrentPolicy();
-            if (info == null) return null;
-            for (OfTable table : flowPipeline) {
-                try {
-                    table.update(nodeId, info, dirty);
-                } catch (Exception e) {
-                    LOG.error("Failed to write flow table {}", 
-                              table.getClass().getSimpleName(), e);
+            for (NodeId node : switchManager.getReadySwitches()) {
+                if (!switchManager.isSwitchReady(node))
+                    return null;
+                PolicyInfo info = policyResolver.getCurrentPolicy();
+                if (info == null)
+                    return null;
+                for (OfTable table : flowPipeline) {
+                    try {
+                        table.update(node, info, flowMap);
+                    } catch (Exception e) {
+                        LOG.error("Failed to write flow table {}",
+                                table.getClass().getSimpleName(), e);
+                    }
                 }
             }
             return null;
@@ -332,25 +313,26 @@ public class PolicyManager
     /**
      * Update all flows on all switches as needed.  Note that this will block
      * one of the threads on the executor.
-     * @author readams
      */
     private class FlowUpdateTask implements Runnable {
         @Override
         public void run() {
             LOG.debug("Beginning flow update task");
 
-            Dirty d = dirty.getAndSet(new Dirty());
             CompletionService<Void> ecs
                 = new ExecutorCompletionService<Void>(executor);
             int n = 0;
-            for (NodeId node : switchManager.getReadySwitches()) {
-                SwitchFlowUpdateTask swut = new SwitchFlowUpdateTask(d, node);
-                ecs.submit(swut);
-                n += 1;
-            }
+
+            FlowMap flowMap = new FlowMap();
+
+            SwitchFlowUpdateTask swut = new SwitchFlowUpdateTask(flowMap);
+            ecs.submit(swut);
+            n+=1;
+
             for (int i = 0; i < n; i++) {
                 try {
                     ecs.take().get();
+                    flowMap.commitToDataStore();
                 } catch (InterruptedException | ExecutionException e) {
                     LOG.error("Failed to update flow tables", e);
                 }
@@ -358,65 +340,9 @@ public class PolicyManager
             LOG.debug("Flow update completed");
         }
     }
-    
-    /**
-     * Dirty state since our last successful flow table sync.
-     */
-    public static class Dirty {
-        private Set<EpKey> endpoints;
-        private Set<NodeId> nodes;
-        private Set<EgKey> groups;
-        private ConcurrentMap<EgKey, Set<EpKey>> groupEps;
-        private ConcurrentMap<NodeId, Set<EpKey>> nodeEps;
-        
-        public Dirty() {
-            ConcurrentHashMap<EpKey,Boolean> epmap = new ConcurrentHashMap<>();
-            endpoints = Collections.newSetFromMap(epmap);
-            ConcurrentHashMap<NodeId,Boolean> nomap = new ConcurrentHashMap<>();
-            nodes = Collections.newSetFromMap(nomap);
-            ConcurrentHashMap<EgKey,Boolean> grmap = new ConcurrentHashMap<>();
-            groups = Collections.newSetFromMap(grmap);
-
-            groupEps = new ConcurrentHashMap<>();
-            nodeEps = new ConcurrentHashMap<>();
-        }
-        
-        public void addEndpointGroupEp(EgKey egKey, EpKey epKey) {
-            SetUtils.getNestedSet(egKey, groupEps)
-                .add(epKey);
-        }
-        public void addNodeEp(NodeId id, EpKey epKey) {
-            SetUtils.getNestedSet(id, nodeEps).add(epKey);
-        }
-        public void addNode(NodeId id) {
-            nodes.add(id);
-        }
-        public void addEndpointGroup(EgKey key) {
-            groups.add(key);
-        }
-        public void addEndpoint(EpKey epKey) {
-            endpoints.add(epKey);
-        }
 
-        public Set<EpKey> getEndpoints() {
-            return endpoints;
-        }
 
-        public Set<NodeId> getNodes() {
-            return nodes;
-        }
 
-        public Set<EgKey> getGroups() {
-            return groups;
-        }
 
-        public ConcurrentMap<EgKey, Set<EpKey>> getGroupEps() {
-            return groupEps;
-        }
 
-        public ConcurrentMap<NodeId, Set<EpKey>> getNodeEps() {
-            return nodeEps;
-        }
-        
-    }
 }
index c9d9827eefd8a2e8157c1ea6956c9385b85567bc..940f3933395473320e3630e36501efed740feb38 100644 (file)
@@ -131,6 +131,7 @@ public class SwitchManager implements AutoCloseable {
         return state.externalPorts;
     }
     
+    //TODO OVSDB CRUD belongs in here. (see Trello)
     public NodeConnectorId getTunnelPort(NodeId nodeId) {
         SwitchState state = switches.get(nodeId);
         if (state == null) return null;
index a519b98f1a49cc4b83d6403eab5f52040c172748..4dfefdbc79cf62070fb3fcfe167324f4acf03eb8 100644 (file)
@@ -8,25 +8,47 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
+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.createNodePath;
+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.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.nxMoveRegTunIdAction;
+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 java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.endpoint.EpKey;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
-import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
-import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 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;
@@ -35,22 +57,17 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 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;
+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.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.group.types.rev131018.groups.Group;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 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.ofoverlay.rev140528.EndpointLocation.LocationType;
 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.EndpointGroup;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -73,19 +90,24 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
 
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
-
 /**
- * Manage the table that maps the destination address to the next hop
- * for the path as well as applies any relevant routing transformations.
- * @author readams
+ * Manage the table that maps the destination address to the next hop for the
+ * path as well as applies any relevant routing transformations.
+ *
  */
 public class DestinationMapper extends FlowTable {
     protected static final Logger LOG =
             LoggerFactory.getLogger(DestinationMapper.class);
 
+    //TODO Li alagalah: Improve UT coverage for this class.
+
+    //TODO Li alagalah: Use EndpointL3 for L3 flows, Endpoint for L2 flows
+    // This ensures we have the appropriate network-containment'
+
     public static final short TABLE_ID = 2;
     /**
      * This is the MAC address of the magical router in the sky
@@ -105,389 +127,653 @@ public class DestinationMapper extends FlowTable {
     }
 
     @Override
-    public void sync(ReadWriteTransaction t,
-                     InstanceIdentifier<Table> tiid,
-                     Map<String, FlowCtx> flowMap,
-                     NodeId nodeId, PolicyInfo policyInfo, Dirty dirty)
-                             throws Exception {
-        dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
+    public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap)
+            throws Exception {
+
+        flowMap.writeFlow(nodeId,TABLE_ID,dropFlow(Integer.valueOf(1), null));
 
-        HashSet<EgKey> visitedEgs = new HashSet<>();
-        HashSet<Integer> visitedFds = new HashSet<>();
+        Set<EpKey> visitedEps = new HashSet<>();
+        Multimap<Integer,Subnet> subnetsByL3c = HashMultimap.create();
+        Set<Integer> fdIds = new HashSet<>();
 
         for (EgKey epg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
             Set<EgKey> peers = Sets.union(Collections.singleton(epg),
-                                          policyInfo.getPeers(epg));
+                    policyInfo.getPeers(epg));
             for (EgKey peer : peers) {
-                syncEPG(t, tiid, flowMap, nodeId,
-                        policyInfo, peer,
-                        visitedEgs, visitedFds);
+                for(Endpoint epPeer : ctx.getEndpointManager().getEndpointsForGroup(peer)) {
+                    syncEP(flowMap, nodeId, policyInfo, epPeer, visitedEps);
+
+                    //Process subnets and flood-domains for epPeer
+                    EndpointFwdCtxOrdinals epOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, epPeer);
+
+                    subnetsByL3c.putAll(epOrds.getL3Id(),ctx.getPolicyResolver().getTenant(peer.getTenantId()).resolveSubnets(epOrds.getNetworkContainment()));
+                    fdIds.add(epOrds.getFdId());
+                }
+            }
+        }
+        // Write subnet flows
+        for (Integer subnetKey : subnetsByL3c.keySet()) {
+            for(Subnet sn:subnetsByL3c.get(subnetKey)) {
+                flowMap.writeFlow(nodeId, TABLE_ID, createRouterArpFlow(nodeId, sn, subnetKey));
+            }
+        }
+        // Write broadcast flows per flood domain.
+        for (Integer fdId : fdIds) {
+            if (groupExists(nodeId, fdId)) {
+                flowMap.writeFlow(nodeId, TABLE_ID, createBroadcastFlow(fdId));
             }
         }
     }
-
     // set up next-hop destinations for all the endpoints in the endpoint
     // group on the node
-    private void syncEPG(ReadWriteTransaction t,
-                         InstanceIdentifier<Table> tiid,
-                         Map<String, FlowCtx> flowMap,
-                         NodeId nodeId, PolicyInfo policyInfo,
-                         EgKey key,
-                         HashSet<EgKey> visitedEgs,
-                         HashSet<Integer> visitedFds) throws Exception {
-        if (visitedEgs.contains(key)) return;
-        visitedEgs.add(key);
-
-        IndexedTenant tenant = ctx.getPolicyResolver().getTenant(key.getTenantId());
-        EndpointGroup eg = tenant.getEndpointGroup(key.getEgId());
-        L2FloodDomain fd = tenant.resolveL2FloodDomain(eg.getNetworkDomain());
-        Collection<Subnet> sns = tenant.resolveSubnets(eg.getNetworkDomain());
-        L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
-        int l3Id = 0;
-
-        if (l3c != null)
-            l3Id = ctx.getPolicyManager().getContextOrdinal(key.getTenantId(),
-                                                       l3c.getId());
-
-        Collection<Endpoint> egEps = ctx.getEndpointManager()
-                .getEndpointsForGroup(key);
-
-        for (Endpoint e : egEps) {
-            if (e.getTenant() == null || e.getEndpointGroup() == null)
-                continue;
-            OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
-            if (ofc == null || ofc.getNodeId() == null) continue;
-
-            syncEP(t, tiid, flowMap, nodeId, policyInfo, e, ofc, tenant, key);
-        }
-
-        if (fd == null) return;
-        Integer fdId = ctx.getPolicyManager().getContextOrdinal(key.getTenantId(),
-                                                           fd.getId());
-        if (visitedFds.contains(fdId)) return;
-        visitedFds.add(fdId);
 
-        //GroupTable must exist before we start adding flows that direct to it via fdId
-        if(groupExists(nodeId,fdId)) {
 
-            FlowId flowId = new FlowId(new StringBuilder()
-            .append("broadcast|")
-            .append(fdId).toString());
-            if (visit(flowMap, flowId.getValue())) {
-                MatchBuilder mb = new MatchBuilder()
+    private Flow createBroadcastFlow(int fdId) {
+        FlowId flowId = new FlowId(new StringBuilder()
+                .append("broadcast|")
+                .append(fdId).toString());
+        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(fdId)));
-
-                FlowBuilder flow = base()
-                        .setPriority(Integer.valueOf(140))
-                        .setId(flowId)
-                        .setMatch(mb.build())
-                        .setInstructions(instructions(applyActionIns(nxMoveRegTunIdAction(NxmNxReg0.class, false),
-                                groupAction(Long.valueOf(fdId)))));
-                writeFlow(t, tiid, flow.build());
-            }
-        }
-        for (Subnet sn : sns) {
-            writeRouterArpFlow(t, tiid, flowMap, nodeId, sn, l3Id);
-        }
+                        .setEthernetDestination(new EthernetDestinationBuilder()
+                                .setAddress(MULTICAST_MAC)
+                                .setMask(MULTICAST_MAC)
+                                .build())
+                        .build());
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class, Long.valueOf(fdId)));
+
+        FlowBuilder flowb = base()
+                .setPriority(Integer.valueOf(140))
+                .setId(flowId)
+                .setMatch(mb.build())
+                .setInstructions(instructions(applyActionIns(nxMoveRegTunIdAction(NxmNxReg0.class, false),
+                        groupAction(Long.valueOf(fdId)))));
+        return flowb.build();
     }
 
+
+
     private boolean groupExists(NodeId nodeId, Integer fdId) throws Exception {
-        //Fetch existing GroupTables
-        if(ctx.getDataBroker()==null) return false;
+        // Fetch existing GroupTables
+        if(ctx.getDataBroker()==null) {
+            return false;
+        }
 
         ReadOnlyTransaction t = ctx.getDataBroker().newReadOnlyTransaction();
         InstanceIdentifier<Node> niid = createNodePath(nodeId);
         Optional<Node> r =
                 t.read(LogicalDatastoreType.CONFIGURATION, niid).get();
-        if (!r.isPresent()) return false;
+        if (!r.isPresent())
+            return false;
         FlowCapableNode fcn = r.get().getAugmentation(FlowCapableNode.class);
-        if (fcn == null) return false;
+        if (fcn == null)
+            return false;
 
         if (fcn.getGroup() != null) {
             for (Group g : fcn.getGroup()) {
-                if (g.getGroupId().getValue().equals(Long.valueOf(fdId))) { //Group Exists.
+                if (g.getGroupId().getValue().equals(Long.valueOf(fdId))) { // Group
+                                                                            // Exists.
                     return true;
                 }
-
             }
         }
         return false;
     }
 
 
-    private void writeRouterArpFlow(ReadWriteTransaction t,
-                                    InstanceIdentifier<Table> tiid,
-                                    Map<String, FlowCtx> flowMap,
-                                    NodeId nodeId,
-                                    Subnet sn,
-                                    int l3Id) {
+    private Flow createRouterArpFlow(NodeId nodeId,
+            Subnet sn,
+            int l3Id) {
         if (sn != null && sn.getVirtualRouterIp() != null) {
             if (sn.getVirtualRouterIp().getIpv4Address() != null) {
                 String ikey = sn.getVirtualRouterIp().getIpv4Address().getValue();
                 FlowId flowId = new FlowId(new StringBuffer()
-                    .append("routerarp|")
-                    .append(sn.getId().getValue())
-                    .append("|")
-                    .append(ikey)
-                    .append("|")
-                    .append(l3Id)
-                    .toString());
-                if (visit(flowMap, flowId.getValue())) {
+                        .append("routerarp|")
+                        .append(sn.getId().getValue())
+                        .append("|")
+                        .append(ikey)
+                        .append("|")
+                        .append(l3Id)
+                        .toString());
                     MatchBuilder mb = new MatchBuilder()
-                        .setEthernetMatch(ethernetMatch(null, null, ARP))
-                        .setLayer3Match(new ArpMatchBuilder()
-                            .setArpOp(Integer.valueOf(1))
-                            .setArpTargetTransportAddress(new Ipv4Prefix(ikey+"/32"))
-                            .build());
+                            .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)));
+                            Long.valueOf(l3Id)));
                     BigInteger routerMac =
                             new BigInteger(1, bytesFromHexString(ROUTER_MAC
-                                                                 .getValue()));
+                                    .getValue()));
                     FlowBuilder flowb = base()
-                         .setPriority(150)
-                         .setId(flowId)
-                         .setMatch(mb.build())
-                         .setInstructions(instructions(applyActionIns(nxMoveEthSrcToEthDstAction(),
-                                                                      setDlSrcAction(ROUTER_MAC),
-                                                                      nxLoadArpOpAction(BigInteger.valueOf(2L)),
-                                                                      nxMoveArpShaToArpThaAction(),
-                                                                      nxLoadArpShaAction(routerMac),
-                                                                      nxMoveArpSpaToArpTpaAction(),
-                                                                      nxLoadArpSpaAction(ikey),
-                                                                      outputAction(new NodeConnectorId(nodeId.getValue() + ":INPORT")))));
-                    writeFlow(t, tiid, flowb.build());
-                }
+                            .setPriority(150)
+                            .setId(flowId)
+                            .setMatch(mb.build())
+                            .setInstructions(instructions(applyActionIns(nxMoveEthSrcToEthDstAction(),
+                                    setDlSrcAction(ROUTER_MAC),
+                                    nxLoadArpOpAction(BigInteger.valueOf(2L)),
+                                    nxMoveArpShaToArpThaAction(),
+                                    nxLoadArpShaAction(routerMac),
+                                    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());
+                        sn.getVirtualRouterIp(), sn.getId().getValue());
             }
         }
+        return null;
     }
 
-    private void syncEP(ReadWriteTransaction t,
-                        InstanceIdentifier<Table> tiid,
-                        Map<String, FlowCtx> flowMap,
-                        NodeId nodeId, PolicyInfo policyInfo,
-                        Endpoint e, OfOverlayContext ofc,
-                        IndexedTenant tenant, EgKey key)
-                                 throws Exception {
+
+    private Flow createLocalL2Flow(Endpoint ep, EndpointFwdCtxOrdinals epFwdCtxOrds, OfOverlayContext ofc) {
+
+        //TODO Li alagalah - refactor common code but keep simple method
         ArrayList<Instruction> instructions = new ArrayList<>();
-        ArrayList<Instruction> l3instructions = new ArrayList<>();
         List<Action> applyActions = new ArrayList<>();
-        List<Action> l3ApplyActions = new ArrayList<>();
 
         int order = 0;
-        EndpointGroup eg = tenant.getEndpointGroup(e.getEndpointGroup());
-        L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
-        L2BridgeDomain bd = tenant.resolveL2BridgeDomain(eg.getNetworkDomain());
-
-        int egId = 0, bdId = 0, l3Id = 0, cgId = 0;
-
-        egId = ctx.getPolicyManager().getContextOrdinal(e.getTenant(),
-                                                   e.getEndpointGroup());
-        if (bd != null)
-            bdId = ctx.getPolicyManager().getContextOrdinal(e.getTenant(),
-                                                       bd.getId());
-        if (l3c != null)
-            l3Id = ctx.getPolicyManager().getContextOrdinal(e.getTenant(),
-                                                       l3c.getId());
-
-        List<ConditionName> conds = ctx.getEndpointManager().getCondsForEndpoint(e);
-        ConditionGroup cg =
-                policyInfo.getEgCondGroup(new EgKey(e.getTenant(),
-                                                    e.getEndpointGroup()),
-                                          conds);
-        cgId = ctx.getPolicyManager().getCondGroupOrdinal(cg);
+
         Action setdEPG = nxLoadRegAction(NxmNxReg2.class,
-                                         BigInteger.valueOf(egId));
+                BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
         Action setdCG = nxLoadRegAction(NxmNxReg3.class,
-                                        BigInteger.valueOf(cgId));
+                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((short) (getTableId() + 1)))
+                .build();
+        instructions.add(gotoTable);
+
+
+        FlowId flowid = new FlowId(new StringBuilder()
+                .append(epFwdCtxOrds.getBdId())
+                .append("|l2|")
+                .append(ep.getMacAddress().getValue())
+                .append("|")
+                .append(nextHop)
+                .toString());
+        MatchBuilder mb = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null,
+                        ep.getMacAddress(),
+                        null));
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(epFwdCtxOrds.getBdId())));
+        FlowBuilder flowb = base()
+                .setId(flowid)
+                .setPriority(Integer.valueOf(50))
+                .setMatch(mb.build())
+                .setInstructions(new InstructionsBuilder()
+                        .setInstruction(instructions)
+                        .build());
+        return flowb.build();
+    }
+
+
+    private void syncEP(FlowMap flowMap,
+            NodeId nodeId, PolicyInfo policyInfo,
+            Endpoint epPeer, Set<EpKey> visitedEps)
+            throws Exception {
+
+        EpKey epPeerKey = new EpKey(epPeer.getL2Context(),epPeer.getMacAddress());
+
+        if (visitedEps.contains(epPeerKey)) {
+            return;
+        }
+        visitedEps.add(epPeerKey);
+
+        // TODO: Conditions messed up, but for now, send policyInfo until this is fixed.
+        EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, epPeer);
+
+        if (epPeer.getTenant() == null || (epPeer.getEndpointGroup() == null && epPeer.getEndpointGroups() == null))
+            return;
+        OfOverlayContext ofc = epPeer.getAugmentation(OfOverlayContext.class);
+
+
+
+        //////////////////////////////////////////////////////////////////////////////////////////
+        /*
+         * NOT HANDLING EXTERNALS
+         */
         if (LocationType.External.equals(ofc.getLocationType())) {
             // XXX - TODO - perform NAT and send to the external network
-            nextHop = "external";
+            // TODO: Use case neutron gateway interface
             LOG.warn("External endpoints not yet supported");
             return;
-        } else {
-            Action setDlSrc = setDlSrcAction(ROUTER_MAC);
-            Action decTtl = decNwTtlAction();
-
-            if (Objects.equals(ofc.getNodeId(), nodeId)) {
-                // this is a local endpoint; send to the approppriate local
-                // port
-                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;
-                }
+        }
 
-                setNextHop = nxLoadRegAction(NxmNxReg7.class,
-                                             BigInteger.valueOf(portNum));
+        if (Objects.equals(ofc.getNodeId(), nodeId)) {
+            // this is a local endpoint; send to the approppriate local
+            // port
 
-                Action setDlDst = setDlDstAction(e.getMacAddress());
-                l3ApplyActions.add(setDlSrc);
-                l3ApplyActions.add(setDlDst);
-                l3ApplyActions.add(decTtl);
-                order +=1;
-            } else {
-                // this endpoint is on a different switch; send to the
-                // appropriate tunnel
-
-                IpAddress tunDst =
-                        ctx.getSwitchManager().getTunnelIP(ofc.getNodeId());
-                NodeConnectorId tunPort =
-                        ctx.getSwitchManager().getTunnelPort(nodeId);
-                if (tunDst == null) return;
-                if (tunPort == null) return;
-
-                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;
+            flowMap.writeFlow(nodeId, TABLE_ID, createLocalL2Flow(epPeer,epFwdCtxOrds,ofc));
+
+            if (epPeer.getL3Address() == null)
+                return;
+            for (L3Address l3a : epPeer.getL3Address()) {
+                if (l3a.getIpAddress() == null || l3a.getL3Context() == null) {
+                    LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",epPeer.getL3Address().toString());
+                    continue;
                 } else {
-                    // this shouldn't happen
-                    LOG.error("Tunnel IP for {} invalid", ofc.getNodeId());
-                    return;
+                    flowMap.writeFlow(nodeId, TABLE_ID, createLocalL3Flow(epPeer,l3a, epFwdCtxOrds,ofc));
                 }
+            }
+        } else {
+            // this endpoint is on a different switch; send to the
+            // appropriate tunnel
 
+             flowMap.writeFlow(nodeId, TABLE_ID, createRemoteL2Flow(epPeer, nodeId, epFwdCtxOrds, ofc));
 
-                long portNum;
-                try {
-                    portNum = getOfPortNum(tunPort);
-                } catch (NumberFormatException ex) {
-                    LOG.warn("Could not parse port number {}",
-                             ofc.getNodeConnectorId(), ex);
-                    return;
+            if (epPeer.getL3Address() == null)
+                return;
+            for (L3Address l3a : epPeer.getL3Address()) {
+                if (l3a.getIpAddress() == null || l3a.getL3Context() == null) {
+                    LOG.error("Endpoint with L3Address but either IPAddress or L3Context is null. {}",epPeer.getL3Address().toString());
+                    continue;
+                } else {
+                    flowMap.writeFlow(nodeId, TABLE_ID, createRemoteL3Flow(l3a, nodeId,epFwdCtxOrds, ofc));
                 }
+            }
+        } // remote (tunnel)
 
-                setNextHop = nxLoadRegAction(NxmNxReg7.class,
-                                             BigInteger.valueOf(portNum));
-                Action tunIdAction =
-                        nxMoveRegTunIdAction(NxmNxReg0.class, false);
 
-                applyActions.add(tunIdAction);
-                applyActions.add(tundstAction);
-                l3ApplyActions.add(setDlSrc);
-                l3ApplyActions.add(decTtl);
-                order +=1;
-            }
+
+        // }
+
+    }
+
+    /* ##################################
+     * DestMapper Flow methods
+     * ##################################
+     */
+    private Flow createLocalL3Flow(Endpoint ep,L3Address l3a, EndpointFwdCtxOrdinals epFwdCtxOrds,OfOverlayContext ofc) {
+
+        //TODO Li alagalah - refactor common code but keep simple method
+
+        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;
+
+        Action setDlSrc = setDlSrcAction(ROUTER_MAC);
+        Action decTtl = decNwTtlAction();
+
+        // 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));
+
+        Action setDlDst = setDlDstAction(ep.getMacAddress());
+        l3ApplyActions.add(setDlDst);
+        //END L3 LOCAL
+
+        l3ApplyActions.add(setDlSrc);
+        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((short) (getTableId() + 1)))
+        .build();
+        l3instructions.add(gotoTable);
+        Layer3Match m = null;
+        Long etherType = null;
+        String ikey = null;
+        if (l3a.getIpAddress().getIpv4Address() != null) {
+            ikey = l3a.getIpAddress().getIpv4Address().getValue() + "/32";
+            etherType = IPv4;
+            m = new Ipv4MatchBuilder()
+                    .setIpv4Destination(new Ipv4Prefix(ikey))
+                    .build();
+        } else if (l3a.getIpAddress().getIpv6Address() != null) {
+            ikey = l3a.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.",l3a.toString());
+            return null;
+        }
+
+        FlowId flowid = new FlowId(new StringBuilder()
+                .append(Integer.toString(epFwdCtxOrds.getL3Id()))
+                .append("|l3|")
+                .append(ikey)
+                .append("|")
+                .append(Integer.toString(epFwdCtxOrds.getEpgId()))
+                .append(" ")
+                .append(Integer.toString(epFwdCtxOrds.getCgId()))
+                .append("|")
+                .append(nextHop)
+                .toString());
+        MatchBuilder mb = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null,
+                        ROUTER_MAC,
+                        etherType))
+                .setLayer3Match(m);
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class,
+                Long.valueOf(epFwdCtxOrds.getL3Id())));
+        FlowBuilder flowb = base()
+                .setId(flowid)
+                .setPriority(Integer.valueOf(132))
+                .setMatch(mb.build())
+                .setInstructions(new InstructionsBuilder()
+                        .setInstruction(l3instructions)
+                        .build());
+        return flowb.build();
+    }
+
+    private Flow createRemoteL2Flow(Endpoint ep, NodeId nodeId, EndpointFwdCtxOrdinals epFwdCtxOrds, 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(epFwdCtxOrds.getEpgId()));
+        Action setdCG = nxLoadRegAction(NxmNxReg3.class,
+                BigInteger.valueOf(epFwdCtxOrds.getCgId()));
+        Action setNextHop;
+        String nextHop;
+
+        // BEGIN TUNNEL HANDLING
+        IpAddress tunDst =
+                ctx.getSwitchManager().getTunnelIP(ofc.getNodeId());
+        NodeConnectorId tunPort =
+                ctx.getSwitchManager().getTunnelPort(nodeId);
+        if (tunDst == null)
+            return null;
+        if (tunPort == null)
+            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));
+        Action tunIdAction =
+                nxMoveRegTunIdAction(NxmNxReg0.class, false);
+
+        applyActions.add(tunIdAction);
+        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();
+                .setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
         instructions.add(applyActionsIns);
 
-        applyActions.addAll(l3ApplyActions);
         applyActionsIns = new InstructionBuilder()
-            .setOrder(order++)
-            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
-            .build();
-        l3instructions.add(applyActionsIns);
+                .setOrder(order++)
+                .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+                .build();
 
         Instruction gotoTable = new InstructionBuilder()
-            .setOrder(order++)
-            .setInstruction(gotoTableIns((short)(getTableId()+1)))
-            .build();
+                .setOrder(order++)
+                .setInstruction(gotoTableIns((short) (getTableId() + 1)))
+                .build();
         instructions.add(gotoTable);
-        l3instructions.add(gotoTable);
 
         FlowId flowid = new FlowId(new StringBuilder()
-            .append(bdId)
-            .append("|l2|")
-            .append(e.getMacAddress().getValue())
-            .append("|")
-            .append(nextHop)
-            .toString());
-        if (visit(flowMap, flowid.getValue())) {
-            MatchBuilder mb = new MatchBuilder()
+                .append(epFwdCtxOrds.getBdId())
+                .append("|l2|")
+                .append(ep.getMacAddress().getValue())
+                .append("|")
+                .append(nextHop)
+                .toString());
+        MatchBuilder mb = new MatchBuilder()
                 .setEthernetMatch(ethernetMatch(null,
-                                                e.getMacAddress(),
-                                                null));
-            addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(bdId)));
-            FlowBuilder flowb = base()
+                        ep.getMacAddress(),
+                        null));
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg4.class, Long.valueOf(epFwdCtxOrds.getBdId())));
+        FlowBuilder flowb = base()
                 .setId(flowid)
                 .setPriority(Integer.valueOf(50))
                 .setMatch(mb.build())
                 .setInstructions(new InstructionsBuilder()
-                    .setInstruction(instructions)
-                    .build());
+                        .setInstruction(instructions)
+                        .build());
+
+        return flowb.build();
+    }
+
+
+    private Flow createRemoteL3Flow(L3Address l3a, NodeId nodeId, EndpointFwdCtxOrdinals epFwdCtxOrds,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> 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;
+
+        Action setDlSrc = setDlSrcAction(ROUTER_MAC);
+        Action decTtl = decNwTtlAction();
+
+        // BEGIN TUNNEL HANDLING
+        IpAddress tunDst =
+                ctx.getSwitchManager().getTunnelIP(ofc.getNodeId());
+        NodeConnectorId tunPort =
+                ctx.getSwitchManager().getTunnelPort(nodeId);
+        if (tunDst == null)
+            return null;
+        if (tunPort == null)
+            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;
+        }
 
-            writeFlow(t, tiid, flowb.build());
+        long portNum;
+        try {
+            portNum = getOfPortNum(tunPort);
+        } catch (NumberFormatException ex) {
+            LOG.warn("Could not parse port number {}",
+                    ofc.getNodeConnectorId(), ex);
+            return null;
         }
-        if (e.getL3Address() == null) return;
-        for (L3Address l3a : e.getL3Address()) {
-            if (l3a.getIpAddress() == null || l3a.getL3Context() == null)
-                continue;
-            Layer3Match m = null;
-            Long etherType = null;
-            String ikey = null;
-            if (l3a.getIpAddress().getIpv4Address() != null) {
-                ikey = l3a.getIpAddress().getIpv4Address().getValue() + "/32";
-                etherType = IPv4;
-                m = new Ipv4MatchBuilder()
+
+        setNextHop = nxLoadRegAction(NxmNxReg7.class,
+                BigInteger.valueOf(portNum));
+        Action tunIdAction =
+                nxMoveRegTunIdAction(NxmNxReg0.class, false);
+
+        applyActions.add(tunIdAction);
+        applyActions.add(tundstAction);
+        // END TUNNEL
+
+
+        l3ApplyActions.add(setDlSrc);
+        l3ApplyActions.add(decTtl);
+        order += 1;
+        applyActions.add(setdEPG);
+        applyActions.add(setdCG);
+        applyActions.add(setNextHop);
+        l3ApplyActions.add(setDlSrc);
+        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((short) (getTableId() + 1)))
+        .build();
+        l3instructions.add(gotoTable);
+        Layer3Match m = null;
+        Long etherType = null;
+        String ikey = null;
+        if (l3a.getIpAddress().getIpv4Address() != null) {
+            ikey = l3a.getIpAddress().getIpv4Address().getValue() + "/32";
+            etherType = IPv4;
+            m = new Ipv4MatchBuilder()
                     .setIpv4Destination(new Ipv4Prefix(ikey))
                     .build();
-            } else if (l3a.getIpAddress().getIpv6Address() != null) {
-                ikey = l3a.getIpAddress().getIpv6Address().getValue() + "/128";
-                etherType = IPv6;
-                m = new Ipv6MatchBuilder()
+        } else if (l3a.getIpAddress().getIpv6Address() != null) {
+            ikey = l3a.getIpAddress().getIpv6Address().getValue() + "/128";
+            etherType = IPv6;
+            m = new Ipv6MatchBuilder()
                     .setIpv6Destination(new Ipv6Prefix(ikey))
                     .build();
-            } else
-                continue;
+        } else {
+            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.",l3a.toString());
+            return null;
+        }
 
-            flowid = new FlowId(new StringBuilder()
-                .append(l3a.getL3Context().getValue())
+        FlowId flowid = new FlowId(new StringBuilder()
+                .append(Integer.toString(epFwdCtxOrds.getL3Id()))
                 .append("|l3|")
                 .append(ikey)
                 .append("|")
+                .append(Integer.toString(epFwdCtxOrds.getEpgId()))
+                .append(" ")
+                .append(Integer.toString(epFwdCtxOrds.getCgId()))
+                .append("|")
                 .append(nextHop)
                 .toString());
-            if (visit(flowMap, flowid.getValue())) {
-                MatchBuilder mb = new MatchBuilder()
-                    .setEthernetMatch(ethernetMatch(null,
-                                                    ROUTER_MAC,
-                                                    etherType))
-                    .setLayer3Match(m);
-                addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class,
-                                              Long.valueOf(l3Id)));
-                FlowBuilder flowb = base()
-                    .setId(flowid)
-                    .setPriority(Integer.valueOf(132))
-                    .setMatch(mb.build())
-                    .setInstructions(new InstructionsBuilder()
+        MatchBuilder mb = new MatchBuilder()
+                .setEthernetMatch(ethernetMatch(null,
+                        ROUTER_MAC,
+                        etherType))
+                .setLayer3Match(m);
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class,
+                Long.valueOf(epFwdCtxOrds.getL3Id())));
+        FlowBuilder flowb = base()
+                .setId(flowid)
+                .setPriority(Integer.valueOf(132))
+                .setMatch(mb.build())
+                .setInstructions(new InstructionsBuilder()
                         .setInstruction(l3instructions)
                         .build());
-
-                writeFlow(t, tiid, flowb.build());
-            }
-        }
+        return flowb.build();
     }
 
+
     static byte[] bytesFromHexString(String values) {
         String target = "";
         if (values != null) {
index 426f3daedfeab1b02432c09ae2a8322c467d4548..c541725e4358e4c0643f60cc977945dd269681df 100644 (file)
@@ -8,26 +8,17 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 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;
 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.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Optional;
-
 /**
  * Base class for managing flow tables
  * @author readams
@@ -46,40 +37,10 @@ public abstract class FlowTable extends OfTable {
 
     @Override
     public void update(NodeId nodeId, PolicyInfo policyInfo,
-                       Dirty dirty) throws Exception {
-        ReadWriteTransaction t = ctx.getDataBroker().newReadWriteTransaction();
-        InstanceIdentifier<Table> tiid =
-                FlowUtils.createTablePath(nodeId, getTableId());
-        Optional<Table> r =
-                t.read(LogicalDatastoreType.CONFIGURATION, tiid).get();
-
-        // Unfortunately, we need to construct a unique string ID for each
-        // flow which is redundant with all the information in the flow itself
-        // We'll build this map so at least we don't have to be O(n^2)
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-
-        if (r.isPresent()) {
-            Table curTable = (Table)r.get();
-
-            if (curTable.getFlow() != null) {
-                for (Flow f : curTable.getFlow()) {
-                    flowMap.put(f.getId().getValue(), new FlowCtx(f));
-                }
-            }
-        }
-
-        sync(t, tiid, flowMap, nodeId, policyInfo, dirty);
-
-        for (FlowCtx fx : flowMap.values()) {
-            if (!fx.visited) {
-                t.delete(LogicalDatastoreType.CONFIGURATION,
-                         FlowUtils.createFlowPath(tiid, fx.f.getKey()));
-            }
-        }
-
-        t.submit().get();
-        //ListenableFuture<Void> result = t.submit();
-        //Futures.addCallback(result, updateCallback);
+                       FlowMap flowMap) throws Exception {
+
+        sync(nodeId, policyInfo, flowMap);
+
     }
 
     // *********
@@ -90,11 +51,7 @@ public abstract class FlowTable extends OfTable {
      * Sync flow state using the flow map
      * @throws Exception
      */
-    public abstract void sync(ReadWriteTransaction t,
-                              InstanceIdentifier<Table> tiid,
-                              Map<String, FlowCtx> flowMap,
-                              NodeId nodeId, PolicyInfo policyInfo, 
-                              Dirty dirty) throws Exception;
+    public abstract void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) throws Exception;
 
     /**
      * Get the table ID being manipulated
@@ -116,71 +73,26 @@ public abstract class FlowTable extends OfTable {
             .setIdleTimeout(0);
     }
 
-    /**
-     * "Visit" a flow ID by checking if it already exists and if so marking
-     * the {@link FlowCtx} visited bit.
-     * @param flowMap the map containing the existing flows for this table
-     * @param flowId the ID for the flow
-     * @return <code>true</code> if the flow needs to be added
-     */
-    protected static boolean visit(Map<String, FlowCtx> flowMap,
-                                   String flowId) {
-        FlowCtx c = flowMap.get(flowId);
-        if (c != null) {
-            c.visited = true;
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Write the given flow to the transaction
-     */
-    protected static void writeFlow(ReadWriteTransaction t,
-                                    InstanceIdentifier<Table> tiid,
-                                    Flow flow) {
-        LOG.trace("{} {}", flow.getId(), flow);
-        t.put(LogicalDatastoreType.CONFIGURATION,
-              FlowUtils.createFlowPath(tiid, flow.getId()),
-              flow, true);
-    }
-
     /**
      * Write a drop flow for the given ethertype at the given priority.
      * If the ethertype is null, then drop all traffic
      */
-    protected void dropFlow(ReadWriteTransaction t,
-                            InstanceIdentifier<Table> tiid,
-                            Map<String, FlowCtx> flowMap,
-                            Integer priority, Long etherType) {
+    public Flow dropFlow(Integer priority, Long etherType) {
         FlowId flowid = new FlowId(new StringBuilder()
-            .append("drop|")
-            .append(etherType)
-            .toString());
-        if (visit(flowMap, flowid.getValue())) {
-            FlowBuilder flowb = base()
+                .append("drop|")
+                .append(etherType)
+                .toString());
+
+        FlowBuilder flowb = base()
                 .setId(flowid)
                 .setPriority(priority)
                 .setInstructions(FlowUtils.dropInstructions());
-            if (etherType != null)
-                flowb.setMatch(new MatchBuilder()
-                    .setEthernetMatch(FlowUtils.ethernetMatch(null, null, 
-                                                              etherType))
-                        .build());
-            writeFlow(t, tiid, flowb.build());
-        }
+        if (etherType != null)
+            flowb.setMatch(new MatchBuilder()
+                    .setEthernetMatch(FlowUtils.ethernetMatch(null, null,
+                            etherType))
+                    .build());
+        return flowb.build();
     }
 
-    /**
-     * Context object for keeping track of flow state
-     */
-    protected static class FlowCtx {
-        Flow f;
-        boolean visited = false;
-
-        public FlowCtx(Flow f) {
-            super();
-            this.f = f;
-        }
-    }
 }
index eca30d2f179d67655c24a69194fc70e12f5017a8..1c2e1ad5127fc2d59395fe52399d0e80d3070eb8 100644 (file)
@@ -8,6 +8,14 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.actionList;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.createBucketPath;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.createGroupPath;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.createNodePath;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.getOfPortNum;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
@@ -16,9 +24,9 @@ import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
-import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
@@ -35,8 +43,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
 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.EndpointGroup;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
 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.inventory.rev130819.nodes.Node;
@@ -48,12 +54,11 @@ import com.google.common.base.Objects;
 import com.google.common.base.Optional;
 import com.google.common.collect.Ordering;
 
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
-
 /**
  * Manage the group tables for handling broadcast/multicast
- * @author readams
+ *
  */
+
 public class GroupTable extends OfTable {
     private static final Logger LOG =
             LoggerFactory.getLogger(GroupTable.class);
@@ -62,8 +67,9 @@ public class GroupTable extends OfTable {
         super(ctx);
     }
 
+    // @Override
     @Override
-    public void update(NodeId nodeId, PolicyInfo policyInfo, Dirty dirty)
+    public void update(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap)
             throws Exception {
         // there appears to be no way of getting only the existing group
         // tables unfortunately, so we have to get the whole goddamned node.
@@ -73,9 +79,11 @@ public class GroupTable extends OfTable {
         InstanceIdentifier<Node> niid = createNodePath(nodeId);
         Optional<Node> r =
                 t.read(LogicalDatastoreType.CONFIGURATION, niid).get();
-        if (!r.isPresent()) return;
+        if (!r.isPresent())
+            return;
         FlowCapableNode fcn = r.get().getAugmentation(FlowCapableNode.class);
-        if (fcn == null) return;
+        if (fcn == null)
+            return;
 
         HashMap<GroupId, GroupCtx> groupMap = new HashMap<>();
 
@@ -86,13 +94,14 @@ public class GroupTable extends OfTable {
 
                 Buckets bs = g.getBuckets();
                 if (bs != null && bs.getBucket() != null)
-                for (Bucket b : bs.getBucket()) {
-                    gctx.bucketMap.put(b.getBucketId(), new BucketCtx(b));
-                }
+                    for (Bucket b : bs.getBucket()) {
+                        gctx.bucketMap.put(b.getBucketId(), new BucketCtx(b));
+                    }
             }
         }
 
-        sync(nodeId, policyInfo, dirty, groupMap);
+        // sync(nodeId, policyInfo, dirty, groupMap);
+        sync(nodeId, policyInfo, groupMap);
 
         WriteTransaction wt = ctx.getDataBroker().newWriteOnlyTransaction();
         boolean wrote = syncGroupToStore(wt, nodeId, groupMap);
@@ -101,8 +110,8 @@ public class GroupTable extends OfTable {
     }
 
     protected boolean syncGroupToStore(WriteTransaction wt,
-                                       NodeId nodeId,
-                                       HashMap<GroupId, GroupCtx> groupMap) {
+            NodeId nodeId,
+            HashMap<GroupId, GroupCtx> groupMap) {
         boolean wrote = false;
         for (GroupCtx gctx : groupMap.values()) {
             InstanceIdentifier<Group> giid =
@@ -117,12 +126,14 @@ public class GroupTable extends OfTable {
                 // update group table
                 for (BucketCtx bctx : gctx.bucketMap.values()) {
                     BucketId bid;
-                    if (bctx.b != null) bid = bctx.b.getBucketId();
-                    else bid = bctx.newb.getBucketId();
+                    if (bctx.b != null)
+                        bid = bctx.b.getBucketId();
+                    else
+                        bid = bctx.newb.getBucketId();
                     InstanceIdentifier<Bucket> biid =
                             createBucketPath(nodeId,
-                                             gctx.groupId,
-                                             bid);
+                                    gctx.groupId,
+                                    bid);
                     if (!bctx.visited) {
                         // remove bucket
                         wrote = true;
@@ -131,84 +142,79 @@ public class GroupTable extends OfTable {
                         // new bucket
                         buckets.add(bctx.newb);
                     } else if (!Objects.equal(bctx.newb.getAction(),
-                                              Ordering.from(ActionComparator.INSTANCE)
-                                                  .sortedCopy(bctx.b.getAction()))) {
+                            Ordering.from(ActionComparator.INSTANCE)
+                                    .sortedCopy(bctx.b.getAction()))) {
                         // update bucket
                         buckets.add(bctx.newb);
                     }
                 }
                 if (buckets.size() > 0) {
                     GroupBuilder gb = new GroupBuilder()
-                        .setGroupId(gctx.groupId)
-                        .setGroupType(GroupTypes.GroupAll)
-                        .setBuckets(new BucketsBuilder()
-                        .setBucket(buckets)
-                        .build());
+                            .setGroupId(gctx.groupId)
+                            .setGroupType(GroupTypes.GroupAll)
+                            .setBuckets(new BucketsBuilder()
+                                    .setBucket(buckets)
+                                    .build());
                     wrote = true;
                     wt.merge(LogicalDatastoreType.CONFIGURATION,
-                             giid, gb.build());
+                            giid, gb.build());
                 }
             }
         }
         return wrote;
     }
 
-    protected void sync(NodeId nodeId, PolicyInfo policyInfo, Dirty dirty,
-                        HashMap<GroupId, GroupCtx> groupMap) throws Exception {
-
-        for (EgKey epg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
-            IndexedTenant it = ctx.getPolicyResolver().getTenant(epg.getTenantId());
-            if (it == null) continue;
-            EndpointGroup eg = it.getEndpointGroup(epg.getEgId());
-            if (eg == null || eg.getNetworkDomain() == null) continue;
-            L2FloodDomain fd = it.resolveL2FloodDomain(eg.getNetworkDomain());
-            if (fd == null) continue;
-
-            int fdId = ctx.getPolicyManager().getContextOrdinal(epg.getTenantId(),
-                                                           fd.getId());
-            GroupId gid = new GroupId(Long.valueOf(fdId));
-            GroupCtx gctx = groupMap.get(gid);
-            if (gctx == null) {
-                groupMap.put(gid, gctx = new GroupCtx(gid));
-            }
-            gctx.visited = true;
-
-            // we'll use the fdId with the high bit set for remote bucket
-            // and just the local port number for local bucket
-            for (NodeId destNode : ctx.getEndpointManager().getNodesForGroup(epg)) {
-                if (nodeId.equals(destNode)) continue;
-
-                long bucketId = ctx.getPolicyManager()
-                        .getContextOrdinal(destNode.getValue());
-                bucketId |= 1L << 31;
-
-                IpAddress tunDst =
-                        ctx.getSwitchManager().getTunnelIP(destNode);
-                NodeConnectorId tunPort =
-                        ctx.getSwitchManager().getTunnelPort(nodeId);
-                if (tunDst == null || tunPort == null) continue;
-                Action tundstAction = null;
-                if (tunDst.getIpv4Address() != null) {
-                    String nextHop = tunDst.getIpv4Address().getValue();
-                    tundstAction = nxLoadTunIPv4Action(nextHop, true);
-                } else {
-                    LOG.error("IPv6 tunnel destination {} for {} not supported",
-                              tunDst.getIpv6Address().getValue(),
-                              destNode);
-                    continue;
+    protected void sync(NodeId nodeId, PolicyInfo policyInfo, HashMap<GroupId, GroupCtx> groupMap) throws Exception {
+
+
+            for (Endpoint localEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
+                EndpointFwdCtxOrdinals localEpFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, localEp);
+                GroupId gid = new GroupId(Long.valueOf(localEpFwdCtxOrds.getFdId()));
+                GroupCtx gctx = groupMap.get(gid);
+                if (gctx == null) {
+                    groupMap.put(gid, gctx = new GroupCtx(gid));
                 }
+                gctx.visited = true;
 
-                BucketBuilder bb = new BucketBuilder()
-                    .setBucketId(new BucketId(Long.valueOf(bucketId)))
-                    .setAction(actionList(tundstAction,
-                                          outputAction(tunPort)));
-                updateBucket(gctx, bb);
-            }
-            for (Endpoint localEp : ctx.getEndpointManager().getEPsForNode(nodeId, epg)) {
+                for (EgKey epg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
+
+
+                    // we'll use the fdId with the high bit set for remote bucket
+                    // and just the local port number for local bucket
+                    for (NodeId destNode : ctx.getEndpointManager().getNodesForGroup(epg)) {
+                        if (nodeId.equals(destNode))
+                            continue;
+
+                        long bucketId = OrdinalFactory.getContextOrdinal(destNode);
+                        bucketId |= 1L << 31;
+
+                        IpAddress tunDst =
+                                ctx.getSwitchManager().getTunnelIP(destNode);
+                        NodeConnectorId tunPort =
+                                ctx.getSwitchManager().getTunnelPort(nodeId);
+                        if (tunDst == null || tunPort == null)
+                            continue;
+                        Action tundstAction = null;
+                        if (tunDst.getIpv4Address() != null) {
+                            String nextHop = tunDst.getIpv4Address().getValue();
+                            tundstAction = nxLoadTunIPv4Action(nextHop, true);
+                        } else {
+                            LOG.error("IPv6 tunnel destination {} for {} not supported",
+                                    tunDst.getIpv6Address().getValue(),
+                                    destNode);
+                            continue;
+                        }
+
+                        BucketBuilder bb = new BucketBuilder()
+                                .setBucketId(new BucketId(Long.valueOf(bucketId)))
+                                .setAction(actionList(tundstAction,
+                                        outputAction(tunPort)));
+                        updateBucket(gctx, bb);
+                    }
                 OfOverlayContext ofc =
                         localEp.getAugmentation(OfOverlayContext.class);
                 if (ofc == null || ofc.getNodeConnectorId() == null ||
-                    (LocationType.External.equals(ofc.getLocationType())))
+                        (LocationType.External.equals(ofc.getLocationType())))
                     continue;
 
                 long bucketId;
@@ -216,14 +222,14 @@ public class GroupTable extends OfTable {
                     bucketId = getOfPortNum(ofc.getNodeConnectorId());
                 } catch (NumberFormatException e) {
                     LOG.warn("Could not parse port number {}",
-                             ofc.getNodeConnectorId(), e);
+                            ofc.getNodeConnectorId(), e);
                     continue;
                 }
 
                 Action output = outputAction(ofc.getNodeConnectorId());
                 BucketBuilder bb = new BucketBuilder()
-                    .setBucketId(new BucketId(Long.valueOf(bucketId)))
-                    .setAction(actionList(output));
+                        .setBucketId(new BucketId(Long.valueOf(bucketId)))
+                        .setAction(actionList(output));
                 updateBucket(gctx, bb);
             }
         }
@@ -233,7 +239,7 @@ public class GroupTable extends OfTable {
         BucketCtx bctx = gctx.bucketMap.get(bb.getBucketId());
         if (bctx == null) {
             gctx.bucketMap.put(bb.getBucketId(),
-                               bctx = new BucketCtx(null));
+                    bctx = new BucketCtx(null));
         }
         bctx.visited = true;
         bctx.newb = bb.build();
@@ -260,5 +266,4 @@ public class GroupTable extends OfTable {
             this.groupId = groupId;
         }
     }
-
 }
index 9e53feb51e8a7e98cbd3eae5e096b0f2ec31d2f2..53f808d4047f1ec812ce4cbbbe2ec804ccc6b620 100644 (file)
@@ -8,17 +8,9 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
-import java.util.concurrent.ScheduledExecutorService;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.SwitchManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
-import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,9 +41,11 @@ public abstract class OfTable {
      * Update the relevant flow table for the node
      * @param nodeId the node to update
      * @param dirty the dirty set
+     * @param policyInfo
+     * @param flowMap
      * @throws Exception
      */
-    public abstract void update(NodeId nodeId, 
+    public abstract void update(NodeId nodeId,
                                 PolicyInfo policyInfo,
-                                Dirty dirty) throws Exception;
+                                FlowMap flowMap) throws Exception;
 }
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OrdinalFactory.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/OrdinalFactory.java
new file mode 100644 (file)
index 0000000..1667eda
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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.flow;
+
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.opendaylight.groupbasedpolicy.endpoint.EpKey;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
+import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
+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.NetworkDomainId;
+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.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OrdinalFactory {
+
+    private final static Logger LOG = LoggerFactory.getLogger(OrdinalFactory.class);
+
+    /**
+     * Counter used to allocate ordinal values for forwarding contexts and VNIDs
+     */
+    private final static AtomicInteger policyOrdinal = new AtomicInteger(1);
+
+    private final static ConcurrentMap<String, Integer> ordinals =
+            new ConcurrentHashMap<>();
+    // XXX - need to garbage collect
+    private final static ConcurrentMap<ConditionGroup, Integer> cgOrdinals =
+            new ConcurrentHashMap<>();
+
+    public static int getContextOrdinal(final TenantId tenantId,
+            final UniqueId id) throws Exception {
+        if (tenantId == null || id == null)
+            return 0;
+        return getContextOrdinalFromString(tenantId.getValue() + "|" + id.getValue());
+    }
+
+    /**
+     * Get a unique ordinal for the given condition group, suitable for use in
+     * the data plane. This is unique only for this node, and not globally.
+     *
+     * @param cg
+     *            the {@link ConditionGroup}
+     * @return the unique ID
+     */
+    public static int getCondGroupOrdinal(final ConditionGroup cg) {
+        if (cg == null)
+            return 0;
+        Integer ord = cgOrdinals.get(cg);
+        if (ord == null) {
+            ord = policyOrdinal.getAndIncrement();
+            Integer old = cgOrdinals.putIfAbsent(cg, ord);
+            if (old != null)
+                ord = old;
+        }
+        return ord.intValue();
+    }
+
+    /**
+     * Get a 32-bit context ordinal suitable for use in the OF data plane for
+     * the given policy item.
+     *
+     * @param tenantId
+     *            the tenant ID of the element
+     * @param id
+     *            the unique ID for the element
+     * @return the 32-bit ordinal value
+     * @throws Exception
+     */
+
+    public static int getContextOrdinal(NodeId destNode) throws Exception {
+        return getContextOrdinalFromString(destNode.getValue());
+    }
+
+    public static int getContextOrdinal(Endpoint ep, NetworkDomainId networkContainment) throws Exception {
+        // TODO: Define private static final Comparator<EndpointGroupId>
+        // COMPARATOR = new Comparator<EndpointGroupId>() { ... }
+        // pass to constructor: new TreeSet<>(COMPARATOR);
+
+        Set<String> epgs = new TreeSet<>();
+
+        // Get EPGs and add to ordered Set
+        if (ep.getEndpointGroup() != null) {
+            epgs.add(ep.getEndpointGroup().getValue());
+        }
+        if (ep.getEndpointGroups() != null) {
+            for (EndpointGroupId epgId : ep.getEndpointGroups()) {
+                epgs.add(epgId.getValue());
+            }
+        }
+
+        StringBuilder key = new StringBuilder(ep.getTenant().getValue());
+
+        for (String epg : epgs) {
+            key.append('|');
+            key.append(epg);
+        }
+
+        key.append("|")
+                .append(networkContainment);
+
+        return getContextOrdinalFromString(key.toString());
+
+    }
+
+    /**
+     * Get a 32-bit context ordinal suitable for use in the OF data plane for
+     * the given policy item.
+     *
+     * @param id
+     *            the unique ID for the element
+     * @return the 32-bit ordinal value
+     */
+    private static int getContextOrdinalFromString(final String id) throws Exception {
+
+        Integer ord = ordinals.get(id);
+        if (ord == null) {
+            ord = policyOrdinal.getAndIncrement();
+            Integer old = ordinals.putIfAbsent(id, ord);
+            if (old != null)
+                ord = old;
+        }
+        return ord.intValue();
+    }
+
+    public static final EndpointFwdCtxOrdinals getEndpointFwdCtxOrdinals(OfContext ctx, PolicyInfo policyInfo,
+            Endpoint ep) throws Exception {
+        return new EndpointFwdCtxOrdinals(ep, policyInfo, ctx);
+    }
+
+    // TODO alagalah Li: Move to either OrdinalFactory or EndpointManager
+    public static class EndpointFwdCtxOrdinals {
+
+        private NetworkDomainId networkContainment;
+        private EpKey ep;
+        private int epgId = 0, bdId = 0, fdId = 0, l3Id = 0, cgId = 0;
+
+        private EndpointFwdCtxOrdinals(Endpoint ep, PolicyInfo policyInfo, OfContext ctx) throws Exception {
+            this.ep = new EpKey(ep.getL2Context(), ep.getMacAddress());
+
+            IndexedTenant tenant = ctx.getPolicyResolver().getTenant(ep.getTenant());
+            // Set network containment either from ep, or from primary EPG
+            if (ep.getNetworkContainment() != null) {
+                this.networkContainment = ep.getNetworkContainment();
+            } else {
+                EndpointGroup epg = tenant.getEndpointGroup(ep.getEndpointGroup());
+                if (epg.getNetworkDomain() != null) {
+                    this.networkContainment = epg.getNetworkDomain();
+                } else {
+                    LOG.info(
+                            "endPoint ordinals for {} not processed in SourceMapper. Must be able to resolve network containment either directly, or from primary EPG",
+                            ep.getKey());
+                    return;
+                }
+            }
+
+            // TODO: alagalah: I have a draft to address structure of mEPG
+            // conditions, but
+            // out of scope until broader bugs with conditions are fixed.
+            List<ConditionName> conds = ctx.getEndpointManager().getCondsForEndpoint(ep);
+            ConditionGroup cg =
+                    policyInfo.getEgCondGroup(new EgKey(ep.getTenant(), ep.getEndpointGroup()), conds);
+            this.cgId = getCondGroupOrdinal(cg);
+
+            // Based on network containment, determine components of
+            // forwarding context
+            L3Context l3c = tenant.resolveL3Context(networkContainment);
+            L2BridgeDomain bd = tenant.resolveL2BridgeDomain(networkContainment);
+            L2FloodDomain fd = tenant.resolveL2FloodDomain(networkContainment);
+
+            // Set ordinal id's for use in flows for each forwarding context
+            // component
+
+            this.epgId = getContextOrdinal(ep, networkContainment);
+            if (bd != null)
+                this.bdId = getContextOrdinal(ep.getTenant(),
+                        bd.getId());
+            if (fd != null)
+                this.fdId = getContextOrdinal(ep.getTenant(),
+                        fd.getId());
+            if (l3c != null)
+                this.l3Id = getContextOrdinal(ep.getTenant(),
+                        l3c.getId());
+
+        }
+
+        public int getEpgId() {
+            return this.epgId;
+        }
+
+        public NetworkDomainId getNetworkContainment() {
+            return this.networkContainment;
+        }
+
+        public EpKey getEp() {
+            return this.ep;
+        }
+
+        public int getBdId() {
+            return this.bdId;
+        }
+
+        public int getFdId() {
+            return this.fdId;
+        }
+
+        public int getL3Id() {
+            return this.l3Id;
+        }
+
+        public int getCgId() {
+            return this.cgId;
+        }
+    }
+}
index 9555a18449c2d748efb6a4251203bdd72ea50c32..8c5c8a7e09a6e6f3747d6f9973cb67d019fad010 100644 (file)
@@ -24,10 +24,10 @@ import java.util.Set;
 
 import javax.annotation.concurrent.Immutable;
 
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassificationResult;
@@ -42,7 +42,7 @@ import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 import org.opendaylight.groupbasedpolicy.resolver.RuleGroup;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 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;
+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;
@@ -65,7 +65,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 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.NxmNxReg7;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -73,9 +72,8 @@ import com.google.common.collect.ComparisonChain;
 import com.google.common.collect.Ordering;
 
 /**
- * Manage the table that enforces policy on the traffic.  Traffic is denied
+ * Manage the table that enforces policy on the traffic. Traffic is denied
  * unless specifically allowed by policy
- * @author readams
  */
 public class PolicyEnforcer extends FlowTable {
     protected static final Logger LOG =
@@ -93,121 +91,122 @@ public class PolicyEnforcer extends FlowTable {
     }
 
     @Override
-    public void sync(ReadWriteTransaction t, InstanceIdentifier<Table> tiid,
-                     Map<String, FlowCtx> flowMap, NodeId nodeId,
-                     PolicyInfo policyInfo, Dirty dirty)
-                             throws Exception {
-        dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
-        allowFromTunnel(t, tiid, flowMap, nodeId);
+    public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) throws Exception {
 
-        HashSet<CgPair> visitedPairs = new HashSet<>();
-
-        for (EgKey sepg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
-            // Allow traffic within the same endpoint group if the policy
-            // specifies
-            IndexedTenant tenant =
-                    ctx.getPolicyResolver().getTenant(sepg.getTenantId());
-            EndpointGroup group =
-                    tenant.getEndpointGroup(sepg.getEgId());
-            IntraGroupPolicy igp = group.getIntraGroupPolicy();
-            int sepgId =
-                    ctx.getPolicyManager().getContextOrdinal(sepg.getTenantId(),
-                                                        sepg.getEgId());
-            if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
-                allowSameEpg(t, tiid, flowMap, nodeId, sepgId);
-            }
-
-            for (Endpoint src : ctx.getEndpointManager().getEPsForNode(nodeId, sepg)) {
-                if (src.getTenant() == null || src.getEndpointGroup() == null)
-                    continue;
+        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null));
 
-                List<ConditionName> conds =
-                        ctx.getEndpointManager().getCondsForEndpoint(src);
-                ConditionGroup scg = policyInfo.getEgCondGroup(sepg, conds);
-                int scgId = ctx.getPolicyManager().getCondGroupOrdinal(scg);
+        flowMap.writeFlow(nodeId, TABLE_ID, allowFromTunnel(nodeId));
 
-                Set<EgKey> peers = policyInfo.getPeers(sepg);
-                for (EgKey depg : peers) {
-                    int depgId =
-                            ctx.getPolicyManager().getContextOrdinal(depg.getTenantId(),
-                                                                depg.getEgId());
-
-                    for (Endpoint dst : ctx.getEndpointManager().getEndpointsForGroup(depg)) {
+        HashSet<CgPair> visitedPairs = new HashSet<>();
 
-                        conds = ctx.getEndpointManager().getCondsForEndpoint(dst);
-                        ConditionGroup dcg =
-                                policyInfo.getEgCondGroup(new EgKey(dst.getTenant(),
-                                                                    dst.getEndpointGroup()),
-                                                          conds);
-                        int dcgId = ctx.getPolicyManager().getCondGroupOrdinal(dcg);
+        for (Endpoint srcEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
+            for (EgKey srcEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(srcEp)) {
+                Set<EgKey> peers = policyInfo.getPeers(srcEpgKey);
+                for (EgKey dstEpgKey : peers) {
+                    for (Endpoint dstEp : ctx.getEndpointManager().getEndpointsForGroup(dstEpgKey)) {
+                        // mEPG ordinals
+                        EndpointFwdCtxOrdinals srcEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, srcEp);
+                        EndpointFwdCtxOrdinals dstEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, dstEp);
+                        int dcgId = dstEpFwdCxtOrds.getCgId();
+                        int depgId = dstEpFwdCxtOrds.getEpgId();
+                        int scgId = srcEpFwdCxtOrds.getCgId();
+                        int sepgId = srcEpFwdCxtOrds.getEpgId();
+
+                        List<ConditionName> conds = ctx.getEndpointManager().getCondsForEndpoint(srcEp);
+                        ConditionGroup scg = policyInfo.getEgCondGroup(srcEpgKey, conds);
+                        conds = ctx.getEndpointManager().getCondsForEndpoint(dstEp);
+                        ConditionGroup dcg = policyInfo.getEgCondGroup(dstEpgKey, conds);
 
                         CgPair p = new CgPair(depgId, sepgId, dcgId, scgId);
-                        if (visitedPairs.contains(p)) continue;
+                        if (visitedPairs.contains(p))
+                            continue;
                         visitedPairs.add(p);
-                        syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
-                                   p, depg, sepg, dcg, scg);
+                        syncPolicy(flowMap, nodeId, policyInfo,
+                                p, dstEpgKey, srcEpgKey, dcg, scg);
 
+                        //Reverse
                         p = new CgPair(sepgId, depgId, scgId, dcgId);
-                        if (visitedPairs.contains(p)) continue;
+                        if (visitedPairs.contains(p))
+                            continue;
                         visitedPairs.add(p);
-                        syncPolicy(t, tiid, flowMap, nodeId, policyInfo,
-                                   p, sepg, depg, scg, dcg);
+                        syncPolicy(flowMap, nodeId, policyInfo,
+                                p, srcEpgKey, dstEpgKey, scg, dcg);
+                    }
+                }
+            }
+        }
+
+        // Allow same EPG
+//        Set<Endpoint> visitedEps = new HashSet<>();
+        for (Endpoint srcEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
+//            visitedEps.add(srcEp);
+            for (EgKey srcEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(srcEp)) {
+
+                IndexedTenant tenant = ctx.getPolicyResolver().getTenant(srcEpgKey.getTenantId());
+                EndpointGroup group = tenant.getEndpointGroup(srcEpgKey.getEgId());
+                IntraGroupPolicy igp = group.getIntraGroupPolicy();
+
+                if (igp == null || igp.equals(IntraGroupPolicy.Allow)) {
+                    for (Endpoint dstEp : ctx.getEndpointManager().getEndpointsForGroup(srcEpgKey)) {
+                        // mEPG ordinals
+//                        if(visitedEps.contains(dstEp)) {
+//                            continue;
+//                        }
+//                        visitedEps.add(dstEp);
+                        EndpointFwdCtxOrdinals srcEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, srcEp);
+                        EndpointFwdCtxOrdinals dstEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, dstEp);
+                        int depgId = dstEpFwdCxtOrds.getEpgId();
+                        int sepgId = srcEpFwdCxtOrds.getEpgId();
+                        flowMap.writeFlow(nodeId, TABLE_ID, allowSameEpg(sepgId, depgId));
+                        flowMap.writeFlow(nodeId, TABLE_ID, allowSameEpg(depgId, sepgId));
                     }
                 }
             }
         }
+
     }
 
-    private void allowSameEpg(ReadWriteTransaction t,
-                              InstanceIdentifier<Table> tiid,
-                              Map<String, FlowCtx> flowMap, NodeId nodeId,
-                              int sepgId) {
+    private Flow allowSameEpg(int sepgId, int depgId) {
         FlowId flowId = new FlowId(new StringBuilder()
-            .append("intraallow|")
-            .append(sepgId).toString());
-        if (visit(flowMap, flowId.getValue())) {
+                .append("intraallow|")
+                .append(sepgId).toString());
             MatchBuilder mb = new MatchBuilder();
             addNxRegMatch(mb,
-                          RegMatch.of(NxmNxReg0.class,Long.valueOf(sepgId)),
-                          RegMatch.of(NxmNxReg2.class,Long.valueOf(sepgId)));
+                    RegMatch.of(NxmNxReg0.class, Long.valueOf(sepgId)),
+                    RegMatch.of(NxmNxReg2.class, Long.valueOf(depgId)));
             FlowBuilder flow = base()
-                .setId(flowId)
-                .setMatch(mb.build())
-                .setPriority(65000)
-                .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
-            writeFlow(t, tiid, flow.build());
-        }
+                    .setId(flowId)
+                    .setMatch(mb.build())
+                    .setPriority(65000)
+                    .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
+            return flow.build();
     }
 
-    private void allowFromTunnel(ReadWriteTransaction t,
-                                 InstanceIdentifier<Table> tiid,
-                                 Map<String, FlowCtx> flowMap, NodeId nodeId) {
+    private Flow allowFromTunnel(NodeId nodeId) {
         NodeConnectorId tunPort =
                 ctx.getSwitchManager().getTunnelPort(nodeId);
-        if (tunPort == null) return;
+        if (tunPort == null)
+            return null;
 
         FlowId flowId = new FlowId("tunnelallow");
-        if (visit(flowMap, flowId.getValue())) {
-            MatchBuilder mb = new MatchBuilder()
+        MatchBuilder mb = new MatchBuilder()
                 .setInPort(tunPort);
-            addNxRegMatch(mb,
-                          RegMatch.of(NxmNxReg1.class,Long.valueOf(0xffffff)));
-            FlowBuilder flow = base()
+        addNxRegMatch(mb,
+                RegMatch.of(NxmNxReg1.class, Long.valueOf(0xffffff)));
+        FlowBuilder flow = base()
                 .setId(flowId)
                 .setMatch(mb.build())
                 .setPriority(65000)
                 .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
-            writeFlow(t, tiid, flow.build());
-        }
+        return flow.build();
+
     }
 
-    private void syncPolicy(ReadWriteTransaction t,
-                            InstanceIdentifier<Table> tiid,
-                            Map<String, FlowCtx> flowMap, NodeId nodeId,
-                            PolicyInfo policyInfo,
-                            CgPair p, EgKey sepg, EgKey depg,
-                            ConditionGroup scg, ConditionGroup dcg)
-                             throws Exception {
+    private void syncPolicy(FlowMap flowMap, NodeId nodeId,
+            PolicyInfo policyInfo,
+            CgPair p, EgKey sepg, EgKey depg,
+            ConditionGroup scg, ConditionGroup dcg)
+            throws Exception {
         // XXX - TODO raise an exception for rules between the same
         // endpoint group that are asymmetric
         Policy policy = policyInfo.getPolicy(sepg, depg);
@@ -218,10 +217,10 @@ public class PolicyEnforcer extends FlowTable {
             TenantId tenantId = rg.getContractTenant().getId();
             IndexedTenant tenant = ctx.getPolicyResolver().getTenant(tenantId);
             for (Rule r : rg.getRules()) {
-                syncDirection(t, tiid, flowMap, nodeId, tenant,
-                                    p, r, Direction.In, priority);
-                syncDirection(t, tiid, flowMap, nodeId, tenant,
-                                    p, r, Direction.Out, priority);
+                syncDirection(flowMap, nodeId, tenant,
+                        p, r, Direction.In, priority);
+                syncDirection(flowMap, nodeId, tenant,
+                        p, r, Direction.Out, priority);
 
                 priority -= 1;
             }
@@ -229,13 +228,10 @@ public class PolicyEnforcer extends FlowTable {
     }
 
     /**
-     * Private internal class for ordering Actions in Rules. The
-     * order is determined first by the value of the order parameter,
-     * with the lower order actions being applied first; for Actions
-     * with either the same order or no order, ordering is lexicographical
-     * by name.
-     *
-     * @author tbachman
+     * Private internal class for ordering Actions in Rules. The order is
+     * determined first by the value of the order parameter, with the lower
+     * order actions being applied first; for Actions with either the same order
+     * or no order, ordering is lexicographical by name.
      *
      */
     private static class ActionRefComparator implements Comparator<ActionRef> {
@@ -245,54 +241,54 @@ public class PolicyEnforcer extends FlowTable {
         public int compare(ActionRef arg0, ActionRef arg1) {
             return ComparisonChain.start()
                     .compare(arg0.getOrder(), arg1.getOrder(),
-                             Ordering.natural().nullsLast())
+                            Ordering.natural().nullsLast())
                     .compare(arg0.getName().getValue(), arg1.getName().getValue(),
-                             Ordering.natural().nullsLast())
+                            Ordering.natural().nullsLast())
                     .result();
         }
 
     }
 
-    private void syncDirection(ReadWriteTransaction t,
-                               InstanceIdentifier<Table> tiid,
-                               Map<String, FlowCtx> flowMap, NodeId nodeId,
-                               IndexedTenant contractTenant,
-                               CgPair p, Rule r, Direction d, int priority) {
+    private void syncDirection(FlowMap flowMap, NodeId nodeId, IndexedTenant contractTenant,
+            CgPair cgPair, Rule rule, Direction direction, int priority) {
         /*
-         * Create the ordered action list. The implicit action is
-         * "allow", and is therefore always in the list
+         * Create the ordered action list. The implicit action is "allow", and
+         * is therefore always in the list
          *
-         * TODO: revisit implicit vs. default for "allow"
-         * TODO: look into incorporating operational policy for actions
+         * TODO: revisit implicit vs. default for "allow" TODO: look into
+         * incorporating operational policy for actions
          */
+
+        //TODO: can pass Comparator ActionRefComparator to List constructor, rather than referencing in sort
         List<ActionBuilder> abl = new ArrayList<ActionBuilder>();
-        if (r.getActionRef() != null) {
+        if (rule.getActionRef() != null) {
             /*
              * Pre-sort by references using order, then name
              */
-            List<ActionRef> arl = new ArrayList<ActionRef>(r.getActionRef());
+            List<ActionRef> arl = new ArrayList<ActionRef>(rule.getActionRef());
             Collections.sort(arl, ActionRefComparator.INSTANCE);
 
-            for (ActionRef ar: arl) {
+            for (ActionRef ar : arl) {
                 ActionInstance ai = contractTenant.getAction(ar.getName());
                 if (ai == null) {
                     // XXX TODO fail the match and raise an exception
                     LOG.warn("Action instance {} not found",
-                             ar.getName().getValue());
+                            ar.getName().getValue());
                     return;
                 }
                 Action act = SubjectFeatures.getAction(ai.getActionDefinitionId());
                 if (act == null) {
                     // XXX TODO fail the match and raise an exception
                     LOG.warn("Action definition {} not found",
-                             ai.getActionDefinitionId().getValue());
+                            ai.getActionDefinitionId().getValue());
                     return;
                 }
 
-                Map<String,Object> params = new HashMap<>();
+                Map<String, Object> params = new HashMap<>();
                 if (ai.getParameterValue() != null) {
                     for (ParameterValue v : ai.getParameterValue()) {
-                        if (v.getName() == null) continue;
+                        if (v.getName() == null)
+                            continue;
                         if (v.getIntValue() != null) {
                             params.put(v.getName().getValue(), v.getIntValue());
                         } else if (v.getStringValue() != null) {
@@ -301,22 +297,22 @@ public class PolicyEnforcer extends FlowTable {
                     }
                 }
                 /*
-                 * Convert the GBP Action to one or more OpenFlow
-                 * Actions
+                 * Convert the GBP Action to one or more OpenFlow Actions
                  */
                 abl = act.updateAction(abl, params, ar.getOrder());
             }
         }
         else {
             Action act = SubjectFeatures.getAction(AllowAction.DEFINITION.getId());
-            abl = act.updateAction(abl, new HashMap<String,Object>(),  0);
+            abl = act.updateAction(abl, new HashMap<String, Object>(), 0);
         }
 
-        for (ClassifierRef cr : r.getClassifierRef()) {
+        for (ClassifierRef cr : rule.getClassifierRef()) {
             if (cr.getDirection() != null &&
-                !cr.getDirection().equals(Direction.Bidirectional) &&
-                !cr.getDirection().equals(d))
+                    !cr.getDirection().equals(Direction.Bidirectional) &&
+                    !cr.getDirection().equals(direction)) {
                 continue;
+            }
 
             StringBuilder idb = new StringBuilder();
             // XXX - TODO - implement connection tracking (requires openflow
@@ -325,43 +321,43 @@ public class PolicyEnforcer extends FlowTable {
 
             MatchBuilder baseMatch = new MatchBuilder();
 
-            if (d.equals(Direction.In)) {
-                idb.append(p.sepg)
-                    .append("|")
-                    .append(p.scgId)
-                    .append("|")
-                    .append(p.depg)
-                    .append("|")
-                    .append(p.dcgId)
-                    .append("|")
-                    .append(priority);
+            if (direction.equals(Direction.In)) {
+                idb.append(cgPair.sepg)
+                        .append("|")
+                        .append(cgPair.scgId)
+                        .append("|")
+                        .append(cgPair.depg)
+                        .append("|")
+                        .append(cgPair.dcgId)
+                        .append("|")
+                        .append(priority);
                 addNxRegMatch(baseMatch,
-                              RegMatch.of(NxmNxReg0.class,Long.valueOf(p.sepg)),
-                              RegMatch.of(NxmNxReg1.class,Long.valueOf(p.scgId)),
-                              RegMatch.of(NxmNxReg2.class,Long.valueOf(p.depg)),
-                              RegMatch.of(NxmNxReg3.class,Long.valueOf(p.dcgId)));
+                        RegMatch.of(NxmNxReg0.class, Long.valueOf(cgPair.sepg)),
+                        RegMatch.of(NxmNxReg1.class, Long.valueOf(cgPair.scgId)),
+                        RegMatch.of(NxmNxReg2.class, Long.valueOf(cgPair.depg)),
+                        RegMatch.of(NxmNxReg3.class, Long.valueOf(cgPair.dcgId)));
             } else {
-                idb.append(p.depg)
-                    .append("|")
-                    .append(p.dcgId)
-                    .append("|")
-                    .append(p.sepg)
-                    .append("|")
-                    .append(p.scgId)
-                    .append("|")
-                    .append(priority);
+                idb.append(cgPair.depg)
+                        .append("|")
+                        .append(cgPair.dcgId)
+                        .append("|")
+                        .append(cgPair.sepg)
+                        .append("|")
+                        .append(cgPair.scgId)
+                        .append("|")
+                        .append(priority);
                 addNxRegMatch(baseMatch,
-                              RegMatch.of(NxmNxReg0.class,Long.valueOf(p.depg)),
-                              RegMatch.of(NxmNxReg1.class,Long.valueOf(p.dcgId)),
-                              RegMatch.of(NxmNxReg2.class,Long.valueOf(p.sepg)),
-                              RegMatch.of(NxmNxReg3.class,Long.valueOf(p.scgId)));
+                        RegMatch.of(NxmNxReg0.class, Long.valueOf(cgPair.depg)),
+                        RegMatch.of(NxmNxReg1.class, Long.valueOf(cgPair.dcgId)),
+                        RegMatch.of(NxmNxReg2.class, Long.valueOf(cgPair.sepg)),
+                        RegMatch.of(NxmNxReg3.class, Long.valueOf(cgPair.scgId)));
             }
 
             ClassifierInstance ci = contractTenant.getClassifier(cr.getName());
             if (ci == null) {
                 // XXX TODO fail the match and raise an exception
                 LOG.warn("Classifier instance {} not found",
-                         cr.getName().getValue());
+                        cr.getName().getValue());
                 return;
             }
             Classifier cfier = SubjectFeatures
@@ -369,12 +365,13 @@ public class PolicyEnforcer extends FlowTable {
             if (cfier == null) {
                 // XXX TODO fail the match and raise an exception
                 LOG.warn("Classifier definition {} not found",
-                         ci.getClassifierDefinitionId().getValue());
+                        ci.getClassifierDefinitionId().getValue());
                 return;
             }
 
             Map<String,ParameterValue> params = new HashMap<>();
             for (ParameterValue v : ci.getParameterValue()) {
+
                 if (v.getIntValue() != null) {
                     params.put(v.getName().getValue(), v);
                 } else if (v.getStringValue() != null) {
@@ -396,11 +393,13 @@ public class PolicyEnforcer extends FlowTable {
                 for (MatchBuilder match : result.getMatchBuilders()) {
                     Match m = match.build();
                     FlowId flowId = new FlowId(baseId + "|" + m.toString());
-                    if (visit(flowMap, flowId.getValue())) {
-                        flow.setMatch(m).setId(flowId).setPriority(Integer.valueOf(priority))
-                                .setInstructions(instructions(applyActionIns(abl)));
-                        writeFlow(t, tiid, flow.build());
-                    }
+                flow.setMatch(m)
+                        .setId(flowId)
+                        .setPriority(Integer.valueOf(priority))
+                        .setInstructions(instructions(applyActionIns(abl)));
+                flowMap.writeFlow(nodeId, TABLE_ID, flow.build());
+
+
                 }
             }
         }
index 0bc6d8c69045a6237273c8c68f93d350cdb4068a..044834f837e8f06aa235eea2160dbec35b1c9c61 100644 (file)
@@ -8,18 +8,15 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
-import java.util.Map;
 import java.util.Set;
 
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 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.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 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.MatchBuilder;
@@ -33,13 +30,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 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.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Manage the table that enforces port security
- * @author readams
+ *
  */
 public class PortSecurity extends FlowTable {
     protected static final Logger LOG =
@@ -57,189 +53,172 @@ public class PortSecurity extends FlowTable {
     }
 
     @Override
-    public void sync(ReadWriteTransaction t,
-                     InstanceIdentifier<Table> tiid,
-                     Map<String, FlowCtx> flowMap,
-                     NodeId nodeId, PolicyInfo policyInfo, Dirty dirty) {
+    public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) {
+
         // Allow traffic from tunnel and external ports
         NodeConnectorId tunnelIf = ctx.getSwitchManager().getTunnelPort(nodeId);
         if (tunnelIf != null)
-            allowFromPort(t, tiid, flowMap, tunnelIf);
+            flowMap.writeFlow(nodeId, TABLE_ID, allowFromPort(tunnelIf));
         Set<NodeConnectorId> external =
                 ctx.getSwitchManager().getExternalPorts(nodeId);
-        for (NodeConnectorId extIf: external) {
-            allowFromPort(t, tiid, flowMap, extIf);
+        for (NodeConnectorId extIf : external) {
+            flowMap.writeFlow(nodeId, TABLE_ID, allowFromPort(extIf));
         }
 
         // Default drop all
-        dropFlow(t, tiid, flowMap, 1, null);
+        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null));
 
         // Drop IP traffic that doesn't match a source IP rule
-        dropFlow(t, tiid, flowMap, 110, FlowUtils.ARP);
-        dropFlow(t, tiid, flowMap, 111, FlowUtils.IPv4);
-        dropFlow(t, tiid, flowMap, 112, FlowUtils.IPv6);
+        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(110), FlowUtils.ARP));
+        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(111), FlowUtils.IPv4));
+        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(112), FlowUtils.IPv6));
 
         for (EgKey sepg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
-            for (Endpoint e : ctx.getEndpointManager().getEPsForNode(nodeId, sepg)) {
-                OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
+            for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId, sepg)) {
+                OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
+
                 if (ofc != null && ofc.getNodeConnectorId() != null &&
                         (ofc.getLocationType() == null ||
                         LocationType.Internal.equals(ofc.getLocationType()))) {
                     // Allow layer 3 traffic (ARP and IP) with the correct
                     // source IP, MAC, and source port
-                    l3flow(t, tiid, flowMap, e, ofc, 120, false);
-                    l3flow(t, tiid, flowMap, e, ofc, 121, true);
-                    l3DhcpDoraFlow(t, tiid, flowMap, e, ofc, 115);
+                    l3flow(flowMap, nodeId, ep, ofc, 120, false);
+                    l3flow(flowMap, nodeId, ep, ofc, 121, true);
+                    flowMap.writeFlow(nodeId, TABLE_ID, l3DhcpDoraFlow(ep, ofc, 115));
 
                     // Allow layer 2 traffic with the correct source MAC and
                     // source port (note lower priority than drop IP rules)
-                    l2flow(t, tiid, flowMap, e, ofc, 100);
+                    flowMap.writeFlow(nodeId, TABLE_ID, l2flow(ep, ofc, 100));
                 }
             }
         }
     }
 
-    private void allowFromPort(ReadWriteTransaction t,
-                               InstanceIdentifier<Table> tiid,
-                               Map<String, FlowCtx> flowMap,
-                               NodeConnectorId port) {
+    private Flow allowFromPort(
+            NodeConnectorId port) {
         FlowId flowid = new FlowId(new StringBuilder()
-            .append("allow|")
-            .append(port.getValue())
-            .toString());
-        if (visit(flowMap, flowid.getValue())) {
-            FlowBuilder flowb = base()
+                .append("allow|")
+                .append(port.getValue())
+                .toString());
+        FlowBuilder flowb = base()
                 .setId(flowid)
                 .setPriority(Integer.valueOf(200))
                 .setMatch(new MatchBuilder()
-                    .setInPort(port)
-                    .build())
-                .setInstructions(FlowUtils.gotoTableInstructions((short)(getTableId()+1)));
-            writeFlow(t, tiid, flowb.build());
-        }
+                        .setInPort(port)
+                        .build())
+                .setInstructions(FlowUtils.gotoTableInstructions((short) (getTableId() + 1)));
+        return flowb.build();
+
     }
 
-    private void l2flow(ReadWriteTransaction t,
-                        InstanceIdentifier<Table> tiid,
-                        Map<String, FlowCtx> flowMap,
-                        Endpoint e, OfOverlayContext ofc,
-                        Integer priority) {
+    private Flow l2flow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
         FlowId flowid = new FlowId(new StringBuilder()
-            .append(ofc.getNodeConnectorId().getValue())
-            .append("|")
-            .append(e.getMacAddress().getValue())
-            .toString());
-        if (visit(flowMap, flowid.getValue())) {
-            FlowBuilder flowb = base()
+                .append(ofc.getNodeConnectorId().getValue())
+                .append("|")
+                .append(ep.getMacAddress().getValue())
+                .toString());
+        FlowBuilder flowb = base()
                 .setPriority(priority)
                 .setId(flowid)
                 .setMatch(new MatchBuilder()
-                    .setEthernetMatch(FlowUtils.ethernetMatch(e.getMacAddress(),
-                                                              null, null))
-                    .setInPort(ofc.getNodeConnectorId())
-                    .build())
-                .setInstructions(FlowUtils.gotoTableInstructions((short)(TABLE_ID + 1)));
+                        .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
+                                null, null))
+                        .setInPort(ofc.getNodeConnectorId())
+                        .build())
+                .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)));
 
-            writeFlow(t, tiid, flowb.build());
-        }
+        return flowb.build();
     }
 
-    private void l3DhcpDoraFlow(ReadWriteTransaction t,
-                                InstanceIdentifier<Table> tiid,
-                                Map<String, FlowCtx> flowMap,
-                                Endpoint e, OfOverlayContext ofc,
-                                Integer priority) {
+    private Flow l3DhcpDoraFlow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
 
-        Long etherType= FlowUtils.IPv4;
+        //TODO: Handle IPv6 DORA
+        Long etherType = FlowUtils.IPv4;
         // DHCP DORA destination is broadcast
-        String ikey="255.255.255.255/32";
-        Layer3Match m=new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
+        String ikey = "255.255.255.255/32";
+        Layer3Match m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
 
         FlowId flowid = new FlowId(new StringBuilder()
-        .append(ofc.getNodeConnectorId().getValue())
-        .append("|")
-        .append(e.getMacAddress().getValue())
-        .append("|dhcp|")
-        .append(etherType)
-        .toString());
-        if (visit(flowMap, flowid.getValue())) {
-            Flow flow = base()
-                    .setPriority(priority)
-                    .setId(flowid)
-                    .setMatch(new MatchBuilder()
-                    .setEthernetMatch(FlowUtils.ethernetMatch(e.getMacAddress(),
-                            null,
-                            etherType))
-                            .setLayer3Match(m)
-                            .setInPort(ofc.getNodeConnectorId())
-                            .build())
-                            .setInstructions(FlowUtils.gotoTableInstructions((short)(TABLE_ID + 1)))
-                            .build();
+                .append(ofc.getNodeConnectorId().getValue())
+                .append("|")
+                .append(ep.getMacAddress().getValue())
+                .append("|dhcp|")
+                .append(etherType)
+                .toString());
+        Flow flow = base()
+                .setPriority(priority)
+                .setId(flowid)
+                .setMatch(new MatchBuilder()
+                        .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
+                                null,
+                                etherType))
+                        .setLayer3Match(m)
+                        .setInPort(ofc.getNodeConnectorId())
+                        .build())
+                .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)))
+                .build();
 
-            writeFlow(t, tiid, flow);
-        }
+        return flow;
     }
 
-    private void l3flow(ReadWriteTransaction t,
-                        InstanceIdentifier<Table> tiid,
-                        Map<String, FlowCtx> flowMap,
-                        Endpoint e, OfOverlayContext ofc,
-                        Integer priority,
-                        boolean arp) {
-        if (e.getL3Address() == null) return;
-        for (L3Address l3 : e.getL3Address()) {
-            if (l3.getIpAddress() == null) continue;
+    private void l3flow(FlowMap flowMap, NodeId nodeId,
+                        Endpoint ep, OfOverlayContext ofc,
+                        Integer priority, boolean arp) {
+        if (ep.getL3Address() == null)
+            return;
+        for (L3Address l3 : ep.getL3Address()) {
+            if (l3.getIpAddress() == null)
+                continue;
             Layer3Match m = null;
             Long etherType = null;
             String ikey = null;
             if (l3.getIpAddress().getIpv4Address() != null) {
-                ikey = l3.getIpAddress().getIpv4Address().getValue()+"/32";
+                ikey = l3.getIpAddress().getIpv4Address().getValue() + "/32";
                 if (arp) {
                     m = new ArpMatchBuilder()
-                        .setArpSourceTransportAddress(new Ipv4Prefix(ikey))
-                        .build();
+                            .setArpSourceTransportAddress(new Ipv4Prefix(ikey))
+                            .build();
                     etherType = FlowUtils.ARP;
                 } else {
                     m = new Ipv4MatchBuilder()
-                        .setIpv4Source(new Ipv4Prefix(ikey))
-                        .build();
+                            .setIpv4Source(new Ipv4Prefix(ikey))
+                            .build();
                     etherType = FlowUtils.IPv4;
                 }
             } else if (l3.getIpAddress().getIpv6Address() != null) {
-                if (arp) continue;
-                ikey = l3.getIpAddress().getIpv6Address().getValue()+"/128";
+                if (arp)
+                    continue;
+                ikey = l3.getIpAddress().getIpv6Address().getValue() + "/128";
                 m = new Ipv6MatchBuilder()
-                    .setIpv6Source(new Ipv6Prefix(ikey))
-                    .build();
+                        .setIpv6Source(new Ipv6Prefix(ikey))
+                        .build();
                 etherType = FlowUtils.IPv6;
             } else {
                 continue;
             }
             FlowId flowid = new FlowId(new StringBuilder()
-                .append(ofc.getNodeConnectorId().getValue())
-                .append("|")
-                .append(e.getMacAddress().getValue())
-                .append("|")
-                .append(ikey)
-                .append("|")
-                .append(etherType)
-                .toString());
-            if (visit(flowMap, flowid.getValue())) {
-                Flow flow = base()
+                    .append(ofc.getNodeConnectorId().getValue())
+                    .append("|")
+                    .append(ep.getMacAddress().getValue())
+                    .append("|")
+                    .append(ikey)
+                    .append("|")
+                    .append(etherType)
+                    .toString());
+            Flow flow = base()
                     .setPriority(priority)
                     .setId(flowid)
                     .setMatch(new MatchBuilder()
-                        .setEthernetMatch(FlowUtils.ethernetMatch(e.getMacAddress(),
-                                                                  null,
-                                                                  etherType))
-                        .setLayer3Match(m)
-                        .setInPort(ofc.getNodeConnectorId())
-                        .build())
-                    .setInstructions(FlowUtils.gotoTableInstructions((short)(TABLE_ID + 1)))
+                            .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
+                                    null,
+                                    etherType))
+                            .setLayer3Match(m)
+                            .setInPort(ofc.getNodeConnectorId())
+                            .build())
+                    .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)))
                     .build();
 
-                writeFlow(t, tiid, flow);
-            }
+            flowMap.writeFlow(nodeId, TABLE_ID,flow);
         }
     }
 }
index cbb554ca0a18e238ebc19d26870d3b8dbcb0c220..634d27a37499c496fd40d2f3008bcc998321e916 100644 (file)
@@ -8,30 +8,36 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxTunIdMatch;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ethernetMatch;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;
+
 import java.math.BigInteger;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
+import java.util.Set;
 
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
 import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
 import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 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;
+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.MatchBuilder;
 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.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
 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.EndpointGroup;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomain;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
 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.openflowjava.nx.match.rev140421.NxmNxReg0;
@@ -39,21 +45,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 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.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
+import com.google.common.collect.Sets;
 
 /**
- * Manage the table that assigns source endpoint group, bridge domain, and 
+ * Manage the table that assigns source endpoint group, bridge domain, and
  * router domain to registers to be used by other tables.
- * @author readams
  */
 public class SourceMapper extends FlowTable {
     protected static final Logger LOG =
             LoggerFactory.getLogger(SourceMapper.class);
 
+    //TODO Li alagalah Improve UT coverage for this class.
     public static final short TABLE_ID = 1;
 
     public SourceMapper(OfContext ctx) {
@@ -66,40 +71,100 @@ public class SourceMapper extends FlowTable {
     }
 
     @Override
-    public void sync(ReadWriteTransaction t,
-                     InstanceIdentifier<Table> tiid,
-                     Map<String, FlowCtx> flowMap, 
-                     NodeId nodeId, PolicyInfo policyInfo, 
-                     Dirty dirty) throws Exception {
-        dropFlow(t, tiid, flowMap, Integer.valueOf(1), null);
-
-        for (EgKey sepg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
-            IndexedTenant tenant = 
-                    ctx.getPolicyResolver().getTenant(sepg.getTenantId());
-            if (tenant == null) continue;
-
-            EndpointGroup eg = tenant.getEndpointGroup(sepg.getEgId());
-            L3Context l3c = tenant.resolveL3Context(eg.getNetworkDomain());
-            L2BridgeDomain bd = tenant.resolveL2BridgeDomain(eg.getNetworkDomain());
-            L2FloodDomain fd = tenant.resolveL2FloodDomain(eg.getNetworkDomain());
-            int egId = 0, bdId = 0, fdId = 0, l3Id = 0;
-            
-            egId = ctx.getPolicyManager().getContextOrdinal(sepg.getTenantId(),
-                                                       sepg.getEgId());
-            if (bd != null)
-                bdId = ctx.getPolicyManager().getContextOrdinal(sepg.getTenantId(),
-                                                           bd.getId());
-            if (fd != null)
-                fdId = ctx.getPolicyManager().getContextOrdinal(sepg.getTenantId(),
-                                                           fd.getId());
-            if (l3c != null)
-                l3Id = ctx.getPolicyManager().getContextOrdinal(sepg.getTenantId(),
-                                                           l3c.getId());
-
-            NodeConnectorId tunPort =
-                    ctx.getSwitchManager().getTunnelPort(nodeId);
-            if (tunPort != null) {
-                FlowId flowid = new FlowId(new StringBuilder()
+    public void sync(NodeId nodeId,
+            PolicyInfo policyInfo, FlowMap flowMap) throws Exception {
+
+        flowMap.writeFlow(nodeId,TABLE_ID,dropFlow(Integer.valueOf(1), null));
+
+         /*
+         * 1. Retrieve all endpoints connected to node 2. For each endpoint: -
+         * calculate and update index for multi-EPG ordinal for flow sEPG - set
+         * bdId, fdId, L3c based from following order: : 1. EP specific
+         * NetworkContextId : 2. Primary EPG : 3. "First" EPG in endpoint-groups
+         * - capture information for adding appropriate tunnel (sEPG ordinal,
+         * ep.bd, ep.fd, ep.l3c) - write flow 3. For each EPG captured above: -
+         * write tunnel flow
+         */
+
+        for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
+
+            OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
+            if (ofc != null && ofc.getNodeConnectorId() != null &&
+                    (ofc.getLocationType() == null ||
+                    LocationType.Internal.equals(ofc.getLocationType())) &&
+                    ep.getTenant() != null && (ep.getEndpointGroup() != null || ep.getEndpointGroups() != null)) {
+
+                IndexedTenant tenant =
+                    ctx.getPolicyResolver().getTenant(ep.getTenant());
+                if (tenant == null)
+                    continue;
+
+                // TODO: MOVE TO NEW CLASS BEGIN____>>>>>>>>>
+                /*
+                 * sepg currently set for conditions.
+                 * TODO: conditions are broken beyond repair. This will do for now.
+                 * Bug raised already to be fixed in Li
+                 *
+                 */
+                EgKey sepg = new EgKey(ep.getTenant(), ep.getEndpointGroup());
+
+                createRemoteTunnels(flowMap,nodeId,ep,policyInfo);
+
+                /**
+                 * Sync the local EP information.
+                 */
+                syncEP(flowMap, policyInfo, nodeId, ep, ofc, sepg);
+            }
+        }
+    }
+
+    private void createRemoteTunnels(FlowMap flowMap,NodeId nodeId, Endpoint ep,
+            PolicyInfo policyInfo) throws Exception {
+        Set<EgKey> epgs = new HashSet<>();
+
+        EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, ep);
+
+        // Get EPGs and add to Set to remove duplicates
+        //TODO alagalah Li: test EndpointManager.getEgKeys
+        if (ep.getEndpointGroup() != null) {
+            epgs.add(new EgKey(ep.getTenant(), ep.getEndpointGroup()));
+        }
+        if (ep.getEndpointGroups() != null) {
+            for (EndpointGroupId epgId : ep.getEndpointGroups()) {
+                epgs.add(new EgKey(ep.getTenant(), epgId));
+            }
+        }
+
+        // Create tunnels on remote Nodes that may talk to us.
+        for (EgKey epg : epgs) {
+            Set<EgKey> peers = Sets.union(Collections.singleton(epg),
+                    policyInfo.getPeers(epg));
+            for (EgKey peer : peers) {
+                for (NodeId remoteNodeId : ctx.getEndpointManager().getNodesForGroup(peer)) {
+
+                    // Only put tunnels on destination nodes
+                    if(remoteNodeId == nodeId) continue;
+                    NodeConnectorId tunPort =
+                            ctx.getSwitchManager().getTunnelPort(remoteNodeId);
+                    if(tunPort == null) {
+                        continue;
+                    }
+                    flowMap.writeFlow(remoteNodeId, TABLE_ID, createTunnelFlow(tunPort,epFwdCtxOrds));
+
+                }
+            }
+        }
+    }
+
+    private Flow createTunnelFlow(NodeConnectorId tunPort, EndpointFwdCtxOrdinals epFwdCtxOrds) {
+        // ... this is a remote node.
+
+        int egId=epFwdCtxOrds.getEpgId();
+        int bdId=epFwdCtxOrds.getBdId();
+        int fdId=epFwdCtxOrds.getFdId();
+        int l3Id=epFwdCtxOrds.getL3Id();
+
+            FlowId flowid = new FlowId(new StringBuilder()
                     .append(tunPort.getValue())
                     .append("|tunnel|")
                     .append(egId)
@@ -110,107 +175,110 @@ public class SourceMapper extends FlowTable {
                     .append("|")
                     .append(l3Id)
                     .toString());
-                if (visit(flowMap, flowid.getValue())) {
-                    MatchBuilder mb = new MatchBuilder()
-                        .setInPort(tunPort);
-                    addNxTunIdMatch(mb, egId);
-                    Action segReg = nxLoadRegAction(NxmNxReg0.class, 
-                                                    BigInteger.valueOf(egId));
-                    // set condition group register to all ones to bypass
-                    // policy enforcement
-                    Action scgReg = nxLoadRegAction(NxmNxReg1.class,
-                                                    BigInteger.valueOf(0xffffff));
-                    Action bdReg = nxLoadRegAction(NxmNxReg4.class, 
-                                                   BigInteger.valueOf(bdId));
-                    Action fdReg = nxLoadRegAction(NxmNxReg5.class, 
-                                                   BigInteger.valueOf(fdId));
-                    Action vrfReg = nxLoadRegAction(NxmNxReg6.class, 
-                                                    BigInteger.valueOf(l3Id));
-                    FlowBuilder flowb = base()
-                        .setId(flowid)
-                        .setPriority(Integer.valueOf(150))
-                        .setMatch(mb.build())
-                        .setInstructions(instructions(applyActionIns(segReg,
-                                                                     scgReg,
-                                                                     bdReg,
-                                                                     fdReg,
-                                                                     vrfReg),
-                                                      gotoTableIns((short)(TABLE_ID + 1))));
-                    writeFlow(t, tiid, flowb.build());
-                }
-            }
-            
-            for (Endpoint e : ctx.getEndpointManager().getEPsForNode(nodeId, sepg)) {
-                OfOverlayContext ofc = e.getAugmentation(OfOverlayContext.class);
-                if (ofc != null && ofc.getNodeConnectorId() != null &&
-                        (ofc.getLocationType() == null ||
-                        LocationType.Internal.equals(ofc.getLocationType())) &&
-                        e.getTenant() != null && e.getEndpointGroup() != null) {
-                    syncEP(t, tiid, flowMap, policyInfo, nodeId, e, ofc,
-                           egId, bdId, fdId, l3Id);
-                } 
-            }
-        }
+
+            MatchBuilder mb = new MatchBuilder()
+                    .setInPort(tunPort);
+            addNxTunIdMatch(mb, egId);
+            Action segReg = nxLoadRegAction(NxmNxReg0.class,
+                    BigInteger.valueOf(egId));
+            // set condition group register to all ones to
+            // bypass
+            // policy enforcement
+            /*
+             * TODO: This breaks distributed policy enforcement
+             * especially wrt multi-action. BAD. Must be addressed
+             * (this is why we can't have nice things)
+             */
+            Action scgReg = nxLoadRegAction(NxmNxReg1.class,
+                    BigInteger.valueOf(0xffffff));
+            Action bdReg = nxLoadRegAction(NxmNxReg4.class,
+                    BigInteger.valueOf(bdId));
+            Action fdReg = nxLoadRegAction(NxmNxReg5.class,
+                    BigInteger.valueOf(fdId));
+            Action vrfReg = nxLoadRegAction(NxmNxReg6.class,
+                    BigInteger.valueOf(l3Id));
+            FlowBuilder flowb = base()
+                    .setId(flowid)
+                    .setPriority(Integer.valueOf(150))
+                    .setMatch(mb.build())
+                    .setInstructions(instructions(applyActionIns(segReg,
+                            scgReg,
+                            bdReg,
+                            fdReg,
+                            vrfReg),
+                            gotoTableIns((short) (TABLE_ID + 1))));
+            return flowb.build();
     }
-    
-    private void syncEP(ReadWriteTransaction t,
-                        InstanceIdentifier<Table> tiid,
-                        Map<String, FlowCtx> flowMap, 
-                        PolicyInfo policyInfo,
-                        NodeId nodeId, Endpoint e, OfOverlayContext ofc,
-                        int egId, int bdId, int fdId, int l3Id) 
-                                 throws Exception {
-        // Set sEPG, flood domain, bridge domain, and layer 3 context 
+
+    private void syncEP(FlowMap flowMap,
+            PolicyInfo policyInfo,
+            NodeId nodeId, Endpoint ep, OfOverlayContext ofc,
+            EgKey egKey)
+            throws Exception {
+
+
+        //TODO alagalah Li/Be: We should also match on EndpointL3 with the appropriate
+        // network containment. This would solve a lot of problems and prepare for EndpointL3 RPC.
+
+        EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, ep);
+
+        int egId=epFwdCtxOrds.getEpgId();
+        int bdId=epFwdCtxOrds.getBdId();
+        int fdId=epFwdCtxOrds.getFdId();
+        int l3Id=epFwdCtxOrds.getL3Id();
+
+        // Set sEPG, flood domain, bridge domain, and layer 3 context
         // for internal endpoints by directly matching each endpoint
 
-        List<ConditionName> conds = ctx.getEndpointManager().getCondsForEndpoint(e);
-        ConditionGroup cg = 
-                policyInfo.getEgCondGroup(new EgKey(e.getTenant(), 
-                                                    e.getEndpointGroup()), 
-                                          conds);
-        int cgId = ctx.getPolicyManager().getCondGroupOrdinal(cg);
+        List<ConditionName> conds = ctx.getEndpointManager().getCondsForEndpoint(ep);
+        ConditionGroup cg =
+                policyInfo.getEgCondGroup(new EgKey(ep.getTenant(),
+                        egKey.getEgId()),
+                        conds);
+
+        int cgId = OrdinalFactory.getCondGroupOrdinal(cg);
 
         FlowId flowid = new FlowId(new StringBuilder()
-            .append(ofc.getNodeConnectorId().getValue())
-            .append("|")
-            .append(e.getMacAddress().getValue())
-            .append("|")
-            .append(egId)
-            .append("|")
-            .append(bdId)
-            .append("|")
-            .append(fdId)
-            .append("|")
-            .append(l3Id)
-            .append("|")
-            .append(cgId)
-            .toString());
-        if (visit(flowMap, flowid.getValue())) {
-            Action segReg = nxLoadRegAction(NxmNxReg0.class, 
-                                            BigInteger.valueOf(egId));
-            Action scgReg = nxLoadRegAction(NxmNxReg1.class, 
-                                            BigInteger.valueOf(cgId));
-            Action bdReg = nxLoadRegAction(NxmNxReg4.class, 
-                                           BigInteger.valueOf(bdId));
-            Action fdReg = nxLoadRegAction(NxmNxReg5.class, 
-                                           BigInteger.valueOf(fdId));
-            Action vrfReg = nxLoadRegAction(NxmNxReg6.class, 
-                                            BigInteger.valueOf(l3Id));
-            FlowBuilder flowb = base()
+                .append(ofc.getNodeConnectorId().getValue())
+                .append("|")
+                .append(ep.getMacAddress().getValue())
+                .append("|")
+                .append(egId)
+                .append("|")
+                .append(bdId)
+                .append("|")
+                .append(fdId)
+                .append("|")
+                .append(l3Id)
+                .append("|")
+                .append(cgId)
+                .toString());
+        Action segReg = nxLoadRegAction(NxmNxReg0.class,
+                BigInteger.valueOf(egId));
+        Action scgReg = nxLoadRegAction(NxmNxReg1.class,
+                BigInteger.valueOf(cgId));
+        Action bdReg = nxLoadRegAction(NxmNxReg4.class,
+                BigInteger.valueOf(bdId));
+        Action fdReg = nxLoadRegAction(NxmNxReg5.class,
+                BigInteger.valueOf(fdId));
+        Action vrfReg = nxLoadRegAction(NxmNxReg6.class,
+                BigInteger.valueOf(l3Id));
+        FlowBuilder flowb = base()
                 .setPriority(Integer.valueOf(100))
                 .setId(flowid)
                 .setMatch(new MatchBuilder()
-                    .setEthernetMatch(ethernetMatch(e.getMacAddress(), 
-                                                    null, null))
-                    .setInPort(ofc.getNodeConnectorId())
-                    .build())
+                        .setEthernetMatch(ethernetMatch(ep.getMacAddress(),
+                                null, null))
+                        .setInPort(ofc.getNodeConnectorId())
+                        .build())
                 .setInstructions(instructions(applyActionIns(segReg,
-                                                             scgReg,
-                                                             bdReg,
-                                                             fdReg,
-                                                             vrfReg),
-                                              gotoTableIns((short)(TABLE_ID + 1))));
-            writeFlow(t, tiid, flowb.build());
-        }
+                        scgReg,
+                        bdReg,
+                        fdReg,
+                        vrfReg),
+                        gotoTableIns((short) (TABLE_ID + 1))));
+        flowMap.writeFlow(nodeId, TABLE_ID, flowb.build());
     }
+
+
 }
old mode 100644 (file)
new mode 100755 (executable)
index 404b58d..3532deb
-/*
- * 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.flow;
-
-import java.math.BigInteger;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
-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.Ipv6Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.GoToTableCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-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.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
-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.match.layer._3.match.Ipv4Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
-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.NxmNxReg7;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-
-import static org.junit.Assert.*;
-
-import static org.mockito.Matchers.*;
-
-import static org.mockito.Mockito.*;
-
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
-
-public class DestinationMapperTest extends FlowTableTest {
-    protected static final Logger LOG =
-            LoggerFactory.getLogger(DestinationMapperTest.class);
-
-    NodeConnectorId remoteTunnelId =
-            new NodeConnectorId(remoteNodeId.getValue() + ":101");
-
-    @Override
-    @Before
-    public void setup() throws Exception {
-        initCtx();
-        table = new DestinationMapper(ctx);
-        super.setup();
-    }
-
-    @Test
-    public void testNoEps() throws Exception {
-        ReadWriteTransaction t = dosync(null);
-        verify(t, times(1)).put(any(LogicalDatastoreType.class),
-                                Matchers.<InstanceIdentifier<Flow>>any(),
-                                any(Flow.class), anyBoolean());
-    }
-
-    private void verifyDMap(Endpoint remoteEp,
-                            Endpoint localEp) throws Exception {
-
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getMatch() == null) {
-                assertEquals(dropInstructions(),
-                             f.getInstructions());
-                count += 1;
-            } else if (Objects.equals(ethernetMatch(null, null, ARP),
-                                      f.getMatch().getEthernetMatch())) {
-                // router ARP reply
-                Instruction ins = f.getInstructions().getInstruction().get(0);
-                ins = f.getInstructions().getInstruction().get(0);
-                assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
-                List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                assertEquals(nxMoveEthSrcToEthDstAction(),
-                             actions.get(0).getAction());
-                assertEquals(Integer.valueOf(0), actions.get(0).getOrder());
-                assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),
-                             actions.get(1).getAction());
-                assertEquals(Integer.valueOf(1), actions.get(1).getOrder());
-                assertEquals(nxLoadArpOpAction(BigInteger.valueOf(2L)),
-                             actions.get(2).getAction());
-                assertEquals(Integer.valueOf(2), actions.get(2).getOrder());
-                assertEquals(nxMoveArpShaToArpThaAction(),
-                             actions.get(3).getAction());
-                assertEquals(Integer.valueOf(3), actions.get(3).getOrder());
-                assertEquals(nxLoadArpShaAction(new BigInteger(1, DestinationMapper
-                                                               .bytesFromHexString(DestinationMapper.ROUTER_MAC
-                                                                                   .getValue()))),
-                             actions.get(4).getAction());
-                assertEquals(Integer.valueOf(4), actions.get(4).getOrder());
-                assertEquals(nxMoveArpSpaToArpTpaAction(),
-                             actions.get(5).getAction());
-                assertEquals(Integer.valueOf(5), actions.get(5).getOrder());
-                assertTrue(nxLoadArpSpaAction("10.0.0.1").equals(actions.get(6).getAction()) ||
-                           nxLoadArpSpaAction("10.0.1.1").equals(actions.get(6).getAction()) ||
-                           nxLoadArpSpaAction("10.0.2.1").equals(actions.get(6).getAction()));
-                assertEquals(Integer.valueOf(6), actions.get(6).getOrder());
-                count += 1;
-            } else if (Objects.equals(localEp.getMacAddress(),
-                               f.getMatch().getEthernetMatch()
-                                   .getEthernetDestination().getAddress())) {
-                int icount = 0;
-                for (Instruction ins : f.getInstructions().getInstruction()) {
-                    if (ins.getInstruction() instanceof ApplyActionsCase) {
-                        long p = getOfPortNum(nodeConnectorId);
-                        List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                        assertEquals(nxLoadRegAction(NxmNxReg7.class,
-                                                     BigInteger.valueOf(p)),
-                                     actions.get(2).getAction());
-                        icount += 1;
-                    } else if (ins.getInstruction() instanceof GoToTableCase) {
-                        assertEquals(gotoTableIns((short)(table.getTableId()+1)),
-                                     ins.getInstruction());
-                        icount += 1;
-                    }
-                }
-                assertEquals(2, icount);
-                LOG.info("{}", f);
-                count += 1;
-            } else if (Objects.equals(remoteEp.getMacAddress(),
-                                      f.getMatch().getEthernetMatch()
-                                      .getEthernetDestination().getAddress())) {
-                int icount = 0;
-                for (Instruction ins : f.getInstructions().getInstruction()) {
-                    if (ins.getInstruction() instanceof ApplyActionsCase) {
-                        long p = getOfPortNum(tunnelId);
-                        List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                        assertEquals(nxLoadRegAction(NxmNxReg7.class,
-                                                     BigInteger.valueOf(p)),
-                                     actions.get(4).getAction());
-                        icount += 1;
-                    } else if (ins.getInstruction() instanceof GoToTableCase) {
-                        assertEquals(gotoTableIns((short)(table.getTableId()+1)),
-                                     ins.getInstruction());
-                        icount += 1;
-                    }
-                }
-                assertEquals(2, icount);
-                LOG.info("{}", f);
-                count += 1;
-            } else if (Objects.equals(DestinationMapper.ROUTER_MAC,
-                                      f.getMatch().getEthernetMatch()
-                                          .getEthernetDestination()
-                                          .getAddress())) {
-                if (f.getMatch().getLayer3Match() instanceof Ipv4Match) {
-                    // should be local port with rewrite dlsrc and dldst plus
-                    // ttl decr
-                    Instruction ins = f.getInstructions().getInstruction().get(0);
-                    assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
-                    List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                    long p = getOfPortNum(nodeConnectorId);
-                    assertEquals(nxLoadRegAction(NxmNxReg7.class,
-                                                 BigInteger.valueOf(p)),
-                                 actions.get(2).getAction());
-                    assertEquals(Integer.valueOf(2), actions.get(2).getOrder());
-                    assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),
-                                 actions.get(3).getAction());
-                    assertEquals(Integer.valueOf(3), actions.get(3).getOrder());
-                    assertEquals(setDlDstAction(localEp.getMacAddress()),
-                                 actions.get(4).getAction());
-                    assertEquals(Integer.valueOf(4), actions.get(4).getOrder());
-                    assertEquals(decNwTtlAction(),
-                                 actions.get(5).getAction());
-                    assertEquals(Integer.valueOf(5), actions.get(5).getOrder());
-                    count += 1;
-                } else if (f.getMatch().getLayer3Match() instanceof Ipv6Match) {
-                    // should be remote port with rewrite dlsrc plus
-                    // ttl decr
-                    Instruction ins = f.getInstructions().getInstruction().get(0);
-                    assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
-                    List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                    long p = getOfPortNum(tunnelId);
-                    assertEquals(nxLoadRegAction(NxmNxReg7.class,
-                                                 BigInteger.valueOf(p)),
-                                 actions.get(4).getAction());
-                    assertEquals(Integer.valueOf(4), actions.get(4).getOrder());
-                    assertEquals(setDlSrcAction(DestinationMapper.ROUTER_MAC),
-                                 actions.get(5).getAction());
-                    assertEquals(Integer.valueOf(5), actions.get(5).getOrder());
-                    assertEquals(decNwTtlAction(),
-                                 actions.get(6).getAction());
-                    assertEquals(Integer.valueOf(6), actions.get(6).getOrder());
-                    count += 1;
-                }
-            } else if (Objects.equals(DestinationMapper.MULTICAST_MAC,
-                                      f.getMatch().getEthernetMatch()
-                                      .getEthernetDestination()
-                                      .getAddress())) {
-                // broadcast/multicast flow should output to group table
-                Instruction ins = f.getInstructions().getInstruction().get(0);
-                ins = f.getInstructions().getInstruction().get(0);
-                assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
-                List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                assertEquals(nxMoveRegTunIdAction(NxmNxReg0.class, false),
-                             actions.get(0).getAction());
-                assertEquals(Integer.valueOf(0), actions.get(0).getOrder());
-                Long v = Long.valueOf(policyManager.getContextOrdinal(tid, fd));
-                assertEquals(groupAction(v), actions.get(1).getAction());
-                assertEquals(Integer.valueOf(1), actions.get(1).getOrder());
-                count += 1;
-            }
-        }
-
-        assertEquals(8, count);
-
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class),
-                               Matchers.<InstanceIdentifier<Flow>>any(),
-                               any(Flow.class), anyBoolean());
-    }
-
-    @Override
-    protected EndpointBuilder localEP() {
-        return super.localEP()
-            .setL3Address(ImmutableList.of(new L3AddressBuilder()
-                .setL3Context(l3c)
-                .setIpAddress(new IpAddress(new Ipv4Address("10.0.0.1")))
-                .build()));
-    }
-    @Override
-    protected EndpointBuilder remoteEP(NodeId remoteNodeId) {
-        return super.remoteEP(remoteNodeId)
-            .setL3Address(ImmutableList.of(new L3AddressBuilder()
-                .setL3Context(l3c)
-                .setIpAddress(new IpAddress(new Ipv6Address("::ffff:0:0::10.0.0.2")))
-                .build()));
-    }
-
-    private void addSwitches() {
-        switchManager.addSwitch(nodeId, tunnelId,
-                                Collections.<NodeConnectorId>emptySet(),
-                                new OfOverlayNodeConfigBuilder()
-                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))
-                                    .build());
-        switchManager.addSwitch(remoteNodeId, remoteTunnelId,
-                                Collections.<NodeConnectorId>emptySet(),
-                                new OfOverlayNodeConfigBuilder()
-                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.5")))
-                                    .build());
-    }
-
-    @Test
-    public void testSame() throws Exception {
-        Endpoint localEp = localEP().build();
-        endpointManager.addEndpoint(localEp);
-        Endpoint remoteEp = remoteEP(remoteNodeId).build();
-        endpointManager.addEndpoint(remoteEp);
-        addSwitches();
-
-        policyResolver.addTenant(baseTenant().build());
-        verifyDMap(remoteEp, localEp);
-    }
-
-    @Test
-    public void testDiff() throws Exception {
-        Endpoint localEp = localEP().build();
-        endpointManager.addEndpoint(localEp);
-        Endpoint remoteEp = remoteEP(remoteNodeId)
-            .setEndpointGroup(eg2)
-            .build();
-        endpointManager.addEndpoint(remoteEp);
-        addSwitches();
-
-        policyResolver.addTenant(baseTenant().build());
-        verifyDMap(remoteEp, localEp);
-    }
-
-}
+/*\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 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.Test;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;\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.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.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.collect.ImmutableList;\r
+\r
+import static org.junit.Assert.*;\r
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;\r
+\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
+        initCtx();\r
+        table = new DestinationMapper(ctx);\r
+        super.setup();\r
+    }\r
+\r
+    @Test\r
+    public void testNoEps() throws Exception {\r
+        FlowMap fm = dosync(null);\r
+        assertEquals(1 ,fm.getTableForNode(nodeId, (short) 2).getFlow().size());\r
+    }\r
+\r
+    private void verifyDMap(Endpoint remoteEp,\r
+                            Endpoint localEp) throws Exception {\r
+\r
+        FlowMap fm = dosync(null);\r
+        assertNotEquals(0 ,fm.getTableForNode(nodeId, (short) 2).getFlow().size());\r
+\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f :fm.getTableForNode(nodeId, (short) 2).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
+                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((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(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,\r
+                                                     BigInteger.valueOf(p)),\r
+                                     actions.get(4).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
+                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.valueOf(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
+        assertEquals(8, 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
+    @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::10.0.0.2")))\r
+                .build()));\r
+    }\r
+\r
+    private void addSwitches() {\r
+        switchManager.addSwitch(nodeId, tunnelId,\r
+                                Collections.<NodeConnectorId>emptySet(),\r
+                                new OfOverlayNodeConfigBuilder()\r
+                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))\r
+                                    .build());\r
+        switchManager.addSwitch(remoteNodeId, remoteTunnelId,\r
+                                Collections.<NodeConnectorId>emptySet(),\r
+                                new OfOverlayNodeConfigBuilder()\r
+                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.5")))\r
+                                    .build());\r
+    }\r
+\r
+    @Test\r
+    public void testSame() throws Exception {\r
+        Endpoint localEp = localEP().build();\r
+        endpointManager.addEndpoint(localEp);\r
+        Endpoint remoteEp = remoteEP(remoteNodeId).build();\r
+        endpointManager.addEndpoint(remoteEp);\r
+        addSwitches();\r
+\r
+        policyResolver.addTenant(baseTenant().build());\r
+        verifyDMap(remoteEp, localEp);\r
+    }\r
+\r
+    @Test\r
+    public void testDiff() throws Exception {\r
+        Endpoint localEp = localEP().build();\r
+        endpointManager.addEndpoint(localEp);\r
+        Endpoint remoteEp = remoteEP(remoteNodeId)\r
+            .setEndpointGroup(eg2)\r
+            .build();\r
+        endpointManager.addEndpoint(remoteEp);\r
+        addSwitches();\r
+\r
+        policyResolver.addTenant(baseTenant().build());\r
+        verifyDMap(remoteEp, localEp);\r
+    }\r
+\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index 4986e80..c884bc1
@@ -1,39 +1,40 @@
-/*
- * 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.flow;
-
-import java.util.Collections;
-import java.util.Map;
-
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import static org.mockito.Mockito.*;
-
-public class FlowTableTest extends OfTableTest {
-    FlowTable table;
-    InstanceIdentifier<Table> tiid;
-
-    protected void setup() throws Exception {
-        tiid = FlowUtils.createTablePath(nodeId, 
-                                         table.getTableId());
-    }
-
-    protected ReadWriteTransaction dosync(Map<String, FlowCtx> flowMap) 
-              throws Exception {
-        ReadWriteTransaction t = mock(ReadWriteTransaction.class);
-        if (flowMap == null)
-            flowMap = Collections.emptyMap();
-        table.sync(t, tiid, flowMap, nodeId, policyResolver.getCurrentPolicy(), 
-                   null);
-        return t;
-    }
-}
+/*\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 java.util.Map;\r
+\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;\r
+\r
+public class FlowTableTest extends OfTableTest {\r
+    FlowTable table;\r
+    InstanceIdentifier<Table> tiid;\r
+\r
+    protected void setup() throws Exception {\r
+        tiid = FlowUtils.createTablePath(nodeId,\r
+                                         table.getTableId());\r
+    }\r
+\r
+    protected FlowMap dosync(Map<String, Flow> flows) throws Exception {\r
+        FlowMap flowMap = policyManager.new FlowMap();\r
+        if (flows != null) {\r
+            for (String key : flows.keySet()) {\r
+                Flow flow = flows.get(key);\r
+                if (flow != null) {\r
+                    flowMap.writeFlow(nodeId, flow.getTableId(), flow);\r
+                }\r
+            }\r
+        }\r
+        table.sync(nodeId, policyResolver.getCurrentPolicy(), flowMap);\r
+        return flowMap;\r
+    }\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index ad54843..b804402
@@ -1,93 +1,93 @@
-/*
- * 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.flow;
-
-import java.util.Collections;
-import java.util.HashMap;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable.BucketCtx;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable.GroupCtx;
-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.opendaylight.group.types.rev131018.GroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Objects;
-
-import static org.junit.Assert.*;
-
-public class GroupTableTest extends OfTableTest {
-    protected static final Logger LOG = 
-            LoggerFactory.getLogger(GroupTableTest.class);
-
-    GroupTable table;
-
-    NodeConnectorId tunnelId = 
-            new NodeConnectorId(nodeId.getValue() + ":42");
-    NodeConnectorId remoteTunnelId = 
-            new NodeConnectorId(remoteNodeId.getValue() + ":101");
-
-    @Before
-    public void setup() throws Exception {
-        initCtx();
-        table = new GroupTable(ctx);
-    }
-    
-    @Test
-    public void testGroup() throws Exception {
-        Endpoint localEp = localEP().build();
-        endpointManager.addEndpoint(localEp);
-        Endpoint remoteEp = remoteEP(remoteNodeId).build();
-        endpointManager.addEndpoint(remoteEp);
-        
-        switchManager.addSwitch(nodeId, tunnelId, 
-                                Collections.<NodeConnectorId>emptySet(),
-                                new OfOverlayNodeConfigBuilder()
-                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))
-                                    .build());
-        switchManager.addSwitch(remoteNodeId, remoteTunnelId, 
-                                Collections.<NodeConnectorId>emptySet(),
-                                new OfOverlayNodeConfigBuilder()
-                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.5")))
-                                    .build());
-
-        policyResolver.addTenant(baseTenant().build());
-
-        HashMap<GroupId, GroupCtx> groupMap = new HashMap<>();
-        table.sync(nodeId, ctx.getPolicyResolver().getCurrentPolicy(),
-                   null, groupMap);
-        
-        assertEquals(1, groupMap.size());
-        int fdId = ctx.getPolicyManager().getContextOrdinal(tid, fd);
-        GroupCtx ctx = groupMap.get(new GroupId(Long.valueOf(fdId)));
-        assertNotNull(ctx);
-        long tunBucketId = 
-                (long)policyManager.getContextOrdinal(remoteNodeId.getValue());
-        tunBucketId |= 1L << 31;
-        int count = 0;
-        for (BucketCtx bctx : ctx.bucketMap.values()) {
-            if (Objects.equal(Long.valueOf(4),
-                              bctx.newb.getBucketId().getValue())) {
-                count += 1;
-            } else if (Objects.equal(Long.valueOf(tunBucketId),
-                                     bctx.newb.getBucketId().getValue())) {
-                
-                count += 1;
-            }
-        }
-        assertEquals(2, count);
-    }
-}
+/*\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.assertNotNull;\r
+\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable.BucketCtx;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.GroupTable.GroupCtx;\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.opendaylight.group.types.rev131018.GroupId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.base.Objects;\r
+\r
+public class GroupTableTest extends OfTableTest {\r
+    protected static final Logger LOG =\r
+            LoggerFactory.getLogger(GroupTableTest.class);\r
+\r
+    GroupTable table;\r
+\r
+    NodeConnectorId tunnelId =\r
+            new NodeConnectorId(nodeId.getValue() + ":42");\r
+    NodeConnectorId remoteTunnelId =\r
+            new NodeConnectorId(remoteNodeId.getValue() + ":101");\r
+\r
+    @Before\r
+    public void setup() throws Exception {\r
+        initCtx();\r
+        table = new GroupTable(ctx);\r
+    }\r
+\r
+    @Test\r
+    public void testGroup() throws Exception {\r
+        Endpoint localEp = localEP().build();\r
+        endpointManager.addEndpoint(localEp);\r
+        Endpoint remoteEp = remoteEP(remoteNodeId).build();\r
+        endpointManager.addEndpoint(remoteEp);\r
+\r
+        switchManager.addSwitch(nodeId, tunnelId,\r
+                                Collections.<NodeConnectorId>emptySet(),\r
+                                new OfOverlayNodeConfigBuilder()\r
+                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))\r
+                                    .build());\r
+        switchManager.addSwitch(remoteNodeId, remoteTunnelId,\r
+                                Collections.<NodeConnectorId>emptySet(),\r
+                                new OfOverlayNodeConfigBuilder()\r
+                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.5")))\r
+                                    .build());\r
+\r
+        policyResolver.addTenant(baseTenant().build());\r
+\r
+        HashMap<GroupId, GroupCtx> groupMap = new HashMap<>();\r
+        table.sync(nodeId, ctx.getPolicyResolver().getCurrentPolicy(), groupMap);\r
+\r
+        assertEquals(1, groupMap.size());\r
+        int fdId = OrdinalFactory.getContextOrdinal(tid, fd);\r
+        GroupCtx ctx = groupMap.get(new GroupId(Long.valueOf(fdId)));\r
+        assertNotNull(ctx);\r
+        long tunBucketId =\r
+                OrdinalFactory.getContextOrdinal(remoteNodeId);\r
+        tunBucketId |= 1L << 31;\r
+\r
+        int count = 0;\r
+        for (BucketCtx bctx : ctx.bucketMap.values()) {\r
+            if (Objects.equal(Long.valueOf(4),\r
+                              bctx.newb.getBucketId().getValue())) {\r
+                count += 1;\r
+            } else if (Objects.equal(Long.valueOf(tunBucketId),\r
+                                     bctx.newb.getBucketId().getValue())) {\r
+\r
+                count += 1;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+    }\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index cd7beaf..cdb5779
-/*
- * 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.flow;
-
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockEndpointManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockSwitchManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;
-import org.opendaylight.groupbasedpolicy.resolver.MockPolicyResolver;
-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.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
-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.L2FloodDomainId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
-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.EndpointBuilder;
-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.HasDirection.Direction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRefBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;
-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.ContractBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomainBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubjectFeatureInstancesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubnetBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstanceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-
-import com.google.common.collect.ImmutableList;
-
-public class OfTableTest {
-    OfContext ctx;
-
-    MockEndpointManager endpointManager;
-    MockPolicyResolver policyResolver;
-    MockPolicyManager policyManager;
-    MockSwitchManager switchManager;
-
-    NodeId nodeId = new NodeId("openflow:1");
-    NodeId remoteNodeId = new NodeId("openflow:2");
-    NodeConnectorId nodeConnectorId =
-            new NodeConnectorId(nodeId.getValue() + ":4");
-
-    NodeConnectorId tunnelId =
-            new NodeConnectorId(nodeId.getValue() + ":42");
-
-    L3ContextId l3c = new L3ContextId("2cf51ee4-e996-467e-a277-2d380334a91d");
-    L2BridgeDomainId bd = new L2BridgeDomainId("c95182ba-7807-43f8-98f7-6c7c720b7639");
-    L2FloodDomainId fd = new L2FloodDomainId("98e1439e-52d2-46f8-bd69-5136e6088771");
-    SubnetId sub = new SubnetId("4fcf8dfc-53b5-4aef-84d3-6b5586992fcb");
-    SubnetId sub2 = new SubnetId("c285a59f-fcb8-42e6-bf29-87ea522fd626");
-    SubnetId sub3 = new SubnetId("a0380d52-2a25-48ef-882c-a4d4cd9e00ec");
-    TenantId tid = new TenantId("1118c691-8520-47ad-80b8-4cf5e3fe3302");
-    EndpointGroupId eg = new EndpointGroupId("36dec84a-08c7-497b-80b6-a0035af72a12");
-    EndpointGroupId eg2 = new EndpointGroupId("632e5e11-7988-4eb5-8fe6-6c182d890276");
-    ContractId cid = new ContractId("a5874893-bcd5-46de-96af-3c8d99bedf9f");
-
-    protected void initCtx() {
-        endpointManager = new MockEndpointManager();
-        policyResolver = new MockPolicyResolver();
-        policyManager = new MockPolicyManager(policyResolver, endpointManager);
-        switchManager = new MockSwitchManager();
-
-        ctx = new OfContext(null,
-                             null,
-                             policyManager,
-                             policyResolver,
-                             switchManager,
-                             endpointManager,
-                             null);
-    }
-
-    protected TenantBuilder baseTenant() {
-        return baseTenant(null);
-    }
-
-    protected TenantBuilder baseTenant(Direction direction) {
-        return new TenantBuilder()
-            .setId(tid)
-            .setEndpointGroup(ImmutableList.of(new EndpointGroupBuilder()
-                    .setId(eg)
-                    .setNetworkDomain(sub)
-                    .setConsumerNamedSelector(ImmutableList.of(new ConsumerNamedSelectorBuilder()
-                        .setName(new SelectorName("cns1"))
-                        .setContract(ImmutableList.of(cid))
-                        .build()))
-                    .build(),
-                new EndpointGroupBuilder()
-                    .setId(eg2)
-                    .setNetworkDomain(sub2)
-                    .setProviderNamedSelector(ImmutableList.of(new ProviderNamedSelectorBuilder()
-                        .setName(new SelectorName("pns1"))
-                        .setContract(ImmutableList.of(cid))
-                        .build()))
-                    .build()))
-            .setL3Context(ImmutableList.of(new L3ContextBuilder()
-                .setId(l3c)
-                .build()))
-            .setL2BridgeDomain(ImmutableList.of(new L2BridgeDomainBuilder()
-                .setId(bd)
-                .setParent(l3c)
-                .build()))
-            .setL2FloodDomain(ImmutableList.of(new L2FloodDomainBuilder()
-                .setId(fd)
-                .setParent(bd)
-                .build()))
-            .setSubnet(ImmutableList.of(new SubnetBuilder()
-                    .setId(sub2)
-                    .setParent(fd)
-                    .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.1.1/24")))
-                    .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.1.1")))
-                    .build(),
-                new SubnetBuilder()
-                    .setId(sub)
-                    .setParent(fd)
-                    .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.0.1/24")))
-                    .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.0.1")))
-                    .build(),
-                new SubnetBuilder()
-                    .setId(sub3)
-                    .setParent(bd)
-                    .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.2.1/24")))
-                    .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.2.1")))
-                    .build()))
-            .setSubjectFeatureInstances(new SubjectFeatureInstancesBuilder()
-                .setClassifierInstance(ImmutableList.of(new ClassifierInstanceBuilder()
-                     .setName(new ClassifierName("tcp_80"))
-                     .setClassifierDefinitionId(L4Classifier.DEFINITION.getId())
-                     .setParameterValue(ImmutableList.of(new ParameterValueBuilder()
-                              .setName(new ParameterName("destport"))
-                              .setIntValue(Long.valueOf(80))
-                              .build(),
-                          new ParameterValueBuilder()
-                             .setName(new ParameterName("proto"))
-                             .setIntValue(Long.valueOf(6))
-                             .build()))
-                     .build()))
-                .setActionInstance(ImmutableList.of(new ActionInstanceBuilder()
-                    .setName(new ActionName("allow"))
-                    .setActionDefinitionId(new AllowAction().getId())
-                    .build()))
-                .build())
-            .setContract(ImmutableList.of(new ContractBuilder()
-                .setId(cid)
-                .setSubject(ImmutableList.of(baseSubject(direction).build()))
-                .setClause(ImmutableList.of(new ClauseBuilder()
-                     .setName(new ClauseName("test"))
-                     .setSubjectRefs(ImmutableList.of(new SubjectName("s1")))
-                     .build()))
-                .build()));
-    }
-
-    protected SubjectBuilder baseSubject(Direction direction) {
-        return new SubjectBuilder()
-            .setName(new SubjectName("s1"))
-            .setRule(ImmutableList.of(new RuleBuilder()
-                .setActionRef(ImmutableList.of(new ActionRefBuilder()
-                    .setName(new ActionName("allow"))
-                    .build()))
-                .setClassifierRef(ImmutableList.of(new ClassifierRefBuilder()
-                    .setName(new ClassifierName("tcp_80"))
-                    .setDirection(direction)
-                    .build()))
-                .build()));
-    }
-
-    protected EndpointBuilder baseEP() {
-        return new EndpointBuilder()
-            .setL2Context(bd)
-            .setTenant(tid)
-            .setEndpointGroup(eg)
-            .setMacAddress(new MacAddress("00:00:00:00:00:01"));
-    }
-
-    protected EndpointBuilder localEP() {
-        OfOverlayContext ofc = new OfOverlayContextBuilder()
-            .setNodeId(nodeId)
-            .setNodeConnectorId(nodeConnectorId)
-            .build();
-        return baseEP()
-            .addAugmentation(OfOverlayContext.class, ofc);
-    }
-
-    protected EndpointBuilder remoteEP(NodeId id) {
-        OfOverlayContext ofc = new OfOverlayContextBuilder()
-            .setNodeId(id)
-            .setNodeConnectorId(new NodeConnectorId(id.getValue() + ":5"))
-            .build();
-        return baseEP()
-            .setMacAddress(new MacAddress("00:00:00:00:00:02"))
-            .addAugmentation(OfOverlayContext.class, ofc);
-    }
-
-}
+/*\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 org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockEndpointManager;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockSwitchManager;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.L4Classifier;\r
+import org.opendaylight.groupbasedpolicy.resolver.MockPolicyResolver;\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.IpPrefix;\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.Ipv4Prefix;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;\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.ClauseName;\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
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2FloodDomainId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SelectorName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;\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.OfOverlayContext;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRefBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.classifier.refs.ClassifierRefBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValueBuilder;\r
+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.ContractBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroupBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomainBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2FloodDomainBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3ContextBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubjectFeatureInstancesBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubnetBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.SubjectBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.RuleBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelectorBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelectorBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstanceBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ClassifierInstanceBuilder;\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
+\r
+import com.google.common.collect.ImmutableList;\r
+\r
+public class OfTableTest {\r
+    OfContext ctx;\r
+\r
+    MockEndpointManager endpointManager;\r
+    MockPolicyResolver policyResolver;\r
+    MockPolicyManager policyManager;\r
+    MockSwitchManager switchManager;\r
+    NodeId nodeId = new NodeId("openflow:1");\r
+    NodeId remoteNodeId = new NodeId("openflow:2");\r
+    NodeConnectorId nodeConnectorId =\r
+            new NodeConnectorId(nodeId.getValue() + ":4");\r
+\r
+    NodeConnectorId tunnelId =\r
+            new NodeConnectorId(nodeId.getValue() + ":42");\r
+\r
+    L3ContextId l3c = new L3ContextId("2cf51ee4-e996-467e-a277-2d380334a91d");\r
+    L2BridgeDomainId bd = new L2BridgeDomainId("c95182ba-7807-43f8-98f7-6c7c720b7639");\r
+    L2FloodDomainId fd = new L2FloodDomainId("98e1439e-52d2-46f8-bd69-5136e6088771");\r
+    SubnetId sub = new SubnetId("4fcf8dfc-53b5-4aef-84d3-6b5586992fcb");\r
+    SubnetId sub2 = new SubnetId("c285a59f-fcb8-42e6-bf29-87ea522fd626");\r
+    SubnetId sub3 = new SubnetId("a0380d52-2a25-48ef-882c-a4d4cd9e00ec");\r
+    TenantId tid = new TenantId("1118c691-8520-47ad-80b8-4cf5e3fe3302");\r
+    EndpointGroupId eg = new EndpointGroupId("36dec84a-08c7-497b-80b6-a0035af72a12");\r
+    EndpointGroupId eg2 = new EndpointGroupId("632e5e11-7988-4eb5-8fe6-6c182d890276");\r
+    ContractId cid = new ContractId("a5874893-bcd5-46de-96af-3c8d99bedf9f");\r
+\r
+    protected void initCtx() {\r
+        endpointManager = new MockEndpointManager();\r
+        policyResolver = new MockPolicyResolver();\r
+        policyManager = new MockPolicyManager(policyResolver, endpointManager);\r
+        switchManager = new MockSwitchManager();\r
+        ctx = new OfContext(null,\r
+                             null,\r
+                             policyManager,\r
+                             policyResolver,\r
+                             switchManager,\r
+                             endpointManager,\r
+                             null);\r
+    }\r
+\r
+    protected TenantBuilder baseTenant() {\r
+        return baseTenant(null);\r
+    }\r
+\r
+    protected TenantBuilder baseTenant(Direction direction) {\r
+        return new TenantBuilder()\r
+            .setId(tid)\r
+            .setEndpointGroup(ImmutableList.of(new EndpointGroupBuilder()\r
+                    .setId(eg)\r
+                    .setNetworkDomain(sub)\r
+                    .setConsumerNamedSelector(ImmutableList.of(new ConsumerNamedSelectorBuilder()\r
+                        .setName(new SelectorName("cns1"))\r
+                        .setContract(ImmutableList.of(cid))\r
+                        .build()))\r
+                    .build(),\r
+                new EndpointGroupBuilder()\r
+                    .setId(eg2)\r
+                    .setNetworkDomain(sub2)\r
+                    .setProviderNamedSelector(ImmutableList.of(new ProviderNamedSelectorBuilder()\r
+                        .setName(new SelectorName("pns1"))\r
+                        .setContract(ImmutableList.of(cid))\r
+                        .build()))\r
+                    .build()))\r
+            .setL3Context(ImmutableList.of(new L3ContextBuilder()\r
+                .setId(l3c)\r
+                .build()))\r
+            .setL2BridgeDomain(ImmutableList.of(new L2BridgeDomainBuilder()\r
+                .setId(bd)\r
+                .setParent(l3c)\r
+                .build()))\r
+            .setL2FloodDomain(ImmutableList.of(new L2FloodDomainBuilder()\r
+                .setId(fd)\r
+                .setParent(bd)\r
+                .build()))\r
+            .setSubnet(ImmutableList.of(new SubnetBuilder()\r
+                    .setId(sub2)\r
+                    .setParent(fd)\r
+                    .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.1.1/24")))\r
+                    .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.1.1")))\r
+                    .build(),\r
+                new SubnetBuilder()\r
+                    .setId(sub)\r
+                    .setParent(fd)\r
+                    .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.0.1/24")))\r
+                    .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.0.1")))\r
+                    .build(),\r
+                new SubnetBuilder()\r
+                    .setId(sub3)\r
+                    .setParent(bd)\r
+                    .setIpPrefix(new IpPrefix(new Ipv4Prefix("10.0.2.1/24")))\r
+                    .setVirtualRouterIp(new IpAddress(new Ipv4Address("10.0.2.1")))\r
+                    .build()))\r
+            .setSubjectFeatureInstances(new SubjectFeatureInstancesBuilder()\r
+                .setClassifierInstance(ImmutableList.of(new ClassifierInstanceBuilder()\r
+                     .setName(new ClassifierName("tcp_80"))\r
+                     .setClassifierDefinitionId(L4Classifier.DEFINITION.getId())\r
+                     .setParameterValue(ImmutableList.of(new ParameterValueBuilder()\r
+                              .setName(new ParameterName("destport"))\r
+                              .setIntValue(Long.valueOf(80))\r
+                              .build(),\r
+                          new ParameterValueBuilder()\r
+                             .setName(new ParameterName("proto"))\r
+                             .setIntValue(Long.valueOf(6))\r
+                             .build()))\r
+                     .build()))\r
+                .setActionInstance(ImmutableList.of(new ActionInstanceBuilder()\r
+                    .setName(new ActionName("allow"))\r
+                    .setActionDefinitionId(new AllowAction().getId())\r
+                    .build()))\r
+                .build())\r
+            .setContract(ImmutableList.of(new ContractBuilder()\r
+                .setId(cid)\r
+                .setSubject(ImmutableList.of(baseSubject(direction).build()))\r
+                .setClause(ImmutableList.of(new ClauseBuilder()\r
+                     .setName(new ClauseName("test"))\r
+                     .setSubjectRefs(ImmutableList.of(new SubjectName("s1")))\r
+                     .build()))\r
+                .build()));\r
+    }\r
+\r
+    protected SubjectBuilder baseSubject(Direction direction) {\r
+        return new SubjectBuilder()\r
+            .setName(new SubjectName("s1"))\r
+            .setRule(ImmutableList.of(new RuleBuilder()\r
+                .setActionRef(ImmutableList.of(new ActionRefBuilder()\r
+                    .setName(new ActionName("allow"))\r
+                    .build()))\r
+                .setClassifierRef(ImmutableList.of(new ClassifierRefBuilder()\r
+                    .setName(new ClassifierName("tcp_80"))\r
+                    .setDirection(direction)\r
+                    .build()))\r
+                .build()));\r
+    }\r
+\r
+    protected EndpointBuilder baseEP() {\r
+        return new EndpointBuilder()\r
+            .setL2Context(bd)\r
+            .setTenant(tid)\r
+            .setEndpointGroup(eg)\r
+            .setMacAddress(new MacAddress("00:00:00:00:00:01"));\r
+    }\r
+\r
+    protected EndpointBuilder localEP() {\r
+        OfOverlayContext ofc = new OfOverlayContextBuilder()\r
+            .setNodeId(nodeId)\r
+            .setNodeConnectorId(nodeConnectorId)\r
+            .build();\r
+        return baseEP()\r
+            .addAugmentation(OfOverlayContext.class, ofc);\r
+    }\r
+\r
+    protected EndpointBuilder remoteEP(NodeId id) {\r
+        OfOverlayContext ofc = new OfOverlayContextBuilder()\r
+            .setNodeId(id)\r
+            .setNodeConnectorId(new NodeConnectorId(id.getValue() + ":5"))\r
+            .build();\r
+        return baseEP()\r
+            .setMacAddress(new MacAddress("00:00:00:00:00:02"))\r
+            .addAugmentation(OfOverlayContext.class, ofc);\r
+    }\r
+\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index d85ecc7..deea207
-/*
- * 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.flow;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
-import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
-import org.opendaylight.groupbasedpolicy.resolver.EgKey;
-import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
-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.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionMatcherName;
-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.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcherBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.Condition;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.ConditionBuilder;
-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.ContractBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;
-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._4.match.TcpMatch;
-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.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.NxmNxReg7;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-
-import static org.junit.Assert.*;
-
-import static org.mockito.Matchers.*;
-
-import static org.mockito.Mockito.*;
-
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
-
-public class PolicyEnforcerTest extends FlowTableTest {
-    protected static final Logger LOG = 
-            LoggerFactory.getLogger(PolicyEnforcerTest.class);
-
-    @Before
-    public void setup() throws Exception {
-        initCtx();
-        table = new PolicyEnforcer(ctx);
-        super.setup();
-        
-        switchManager.addSwitch(nodeId, tunnelId, 
-                                Collections.<NodeConnectorId>emptySet(),
-                                new OfOverlayNodeConfigBuilder()
-                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))
-                                    .build());
-    }
-
-    @Test
-    public void testNoEps() throws Exception {
-        ReadWriteTransaction t = dosync(null);
-        verify(t, times(2)).put(any(LogicalDatastoreType.class), 
-                                Matchers.<InstanceIdentifier<Flow>>any(), 
-                                any(Flow.class), anyBoolean());
-    }
-    
-    @Test
-    public void testSameEg() throws Exception {
-        Endpoint ep1 = localEP().build();
-        endpointManager.addEndpoint(ep1);
-        Endpoint ep2 = localEP()
-            .setMacAddress(new MacAddress("00:00:00:00:00:02"))
-            .build();
-        endpointManager.addEndpoint(ep2);
-        policyResolver.addTenant(baseTenant().build());
-        
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION), 
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getId().getValue().indexOf("intraallow") == 0)
-                count += 1;
-        }
-        assertEquals(1, count);
-
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class), 
-                               Matchers.<InstanceIdentifier<Flow>>any(), 
-                               any(Flow.class), anyBoolean());
-    }
-
-    @Test
-    public void testDifferentEg() throws Exception {
-        doTestDifferentEg(null);
-        doTestDifferentEg(Direction.Bidirectional);
-        doTestDifferentEg(Direction.In);
-        doTestDifferentEg(Direction.Out);
-    }
-    
-    public void doTestDifferentEg(Direction direction) throws Exception {
-        Endpoint ep1 = localEP().build();
-        endpointManager.addEndpoint(ep1);
-        Endpoint ep2 = localEP()
-            .setMacAddress(new MacAddress("00:00:00:00:00:02"))
-            .setEndpointGroup(eg2)
-            .build();
-        endpointManager.addEndpoint(ep2);
-        policyResolver.addTenant(baseTenant(direction).build());
-        
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION), 
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getId().getValue().indexOf("intraallow") == 0) {
-                count += 1;
-            } else if (f.getMatch() != null &&
-                       Objects.equals(tunnelId, f.getMatch().getInPort())) {
-                assertEquals(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))),
-                             f.getInstructions());
-                count += 1;
-            } else if (f.getMatch() != null &&
-                       f.getMatch().getEthernetMatch() != null &&
-                       Objects.equals(FlowUtils.IPv4,
-                                      f.getMatch().getEthernetMatch()
-                                          .getEthernetType().getType().getValue()) &&
-                       f.getMatch().getIpMatch() != null &&
-                       Objects.equals(Short.valueOf((short)6),
-                                      f.getMatch().getIpMatch().getIpProtocol()) &&
-                       Objects.equals(Integer.valueOf(80),
-                                      ((TcpMatch)f.getMatch().getLayer4Match())
-                                          .getTcpDestinationPort().getValue())) {
-                count += 1;
-            } else if (f.getMatch() != null &&
-                       f.getMatch().getEthernetMatch() != null &&
-                       Objects.equals(FlowUtils.IPv6,
-                                      f.getMatch().getEthernetMatch()
-                                          .getEthernetType().getType().getValue()) &&
-                       f.getMatch().getIpMatch() != null &&
-                       Objects.equals(Short.valueOf((short)6),
-                                      f.getMatch().getIpMatch().getIpProtocol()) &&
-                       Objects.equals(Integer.valueOf(80),
-                                      ((TcpMatch)f.getMatch().getLayer4Match())
-                                          .getTcpDestinationPort().getValue())) {
-                count += 1;
-            } 
-        }
-        if (direction == null || direction.equals(Direction.Bidirectional))
-            assertEquals(7, count);
-        else
-            assertEquals(5, count);
-
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class), 
-                               Matchers.<InstanceIdentifier<Flow>>any(), 
-                               any(Flow.class), anyBoolean());
-    }
-
-    @Test
-    public void testConditions() throws Exception {
-        Condition cond1 = new ConditionBuilder()
-            .setName(new ConditionName("cond1"))
-            .build();
-        Condition cond2 = new ConditionBuilder()
-            .setName(new ConditionName("cond2"))
-            .build();
-
-        Endpoint ep1 = localEP()
-            .setCondition(ImmutableList.of(cond1.getName()))
-            .build();
-        endpointManager.addEndpoint(ep1);
-        Endpoint ep2 = localEP()
-            .setMacAddress(new MacAddress("00:00:00:00:00:02"))
-            .setCondition(ImmutableList.of(cond1.getName(), cond2.getName()))
-            .setEndpointGroup(eg2)
-            .build();
-        endpointManager.addEndpoint(ep2);        
-        
-        TenantBuilder tb = baseTenant()
-            .setContract(ImmutableList.of(new ContractBuilder()
-                .setId(cid)
-                .setSubject(ImmutableList.of(baseSubject(Direction.Out).build()))
-                .setClause(ImmutableList.of(new ClauseBuilder()
-                    .setName(new ClauseName("test"))
-                    .setSubjectRefs(ImmutableList.of(new SubjectName("s1")))
-                    .setConsumerMatchers(new ConsumerMatchersBuilder()
-                        .setConditionMatcher(ImmutableList.of(new ConditionMatcherBuilder()
-                            .setName(new ConditionMatcherName("m1"))
-                            .setCondition(ImmutableList.of(cond1, cond2))
-                            .setMatchType(MatchType.Any)
-                            .build()))
-                        .build())
-                    .setProviderMatchers(new ProviderMatchersBuilder()
-                        .setConditionMatcher(ImmutableList.of(new ConditionMatcherBuilder()
-                            .setName(new ConditionMatcherName("m2"))
-                            .setCondition(ImmutableList.of(cond1, cond2))
-                            .setMatchType(MatchType.All)
-                            .build()))
-                        .build())
-                    .build()))
-                .build()));
-        policyResolver.addTenant(tb.build());
-
-        PolicyInfo policy = policyResolver.getCurrentPolicy();
-        List<ConditionName> ep1c = endpointManager.getCondsForEndpoint(ep1);
-        ConditionGroup cg1 = 
-                policy.getEgCondGroup(new EgKey(tb.getId(), 
-                                                ep1.getEndpointGroup()),
-                                      ep1c);
-        List<ConditionName> ep2c = endpointManager.getCondsForEndpoint(ep2);
-        ConditionGroup cg2 = 
-                policy.getEgCondGroup(new EgKey(tb.getId(), 
-                                                ep2.getEndpointGroup()),
-                                      ep2c);
-        int cg1Id = policyManager.getCondGroupOrdinal(cg1);
-        int cg2Id = policyManager.getCondGroupOrdinal(cg2);
-        int eg1Id = policyManager.getContextOrdinal(ep1.getTenant(),
-                                                    ep1.getEndpointGroup());
-        int eg2Id = policyManager.getContextOrdinal(ep1.getTenant(),
-                                                    ep2.getEndpointGroup());
-
-        assertNotEquals(cg1Id, cg2Id);
-
-        MatchBuilder mb = new MatchBuilder();
-        FlowUtils.addNxRegMatch(mb, 
-                                RegMatch.of(NxmNxReg0.class, Long.valueOf(eg1Id)),
-                                RegMatch.of(NxmNxReg1.class, Long.valueOf(cg1Id)),
-                                RegMatch.of(NxmNxReg2.class, Long.valueOf(eg2Id)),
-                                RegMatch.of(NxmNxReg3.class, Long.valueOf(cg2Id)));
-        GeneralAugMatchNodesNodeTableFlow m1 =
-                mb.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);
-        FlowUtils.addNxRegMatch(mb, 
-                                RegMatch.of(NxmNxReg0.class, Long.valueOf(eg2Id)),
-                                RegMatch.of(NxmNxReg1.class, Long.valueOf(cg2Id)),
-                                RegMatch.of(NxmNxReg2.class, Long.valueOf(eg1Id)),
-                                RegMatch.of(NxmNxReg3.class, Long.valueOf(cg1Id)));
-        GeneralAugMatchNodesNodeTableFlow m2 =
-                mb.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);
-
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION), 
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getMatch() != null &&
-                f.getMatch().getEthernetMatch() != null) {
-                GeneralAugMatchNodesNodeTableFlow fm =
-                        f.getMatch().getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);
-                assertTrue(Objects.equals(fm, m1) ||
-                           Objects.equals(fm, m2));
-                count += 1;
-            }
-        }
-        assertEquals(2, count);
-
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class), 
-                               Matchers.<InstanceIdentifier<Flow>>any(), 
-                               any(Flow.class), anyBoolean());
-    }
-}
+/*\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 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.Test;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;\r
+import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;\r
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;\r
+import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;\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.yang.types.rev100924.MacAddress;\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.flow.MatchBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClauseName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionMatcherName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayNodeConfigBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcherBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.Condition;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.ConditionBuilder;\r
+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.ContractBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.ClauseBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ConsumerMatchersBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.ProviderMatchersBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;\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.NxmNxReg1;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg3;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.collect.ImmutableList;\r
+\r
+import static org.junit.Assert.*;\r
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;\r
+\r
+public class PolicyEnforcerTest extends FlowTableTest {\r
+    protected static final Logger LOG = \r
+            LoggerFactory.getLogger(PolicyEnforcerTest.class);\r
+\r
+    @Before\r
+    public void setup() throws Exception {\r
+        initCtx();\r
+        table = new PolicyEnforcer(ctx);\r
+        super.setup();\r
+        \r
+        switchManager.addSwitch(nodeId, tunnelId, \r
+                                Collections.<NodeConnectorId>emptySet(),\r
+                                new OfOverlayNodeConfigBuilder()\r
+                                    .setTunnelIp(new IpAddress(new Ipv4Address("1.2.3.4")))\r
+                                    .build());\r
+    }\r
+\r
+    @Test\r
+    public void testNoEps() throws Exception {\r
+        FlowMap fm = dosync(null);\r
+        assertEquals(2, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testSameEg() throws Exception {\r
+        Endpoint ep1 = localEP().build();\r
+        endpointManager.addEndpoint(ep1);\r
+        Endpoint ep2 = localEP()\r
+            .setMacAddress(new MacAddress("00:00:00:00:00:02"))\r
+            .build();\r
+        endpointManager.addEndpoint(ep2);\r
+        policyResolver.addTenant(baseTenant().build());\r
+\r
+        FlowMap fm = dosync(null);\r
+        assertNotEquals(0, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 3).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getId().getValue().indexOf("intraallow") == 0)\r
+                count += 1;\r
+        }\r
+        assertEquals(1, count);\r
+        assertEquals(3, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+        fm = dosync(flowMap);\r
+        assertEquals(3, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testDifferentEg() throws Exception {\r
+        doTestDifferentEg(null);\r
+        doTestDifferentEg(Direction.Bidirectional);\r
+        doTestDifferentEg(Direction.In);\r
+        doTestDifferentEg(Direction.Out);\r
+    }\r
+\r
+    public void doTestDifferentEg(Direction direction) throws Exception {\r
+        Endpoint ep1 = localEP().build();\r
+        endpointManager.addEndpoint(ep1);\r
+        Endpoint ep2 = localEP()\r
+            .setMacAddress(new MacAddress("00:00:00:00:00:02"))\r
+            .setEndpointGroup(eg2)\r
+            .build();\r
+        endpointManager.addEndpoint(ep2);\r
+        policyResolver.addTenant(baseTenant(direction).build());\r
+\r
+        FlowMap fm = dosync(null);\r
+        assertNotEquals(0, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 3).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getId().getValue().indexOf("intraallow") == 0) {\r
+                count += 1;\r
+            } else if (f.getMatch() != null &&\r
+                       Objects.equals(tunnelId, f.getMatch().getInPort())) {\r
+                assertEquals(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))),\r
+                             f.getInstructions());\r
+                count += 1;\r
+            } else if (f.getMatch() != null &&\r
+                       f.getMatch().getEthernetMatch() != null &&\r
+                       Objects.equals(FlowUtils.IPv4,\r
+                                      f.getMatch().getEthernetMatch()\r
+                                          .getEthernetType().getType().getValue()) &&\r
+                       f.getMatch().getIpMatch() != null &&\r
+                       Objects.equals(Short.valueOf((short)6),\r
+                                      f.getMatch().getIpMatch().getIpProtocol()) &&\r
+                       Objects.equals(Integer.valueOf(80),\r
+                                      ((TcpMatch)f.getMatch().getLayer4Match())\r
+                                          .getTcpDestinationPort().getValue())) {\r
+                count += 1;\r
+            } else if (f.getMatch() != null &&\r
+                       f.getMatch().getEthernetMatch() != null &&\r
+                       Objects.equals(FlowUtils.IPv6,\r
+                                      f.getMatch().getEthernetMatch()\r
+                                          .getEthernetType().getType().getValue()) &&\r
+                       f.getMatch().getIpMatch() != null &&\r
+                       Objects.equals(Short.valueOf((short)6),\r
+                                      f.getMatch().getIpMatch().getIpProtocol()) &&\r
+                       Objects.equals(Integer.valueOf(80),\r
+                                      ((TcpMatch)f.getMatch().getLayer4Match())\r
+                                          .getTcpDestinationPort().getValue())) {\r
+                count += 1;\r
+            } \r
+        }\r
+        if (direction == null || direction.equals(Direction.Bidirectional))\r
+            assertEquals(7, count);\r
+        else\r
+            assertEquals(5, count);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 3).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testConditions() throws Exception {\r
+        Condition cond1 = new ConditionBuilder()\r
+            .setName(new ConditionName("cond1"))\r
+            .build();\r
+        Condition cond2 = new ConditionBuilder()\r
+            .setName(new ConditionName("cond2"))\r
+            .build();\r
+\r
+        Endpoint ep1 = localEP()\r
+            .setCondition(ImmutableList.of(cond1.getName()))\r
+            .build();\r
+        endpointManager.addEndpoint(ep1);\r
+        Endpoint ep2 = localEP()\r
+            .setMacAddress(new MacAddress("00:00:00:00:00:02"))\r
+            .setCondition(ImmutableList.of(cond1.getName(), cond2.getName()))\r
+            .setEndpointGroup(eg2)\r
+            .build();\r
+        endpointManager.addEndpoint(ep2);        \r
+\r
+        TenantBuilder tb = baseTenant()\r
+            .setContract(ImmutableList.of(new ContractBuilder()\r
+                .setId(cid)\r
+                .setSubject(ImmutableList.of(baseSubject(Direction.Out).build()))\r
+                .setClause(ImmutableList.of(new ClauseBuilder()\r
+                    .setName(new ClauseName("test"))\r
+                    .setSubjectRefs(ImmutableList.of(new SubjectName("s1")))\r
+                    .setConsumerMatchers(new ConsumerMatchersBuilder()\r
+                        .setConditionMatcher(ImmutableList.of(new ConditionMatcherBuilder()\r
+                            .setName(new ConditionMatcherName("m1"))\r
+                            .setCondition(ImmutableList.of(cond1, cond2))\r
+                            .setMatchType(MatchType.Any)\r
+                            .build()))\r
+                        .build())\r
+                    .setProviderMatchers(new ProviderMatchersBuilder()\r
+                        .setConditionMatcher(ImmutableList.of(new ConditionMatcherBuilder()\r
+                            .setName(new ConditionMatcherName("m2"))\r
+                            .setCondition(ImmutableList.of(cond1, cond2))\r
+                            .setMatchType(MatchType.All)\r
+                            .build()))\r
+                        .build())\r
+                    .build()))\r
+                .build()));\r
+        policyResolver.addTenant(tb.build());\r
+\r
+        PolicyInfo policy = policyResolver.getCurrentPolicy();\r
+        List<ConditionName> ep1c = endpointManager.getCondsForEndpoint(ep1);\r
+        ConditionGroup cg1 = \r
+                policy.getEgCondGroup(new EgKey(tb.getId(), \r
+                                                ep1.getEndpointGroup()),\r
+                                      ep1c);\r
+        List<ConditionName> ep2c = endpointManager.getCondsForEndpoint(ep2);\r
+        ConditionGroup cg2 = \r
+                policy.getEgCondGroup(new EgKey(tb.getId(), \r
+                                                ep2.getEndpointGroup()),\r
+                                      ep2c);\r
+        int cg1Id = OrdinalFactory.getCondGroupOrdinal(cg1);\r
+        int cg2Id = OrdinalFactory.getCondGroupOrdinal(cg2);\r
+        int eg1Id = OrdinalFactory.getContextOrdinal(ep1.getTenant(),\r
+                                                    ep1.getEndpointGroup());\r
+        int eg2Id = OrdinalFactory.getContextOrdinal(ep1.getTenant(),\r
+                                                    ep2.getEndpointGroup());\r
+\r
+        assertNotEquals(cg1Id, cg2Id);\r
+\r
+        MatchBuilder mb = new MatchBuilder();\r
+        FlowUtils.addNxRegMatch(mb, \r
+                                RegMatch.of(NxmNxReg0.class, Long.valueOf(eg1Id)),\r
+                                RegMatch.of(NxmNxReg1.class, Long.valueOf(cg1Id)),\r
+                                RegMatch.of(NxmNxReg2.class, Long.valueOf(eg2Id)),\r
+                                RegMatch.of(NxmNxReg3.class, Long.valueOf(cg2Id)));\r
+        GeneralAugMatchNodesNodeTableFlow m1 =\r
+                mb.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);\r
+        FlowUtils.addNxRegMatch(mb, \r
+                                RegMatch.of(NxmNxReg0.class, Long.valueOf(eg2Id)),\r
+                                RegMatch.of(NxmNxReg1.class, Long.valueOf(cg2Id)),\r
+                                RegMatch.of(NxmNxReg2.class, Long.valueOf(eg1Id)),\r
+                                RegMatch.of(NxmNxReg3.class, Long.valueOf(cg1Id)));\r
+        GeneralAugMatchNodesNodeTableFlow m2 =\r
+                mb.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class);\r
+        int count = 0;\r
+        FlowMap fm = dosync(null);\r
+        assertEquals(6, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 3).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getMatch() != null &&\r
+                f.getMatch().getEthernetMatch() != null) {\r
+                count++;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+        fm = dosync(flowMap);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 3).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 3).getFlow().size());\r
+    }\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index 60747e5..c380516
-/*
- * 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.flow;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
-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.Ipv6Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-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.ofoverlay.rev140528.OfOverlayContext;
-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.match.layer._3.match.ArpMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-
-import static org.junit.Assert.*;
-
-import static org.mockito.Matchers.*;
-
-import static org.mockito.Mockito.*;
-
-public class PortSecurityTest extends FlowTableTest {
-    protected static final Logger LOG =
-            LoggerFactory.getLogger(PortSecurityTest.class);
-
-    @Override
-    @Before
-    public void setup() throws Exception {
-        initCtx();
-        table = new PortSecurity(ctx);
-        super.setup();
-    }
-
-    @Test
-    public void testDefaultDeny() throws Exception {
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, times(4)).put(eq(LogicalDatastoreType.CONFIGURATION),
-                                Matchers.<InstanceIdentifier<Flow>>any(),
-                                ac.capture(), anyBoolean());
-        int count = 0;
-
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            Long etherType = null;
-            if (f.getMatch() != null) {
-                etherType = f.getMatch().getEthernetMatch()
-                        .getEthernetType().getType().getValue();
-            }
-            if (f.getMatch() == null ||
-                FlowUtils.ARP.equals(etherType) ||
-                FlowUtils.IPv4.equals(etherType) ||
-                FlowUtils.IPv6.equals(etherType)) {
-                count += 1;
-                assertEquals(FlowUtils.dropInstructions(),
-                             f.getInstructions());
-            }
-        }
-        assertEquals(4, count);
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class),
-                               Matchers.<InstanceIdentifier<Flow>>any(),
-                               any(Flow.class), anyBoolean());
-    }
-
-    @Test
-    public void testNonLocalAllow() throws Exception {
-        switchManager
-            .addSwitch(new NodeId("openflow:1"),
-                       new NodeConnectorId("openflow:1:1"),
-                       ImmutableSet.of(new NodeConnectorId("openflow:1:2")),
-                       null);
-
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        Set<String> ncs = ImmutableSet.of("openflow:1:1", "openflow:1:2");
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getMatch() != null && f.getMatch().getInPort() != null &&
-                ncs.contains(f.getMatch().getInPort().getValue())) {
-                assertEquals(f.getInstructions(),
-                             FlowUtils.gotoTableInstructions((short)(table.getTableId()+1)));
-                count += 1;
-            }
-        }
-        assertEquals(2, count);
-
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class),
-                               Matchers.<InstanceIdentifier<Flow>>any(),
-                               any(Flow.class), anyBoolean());
-    }
-
-    @Test
-    public void testL2() throws Exception {
-        List<L3Address> l3 = Collections.emptyList();
-        Endpoint ep = localEP()
-            .setL3Address(l3)
-            .build();
-
-        endpointManager.addEndpoint(ep);
-
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getMatch() != null &&
-                f.getMatch().getEthernetMatch() != null &&
-                f.getMatch().getEthernetMatch().getEthernetSource() != null &&
-                Objects.equals(ep.getMacAddress(),
-                               f.getMatch().getEthernetMatch()
-                                   .getEthernetSource().getAddress()) &&
-                Objects.equals(ep.getAugmentation(OfOverlayContext.class).getNodeConnectorId(),
-                               f.getMatch().getInPort())) {
-                count += 1;
-                assertEquals(FlowUtils.gotoTableInstructions((short)(table.getTableId()+1)),
-                             f.getInstructions());
-            }
-        }
-        assertEquals(2, count);
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class),
-                               Matchers.<InstanceIdentifier<Flow>>any(),
-                               any(Flow.class), anyBoolean());
-    }
-
-    @Test
-    public void testL3() throws Exception {
-        Endpoint ep = localEP()
-            .setL3Address(ImmutableList.of(new L3AddressBuilder()
-                .setIpAddress(new IpAddress(new Ipv4Address("10.10.10.10")))
-                .build(),
-                new L3AddressBuilder()
-                .setIpAddress(new IpAddress(new Ipv6Address("2001:db8:85a3::8a2e:370:7334")))
-                .build()))
-            .build();
-
-        endpointManager.addEndpoint(ep);
-
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, atLeastOnce()).put(eq(LogicalDatastoreType.CONFIGURATION),
-                                     Matchers.<InstanceIdentifier<Flow>>any(),
-                                     ac.capture(), anyBoolean());
-
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getMatch() != null &&
-                Objects.equals(ep.getAugmentation(OfOverlayContext.class).getNodeConnectorId(),
-                               f.getMatch().getInPort()) &&
-                ((f.getMatch().getLayer3Match() != null &&
-                  f.getMatch().getLayer3Match() instanceof Ipv4Match &&
-                  ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Source() != null &&
-                  Objects.equals(ep.getL3Address().get(0).getIpAddress().getIpv4Address().getValue(),
-                          ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Source().getValue().split("/")[0])) ||
-                 (f.getMatch().getLayer3Match() != null &&
-                         f.getMatch().getLayer3Match() instanceof Ipv4Match &&
-                         ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Destination() != null &&
-                  Objects.equals("255.255.255.255",
-                          ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Destination().getValue().split("/")[0]))     ||
-                 (f.getMatch().getLayer3Match() != null &&
-                  f.getMatch().getLayer3Match() instanceof ArpMatch &&
-                  Objects.equals(ep.getL3Address().get(0).getIpAddress().getIpv4Address().getValue(),
-                                 ((ArpMatch)f.getMatch().getLayer3Match()).getArpSourceTransportAddress().getValue().split("/")[0])) ||
-                 (f.getMatch().getLayer3Match() != null &&
-                  f.getMatch().getLayer3Match() instanceof Ipv6Match &&
-                  Objects.equals(ep.getL3Address().get(1).getIpAddress().getIpv6Address().getValue(),
-                                 ((Ipv6Match)f.getMatch().getLayer3Match()).getIpv6Source().getValue().split("/")[0])))) {
-                count += 1;
-                assertEquals(FlowUtils.gotoTableInstructions((short)(table.getTableId()+1)),
-                             f.getInstructions());
-            }
-        }
-        assertEquals(4, count);
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class),
-                               Matchers.<InstanceIdentifier<Flow>>any(),
-                               any(Flow.class), anyBoolean());
-    }
-}
+/*\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 java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Objects;\r
+import java.util.Set;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;\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.flow.inventory.rev130819.tables.table.Flow;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;\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.ofoverlay.rev140528.OfOverlayContext;\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.ArpMatch;\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.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.google.common.collect.ImmutableList;\r
+import com.google.common.collect.ImmutableSet;\r
+\r
+import static org.junit.Assert.*;\r
+\r
+public class PortSecurityTest extends FlowTableTest {\r
+    protected static final Logger LOG =\r
+            LoggerFactory.getLogger(PortSecurityTest.class);\r
+\r
+    @Override\r
+    @Before\r
+    public void setup() throws Exception {\r
+        initCtx();\r
+        table = new PortSecurity(ctx);\r
+        super.setup();\r
+    }\r
+\r
+    @Test\r
+    public void testDefaultDeny() throws Exception {\r
+        FlowMap fm = dosync(null);\r
+        int count = 0;\r
+        Map<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 0).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            Long etherType = null;\r
+            if (f.getMatch() != null) {\r
+                etherType = f.getMatch().getEthernetMatch().getEthernetType().getType().getValue();\r
+            }\r
+            if (f.getMatch() == null || FlowUtils.ARP.equals(etherType) || FlowUtils.IPv4.equals(etherType)\r
+                    || FlowUtils.IPv6.equals(etherType)) {\r
+                count += 1;\r
+                assertEquals(FlowUtils.dropInstructions(), f.getInstructions());\r
+            }\r
+        }\r
+        assertEquals(4, count);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 0).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testNonLocalAllow() throws Exception {\r
+        switchManager\r
+            .addSwitch(new NodeId("openflow:1"),\r
+                       new NodeConnectorId("openflow:1:1"),\r
+                       ImmutableSet.of(new NodeConnectorId("openflow:1:2")),\r
+                       null);\r
+        FlowMap fm = dosync(null);\r
+        assertNotEquals(0 ,fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        Set<String> ncs = ImmutableSet.of("openflow:1:1", "openflow:1:2");\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 0).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getMatch() != null && f.getMatch().getInPort() != null &&\r
+                ncs.contains(f.getMatch().getInPort().getValue())) {\r
+                assertEquals(f.getInstructions(),\r
+                             FlowUtils.gotoTableInstructions((short)(table.getTableId()+1)));\r
+                count += 1;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 0).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testL2() throws Exception {\r
+        List<L3Address> l3 = Collections.emptyList();\r
+        Endpoint ep = localEP()\r
+            .setL3Address(l3)\r
+            .build();\r
+\r
+        endpointManager.addEndpoint(ep);\r
+\r
+        FlowMap fm = dosync(null);\r
+        assertNotEquals(0 ,fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 0).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getMatch() != null &&\r
+                f.getMatch().getEthernetMatch() != null &&\r
+                f.getMatch().getEthernetMatch().getEthernetSource() != null &&\r
+                Objects.equals(ep.getMacAddress(),\r
+                               f.getMatch().getEthernetMatch()\r
+                                   .getEthernetSource().getAddress()) &&\r
+                Objects.equals(ep.getAugmentation(OfOverlayContext.class).getNodeConnectorId(),\r
+                               f.getMatch().getInPort())) {\r
+                count += 1;\r
+                assertEquals(FlowUtils.gotoTableInstructions((short)(table.getTableId()+1)),\r
+                             f.getInstructions());\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 0).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testL3() throws Exception {\r
+        Endpoint ep = localEP()\r
+            .setL3Address(ImmutableList.of(new L3AddressBuilder()\r
+                .setIpAddress(new IpAddress(new Ipv4Address("10.10.10.10")))\r
+                .build(),\r
+                new L3AddressBuilder()\r
+                .setIpAddress(new IpAddress(new Ipv6Address("2001:db8:85a3::8a2e:370:7334")))\r
+                .build()))\r
+            .build();\r
+\r
+        endpointManager.addEndpoint(ep);\r
+\r
+        FlowMap fm = dosync(null);\r
+        assertNotEquals(0 ,fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 0).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getMatch() != null &&\r
+                Objects.equals(ep.getAugmentation(OfOverlayContext.class).getNodeConnectorId(),\r
+                               f.getMatch().getInPort()) &&\r
+                ((f.getMatch().getLayer3Match() != null &&\r
+                  f.getMatch().getLayer3Match() instanceof Ipv4Match &&\r
+                  ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Source() != null &&\r
+                  Objects.equals(ep.getL3Address().get(0).getIpAddress().getIpv4Address().getValue(),\r
+                          ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Source().getValue().split("/")[0])) ||\r
+                 (f.getMatch().getLayer3Match() != null &&\r
+                         f.getMatch().getLayer3Match() instanceof Ipv4Match &&\r
+                         ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Destination() != null &&\r
+                  Objects.equals("255.255.255.255",\r
+                          ((Ipv4Match)f.getMatch().getLayer3Match()).getIpv4Destination().getValue().split("/")[0]))     ||\r
+                 (f.getMatch().getLayer3Match() != null &&\r
+                  f.getMatch().getLayer3Match() instanceof ArpMatch &&\r
+                  Objects.equals(ep.getL3Address().get(0).getIpAddress().getIpv4Address().getValue(),\r
+                                 ((ArpMatch)f.getMatch().getLayer3Match()).getArpSourceTransportAddress().getValue().split("/")[0])) ||\r
+                 (f.getMatch().getLayer3Match() != null &&\r
+                  f.getMatch().getLayer3Match() instanceof Ipv6Match &&\r
+                  Objects.equals(ep.getL3Address().get(1).getIpAddress().getIpv6Address().getValue(),\r
+                                 ((Ipv6Match)f.getMatch().getLayer3Match()).getIpv6Source().getValue().split("/")[0])))) {\r
+                count += 1;\r
+                assertEquals(FlowUtils.gotoTableInstructions((short)(table.getTableId()+1)),\r
+                             f.getInstructions());\r
+            }\r
+        }\r
+        assertEquals(4, count);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 0).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 0).getFlow().size());\r
+    }\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index ef71152..a1558aa
-/*
- * 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.flow;
-
-import java.math.BigInteger;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable.FlowCtx;
-import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;
-import org.opendaylight.groupbasedpolicy.resolver.EgKey;
-import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
-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;
-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.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.junit.Assert.*;
-
-import static org.mockito.Matchers.*;
-
-import static org.mockito.Mockito.*;
-
-public class SourceMapperTest extends FlowTableTest {
-    protected static final Logger LOG = 
-            LoggerFactory.getLogger(SourceMapperTest.class);
-    @Before
-    public void setup() throws Exception {
-        initCtx();
-        table = new SourceMapper(ctx);
-        super.setup();
-    }
-    
-    @Test
-    public void testNoPolicy() throws Exception {
-        endpointManager.addEndpoint(localEP().build());
-        ReadWriteTransaction t = dosync(null);
-        verify(t, times(1)).put(any(LogicalDatastoreType.class), 
-                                Matchers.<InstanceIdentifier<Flow>>any(), 
-                                any(Flow.class), anyBoolean());
-    }
-    
-    @Test
-    public void testMap() throws Exception {
-        Endpoint ep = localEP().build();
-        endpointManager.addEndpoint(ep);
-        policyResolver.addTenant(baseTenant().build());
-        
-        ReadWriteTransaction t = dosync(null);
-        ArgumentCaptor<Flow> ac = ArgumentCaptor.forClass(Flow.class);
-        verify(t, times(2)).put(eq(LogicalDatastoreType.CONFIGURATION), 
-                                Matchers.<InstanceIdentifier<Flow>>any(),
-                                ac.capture(), anyBoolean());
-
-        int count = 0;
-        HashMap<String, FlowCtx> flowMap = new HashMap<>();
-        for (Flow f : ac.getAllValues()) {
-            flowMap.put(f.getId().getValue(), new FlowCtx(f));
-            if (f.getMatch() == null) {
-                assertEquals(FlowUtils.dropInstructions(),
-                             f.getInstructions());
-                count += 1;
-            } else if (Objects.equals(ep.getMacAddress(),
-                               f.getMatch().getEthernetMatch()
-                                   .getEthernetSource().getAddress())) {
-                PolicyInfo pi = policyResolver.getCurrentPolicy();
-                List<ConditionName> cset = endpointManager.getCondsForEndpoint(ep);
-                ConditionGroup cg = pi.getEgCondGroup(new EgKey(tid, eg), cset);
-                
-                Instruction ins = f.getInstructions().getInstruction().get(0);
-                assertTrue(ins.getInstruction() instanceof ApplyActionsCase);
-                List<Action> actions = ((ApplyActionsCase)ins.getInstruction()).getApplyActions().getAction();
-                int v = policyManager.getContextOrdinal(tid, eg);
-                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg0.class, 
-                                                       BigInteger.valueOf(v)),
-                             actions.get(0).getAction());
-                v = policyManager.getCondGroupOrdinal(cg);
-                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg1.class, 
-                                                       BigInteger.valueOf(v)),
-                             actions.get(1).getAction());
-                v = policyManager.getContextOrdinal(tid, bd);
-                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg4.class, 
-                                                       BigInteger.valueOf(v)),
-                             actions.get(2).getAction());
-                v = policyManager.getContextOrdinal(tid, fd);
-                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg5.class, 
-                                                       BigInteger.valueOf(v)),
-                             actions.get(3).getAction());
-                v = policyManager.getContextOrdinal(tid, l3c);
-                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg6.class, 
-                                                       BigInteger.valueOf(v)),
-                             actions.get(4).getAction());
-                count += 1;
-            }
-        }
-        assertEquals(2, count);
-
-        t = dosync(flowMap);
-        verify(t, never()).put(any(LogicalDatastoreType.class), 
-                               Matchers.<InstanceIdentifier<Flow>>any(), 
-                               any(Flow.class), anyBoolean());
-    }
-    
-}
+/*\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 java.math.BigInteger;\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.Test;\r
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;\r
+import org.opendaylight.groupbasedpolicy.resolver.ConditionGroup;\r
+import org.opendaylight.groupbasedpolicy.resolver.EgKey;\r
+import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;\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.list.Instruction;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;\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.NxmNxReg1;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import static org.junit.Assert.*;\r
+\r
+public class SourceMapperTest extends FlowTableTest {\r
+\r
+    protected static final Logger LOG = LoggerFactory.getLogger(SourceMapperTest.class);\r
+\r
+    @Before\r
+    public void setup() throws Exception {\r
+        initCtx();\r
+        table = new SourceMapper(ctx);\r
+        super.setup();\r
+    }\r
+\r
+    @Test\r
+    public void testNoPolicy() throws Exception {\r
+        endpointManager.addEndpoint(localEP().build());\r
+        FlowMap fm = dosync(null);\r
+        assertEquals(1, fm.getTableForNode(nodeId, (short) 1).getFlow().size());\r
+    }\r
+\r
+    @Test\r
+    public void testMap() throws Exception {\r
+        Endpoint ep = localEP().build();\r
+        endpointManager.addEndpoint(ep);\r
+        policyResolver.addTenant(baseTenant().build());\r
+\r
+        FlowMap fm = dosync(null);\r
+        assertEquals(2, fm.getTableForNode(nodeId, (short) 1).getFlow().size());\r
+\r
+        int count = 0;\r
+        HashMap<String, Flow> flowMap = new HashMap<>();\r
+        for (Flow f : fm.getTableForNode(nodeId, (short) 1).getFlow()) {\r
+            flowMap.put(f.getId().getValue(), f);\r
+            if (f.getMatch() == null) {\r
+                assertEquals(FlowUtils.dropInstructions(), f.getInstructions());\r
+                count += 1;\r
+            } else if (Objects.equals(ep.getMacAddress(), f.getMatch()\r
+                .getEthernetMatch()\r
+                .getEthernetSource()\r
+                .getAddress())) {\r
+                PolicyInfo pi = policyResolver.getCurrentPolicy();\r
+                List<ConditionName> cset = endpointManager.getCondsForEndpoint(ep);\r
+                ConditionGroup cg = pi.getEgCondGroup(new EgKey(tid, eg), cset);\r
+\r
+                Instruction ins = f.getInstructions().getInstruction().get(0);\r
+                assertTrue(ins.getInstruction() instanceof ApplyActionsCase);\r
+                List<Action> actions = ((ApplyActionsCase) ins.getInstruction()).getApplyActions().getAction();\r
+                NetworkDomainId networkContainement = policyResolver.getTenant(tid)\r
+                    .getEndpointGroup(eg)\r
+                    .getNetworkDomain();\r
+                int v = OrdinalFactory.getContextOrdinal(ep, networkContainement);\r
+                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(v)), actions.get(0)\r
+                    .getAction());\r
+                v = OrdinalFactory.getCondGroupOrdinal(cg);\r
+                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(v)), actions.get(1)\r
+                    .getAction());\r
+                v = OrdinalFactory.getContextOrdinal(tid, bd);\r
+                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(v)), actions.get(2)\r
+                    .getAction());\r
+                v = OrdinalFactory.getContextOrdinal(tid, fd);\r
+                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(v)), actions.get(3)\r
+                    .getAction());\r
+                v = OrdinalFactory.getContextOrdinal(tid, l3c);\r
+                assertEquals(FlowUtils.nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(v)), actions.get(4)\r
+                    .getAction());\r
+                count += 1;\r
+            }\r
+        }\r
+        assertEquals(2, count);\r
+        int numberOfFlows = fm.getTableForNode(nodeId, (short) 1).getFlow().size();\r
+        fm = dosync(flowMap);\r
+        assertEquals(numberOfFlows, fm.getTableForNode(nodeId, (short) 1).getFlow().size());\r
+    }\r
+\r
+}\r