Bug 3244 - SFC Improvements for distributed classifier, robustness 06/22406/3
authorKeith Burns (alagalah) <alagalah@gmail.com>
Thu, 4 Jun 2015 05:18:50 +0000 (22:18 -0700)
committerKeith Burns <alagalah@gmail.com>
Fri, 12 Jun 2015 20:30:09 +0000 (20:30 +0000)
- Added specific ChainActionFlow class for handling of chain specific flows.
- Added simultaneous multiencap support (VXLAN, VXLANGPE)
- Ensure non-symmetric chain, path. Not supported Li
- Added setting of C1/C2 in ExternalTable per destination
- "visited" pairs fixed for assymetry

Change-Id: Icf9118dec65a8d1e57a24d5702c9334b3b33aea3
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
24 files changed:
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/AbstractTunnelType.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanGpeTunnelType.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanTunnelType.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/EndpointHelper.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/InventoryHelper.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/OvsdbHelper.java
neutron-ovsdb/src/test/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TunnelTypeTest.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ChainActionFlows.java [new file with mode: 0644]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowIdUtils.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/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/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/node/SwitchManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Action.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/AllowAction.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ChainAction.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcDataStoreHelper.java [deleted file]
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcIidFactory.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcNshHeader.java [new file with mode: 0644]

index 15825c508acd1d55bd3c868b496c21f23bc02933..84dec31fd97abd0cdd7c8415790f447cdd12df8f 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
 
 public abstract class AbstractTunnelType {
+    protected static final String DESTPORT_KEY = "dst_port";
     protected static final String REMOTE_IP_KEY = "remote_ip";
     protected static final String REMOTE_IP_VALUE = "flow";
     protected static final String VNID_KEY = "key";
@@ -63,6 +64,19 @@ public abstract class AbstractTunnelType {
         return false;
     }
 
+    protected String getDestPort(OvsdbTerminationPointAugmentation tpAugmentation) {
+        List<Options> options = tpAugmentation.getOptions();
+        if (options == null) {
+            return null;
+        }
+        for (Options opt: options) {
+            if (DESTPORT_KEY.equals(opt.getOption())) {
+                return opt.getValue();
+            }
+        }
+        return null;
+    }
+
     /**
      * Return the {@link List<Options>} valid for this tunnel type
      *
index b8f6ce6afc979e0c0bc33a096ab61ee56af6a5cb..a078e2c6ab52113a10b8b6660186a44d47fa2143 100755 (executable)
@@ -8,7 +8,29 @@
 
 package org.opendaylight.groupbasedpolicy.neutron.ovsdb;
 
-import com.google.common.base.Optional;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.getProviderMapping;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.processNodeNotification;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.lookupEndpoint;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointRemoveLocation;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointWithLocation;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.checkOfOverlayConfig;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeConnectorIdString;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeIdString;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.removeTunnelsOfOverlayConfig;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.updateOfOverlayConfig;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronHelper.getEpKeyFromNeutronMapper;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.createTunnelPort;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getManagerNode;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbBridgeFromTerminationPoint;
+import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getTopologyNode;
+import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map.Entry;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
@@ -37,28 +59,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map.Entry;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.getProviderMapping;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.NodeDataChangeListener.processNodeNotification;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.lookupEndpoint;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointRemoveLocation;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointWithLocation;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.checkOfOverlayConfig;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeConnectorIdString;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeIdString;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.removeTunnelsOfOverlayConfig;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.updateOfOverlayConfig;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronHelper.getEpKeyFromNeutronMapper;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.createTunnelPort;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getManagerNode;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbBridgeFromTerminationPoint;
-import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getTopologyNode;
-import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
+import com.google.common.base.Optional;
 
 public class TerminationPointDataChangeListener implements DataChangeListener, AutoCloseable {
 
@@ -84,8 +85,8 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
 
     private List<AbstractTunnelType> createSupportedTunnelsList() {
         List<AbstractTunnelType> required = new ArrayList<AbstractTunnelType>();
-        // required.add(new VxlanGpeTunnelType());
         required.add(new VxlanTunnelType());
+        required.add(new VxlanGpeTunnelType());
         return Collections.unmodifiableList(required);
     }
 
@@ -130,8 +131,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
             if (old instanceof OvsdbTerminationPointAugmentation) {
                 OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation) old;
                 @SuppressWarnings("unchecked")
-                InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid =
-                        (InstanceIdentifier<OvsdbTerminationPointAugmentation>) iid;
+                InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid = (InstanceIdentifier<OvsdbTerminationPointAugmentation>) iid;
                 OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
                 if (ovsdbBridge != null) {
                     processRemovedTp(ovsdbBridge, ovsdbTp, ovsdbTpIid);
@@ -213,13 +213,13 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
 
         /*
          * Check if Neutron External port was announed in Node before TerminationPoint it refers to
-         * was actually instantiated. This may or may not have external information in the future, hence
+         * was actually instantiated. This may or may not have external information in the future,
+         * hence
          * not process as IF/ELSE externalID.
          */
         ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
         Optional<Node> node = readFromDs(LogicalDatastoreType.OPERATIONAL, nodeIid, transaction);
-        if (node.isPresent()
-                && node.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
+        if (node.isPresent() && node.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
             OvsdbNodeAugmentation ovsdbNodeAug = node.get().getAugmentation(OvsdbNodeAugmentation.class);
             if (getProviderMapping(ovsdbNodeAug) != null) {
                 processNodeNotification(ovsdbNodeAug);
@@ -232,8 +232,9 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
          * In that case, we need to update the Inventory Node's OfOverlay
          * augmentation with missing information
          */
-        if (isTunnelPort(ovsdbTp, requiredTunnelTypes)) {
-            updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, requiredTunnelTypes, dataBroker);
+        AbstractTunnelType tunnel = getTunnelType(ovsdbTp, requiredTunnelTypes);
+        if (tunnel != null) {
+            updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, tunnel, dataBroker);
         }
         if (externalId != null) {
             ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
@@ -250,11 +251,13 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
      * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
      * @param ovsdbTpIid termination point's IID {@link InstanceIdentifier}
      */
-    private void processRemovedTp(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp, InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid) {
+    private void processRemovedTp(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp,
+            InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid) {
 
         checkNotNull(ovsdbBridge);
         if (ovsdbBridge.getBridgeName().getValue().equals(ovsdbTp.getName())) {
-            LOG.debug("Termination Point {} same as Bridge {}. Not processing.", ovsdbTp.getName(), ovsdbBridge.getBridgeName().getValue());
+            LOG.debug("Termination Point {} same as Bridge {}. Not processing.", ovsdbTp.getName(),
+                    ovsdbBridge.getBridgeName().getValue());
             return;
         }
 
@@ -276,7 +279,7 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
      *
      * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
      */
-    private void deleteLocationForTp(OvsdbTerminationPointAugmentation ovsdbTp){
+    private void deleteLocationForTp(OvsdbTerminationPointAugmentation ovsdbTp) {
         String externalId = getNeutronPortUuid(ovsdbTp);
         if (externalId != null) {
             EndpointKey epKey = getEpKeyFromNeutronMapper(new Uuid(externalId), dataBroker);
@@ -288,7 +291,9 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
             Endpoint ep = lookupEndpoint(epKey, readOnlyTransaction);
             readOnlyTransaction.close();
             if (ep == null) {
-                LOG.warn("TerminationPoint {} with external ID {} is in Neutron Map, but corresponding Endpoint {} isn't in Endpoint Repository.", ovsdbTp, externalId, epKey);
+                LOG.warn(
+                        "TerminationPoint {} with external ID {} is in Neutron Map, but corresponding Endpoint {} isn't in Endpoint Repository.",
+                        ovsdbTp, externalId, epKey);
                 return;
             }
             updateEndpointRemoveLocation(ep, dataBroker.newReadWriteTransaction());
@@ -298,11 +303,32 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A
     }
 
     /**
+     * Check to see if the {@link OvsdbTerminationPointAugmentation} is also a Tunnel port that we
+     * care about.
+     *
+     * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     * @param requiredTunnelTypes {@link List} of tunnel types
+     */
+    private static AbstractTunnelType getTunnelType(OvsdbTerminationPointAugmentation ovsdbTp,
+            List<AbstractTunnelType> requiredTunnelTypes) {
+        if (ovsdbTp.getInterfaceType() != null) {
+            for (AbstractTunnelType tunnelType : requiredTunnelTypes) {
+                if (tunnelType.isValidTunnelPort(ovsdbTp)) {
+                    return tunnelType;
+                }
+            }
+        }
+        return null;
+    }
+
+    /*
      * Check to see if the {@link OvsdbTerminationPointAugmentation}
      * is also a Tunnel port that we care about.
      *
      * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+     *
      * @param requiredTunnelTypes {@link List} of tunnel types
+     *
      * @return true if it's a required tunnel port, false if it isn't
      */
     private boolean isTunnelPort(OvsdbTerminationPointAugmentation ovsdbTp, List<AbstractTunnelType> requiredTunnelTypes) {
index e3e5d96dbc3f2e93ad3fade4d35868fa0a79da51..0408db766d93c558b9e47198121e57a2c1e10a58 100644 (file)
@@ -21,6 +21,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
 
 public class VxlanGpeTunnelType extends AbstractTunnelType {
+
+    private static final String VXLAN_GPE_TUNNEL_PREFIX = "vxlangpe-";
+    private static final Integer VXLAN_GPE_PORT_NUMBER = 6633;
+
     private static final String NSH_NSI_KEY = "nsi";
     private static final String NSH_NSI_VALUE = "flow";
     private static final String NSH_NSP_KEY = "nsp";
@@ -33,10 +37,10 @@ public class VxlanGpeTunnelType extends AbstractTunnelType {
     private static final String NSH_NSHC3_VALUE = "flow";
     private static final String NSH_NSHC4_KEY = "nshc4";
     private static final String NSH_NSHC4_VALUE = "flow";
+    private static final String DESTPORT_KEY = "dst_port";
+    private static final String DESTPORT_VALUE = VXLAN_GPE_PORT_NUMBER.toString();
 
-    private static final String VXLAN_GPE_TUNNEL_PREFIX = "vxlangpe-";
 
-    private static final Integer VXLAN_GPE_PORT_NUMBER = 6633;
        private final PortNumber udpTunnelPort;
     private final List<Options> optionsList;
     private static final Class<? extends TunnelTypeBase> tunnelType = TunnelTypeVxlanGpe.class;
@@ -57,6 +61,7 @@ public class VxlanGpeTunnelType extends AbstractTunnelType {
         opts.put(NSH_NSHC2_KEY, NSH_NSHC2_VALUE);
         opts.put(NSH_NSHC3_KEY, NSH_NSHC3_VALUE);
         opts.put(NSH_NSHC4_KEY, NSH_NSHC4_VALUE);
+        opts.put(DESTPORT_KEY, DESTPORT_VALUE);
         optsMap = Collections.unmodifiableMap(opts);
     }
 
@@ -93,7 +98,8 @@ public class VxlanGpeTunnelType extends AbstractTunnelType {
        @Override
     public boolean isValidTunnelPort(OvsdbTerminationPointAugmentation tpAugmentation) {
         if (hasTunnelOptions(tpAugmentation, optsMap)
-                && InterfaceTypeVxlan.class.equals(tpAugmentation.getInterfaceType())) {
+                && InterfaceTypeVxlan.class.equals(tpAugmentation.getInterfaceType())
+                && getDestPort(tpAugmentation).equals(VXLAN_GPE_PORT_NUMBER.toString())) {
             return true;
         }
         return false;
index fcf9882242871747c578efbd41d571c1555cd5a9..c3e7b8756f41af99d212eddfbe400b7dc43ba0ef 100644 (file)
@@ -73,7 +73,9 @@ public class VxlanTunnelType extends AbstractTunnelType {
        @Override
     public boolean isValidTunnelPort(OvsdbTerminationPointAugmentation tpAugmentation) {
         if (hasTunnelOptions(tpAugmentation, optsMap)
-                && InterfaceTypeVxlan.class.equals(tpAugmentation.getInterfaceType())) {
+                && InterfaceTypeVxlan.class.equals(tpAugmentation.getInterfaceType())
+                && (getDestPort(tpAugmentation) == null
+                || getDestPort(tpAugmentation).equals(VXLAN_PORT_NUMBER.toString()))) {
             return true;
         }
         return false;
index 58a709ace34e882cc396ff79c39accc56fc60e81..7df6a65aa1f1df2ea8d1d894b6d2f944dc3481a9 100755 (executable)
@@ -7,45 +7,26 @@
  */
 package org.opendaylight.groupbasedpolicy.neutron.ovsdb.util;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
+import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
+import static org.opendaylight.groupbasedpolicy.util.IidFactory.endpointIid;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 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.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
-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.SubnetId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInputBuilder;
-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.EndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L2Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.unregister.endpoint.input.L3Builder;
 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.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
-import static org.opendaylight.groupbasedpolicy.util.IidFactory.endpointIid;
+import com.google.common.base.Optional;
 
 
 public class EndpointHelper {
index 76545d13a65d9f08c96bb62d02465ea311fbbecf..7498c61cdc87545f6292e3d6284fffa320c992b8 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015 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,
@@ -8,6 +8,8 @@
 package org.opendaylight.groupbasedpolicy.neutron.ovsdb.util;
 
 import com.google.common.base.Optional;
+import java.util.HashSet;
+import java.util.Set;
 import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
@@ -46,6 +48,7 @@ import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
 import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.submitToDs;
 
 public class InventoryHelper {
+
     private static final Logger LOG = LoggerFactory.getLogger(InventoryHelper.class);
     private static final String HEX = "0x";
 
@@ -57,20 +60,16 @@ public class InventoryHelper {
      */
     public static Long getLongFromDpid(String dpid) {
         String[] addressInBytes = dpid.split(":");
-        Long address =
-                (Long.decode(HEX + addressInBytes[2]) << 40) |
-                (Long.decode(HEX + addressInBytes[3]) << 32) |
-                (Long.decode(HEX + addressInBytes[4]) << 24) |
-                (Long.decode(HEX + addressInBytes[5]) << 16) |
-                (Long.decode(HEX + addressInBytes[6]) << 8 ) |
-                (Long.decode(HEX + addressInBytes[7]));
+        Long address = (Long.decode(HEX + addressInBytes[2]) << 40) | (Long.decode(HEX + addressInBytes[3]) << 32)
+                | (Long.decode(HEX + addressInBytes[4]) << 24) | (Long.decode(HEX + addressInBytes[5]) << 16)
+                | (Long.decode(HEX + addressInBytes[6]) << 8) | (Long.decode(HEX + addressInBytes[7]));
         return address;
     }
 
-    private static final Long MAX_OF_PORT=65534L;
+    private static final Long MAX_OF_PORT = 65534L;
+
     /**
-     * Construct a String that can be used to create a
-     * {@link NodeId}.
+     * Construct a String that can be used to create a {@link NodeId}.
      * The String is constructed by getting the Datapath ID from the OVSDB bridge
      * augmentation, converting that to a Long, and prepending it with the
      * "openflow:" prefix.
@@ -91,8 +90,8 @@ public class InventoryHelper {
         }
         Long macLong = getLongFromDpid(ovsdbBridge.getDatapathId().getValue());
         String nodeIdString = "openflow:" + String.valueOf(macLong);
-        if(StringUtils.countMatches(nodeIdString, ":") != 1) {
-            LOG.error("{} is not correct format for NodeId.",nodeIdString);
+        if (StringUtils.countMatches(nodeIdString, ":") != 1) {
+            LOG.error("{} is not correct format for NodeId.", nodeIdString);
             return null;
         }
         return nodeIdString;
@@ -109,21 +108,17 @@ public class InventoryHelper {
      * @return String representation of the Inventory NodeConnectorId, null if it fails
      */
     public static String getInventoryNodeConnectorIdString(String inventoryNodeId,
-                       OvsdbTerminationPointAugmentation ovsdbTp,
-                       InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid,
-                       DataBroker dataBroker) {
+            OvsdbTerminationPointAugmentation ovsdbTp, InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid,
+            DataBroker dataBroker) {
         Long ofport = null;
-        if (ovsdbTp.getOfport() != null && ovsdbTp.getOfport()>MAX_OF_PORT) {
-            LOG.debug("Invalid OpenFlow port {} for {}",ovsdbTp.getOfport(), ovsdbTp);
+        if (ovsdbTp.getOfport() != null && ovsdbTp.getOfport() > MAX_OF_PORT) {
+            LOG.debug("Invalid OpenFlow port {} for {}", ovsdbTp.getOfport(), ovsdbTp);
             return null;
         }
         if (ovsdbTp.getOfport() == null) {
-            OvsdbTerminationPointAugmentation readOvsdbTp =
-                    getOvsdbTerminationPoint(tpIid, dataBroker);
-            if (readOvsdbTp == null
-                    || readOvsdbTp.getOfport() == null
-                    || readOvsdbTp.getOfport() >MAX_OF_PORT) {
-                LOG.debug("Couldn't get OpenFlow port for {}",ovsdbTp);
+            OvsdbTerminationPointAugmentation readOvsdbTp = getOvsdbTerminationPoint(tpIid, dataBroker);
+            if (readOvsdbTp == null || readOvsdbTp.getOfport() == null || readOvsdbTp.getOfport() > MAX_OF_PORT) {
+                LOG.debug("Couldn't get OpenFlow port for {}", ovsdbTp);
                 return null;
             }
             ofport = readOvsdbTp.getOfport();
@@ -132,8 +127,8 @@ public class InventoryHelper {
         }
         String nodeConnectorIdString = inventoryNodeId + ":" + String.valueOf(ofport);
 
-        if(StringUtils.countMatches(nodeConnectorIdString, ":") != 2) {
-            LOG.error("{} is not correct format for NodeConnectorId.",nodeConnectorIdString);
+        if (StringUtils.countMatches(nodeConnectorIdString, ":") != 2) {
+            LOG.error("{} is not correct format for NodeConnectorId.", nodeConnectorIdString);
             return null;
         }
         return nodeConnectorIdString;
@@ -146,11 +141,11 @@ public class InventoryHelper {
      *
      * @return true if tunnel types are present, false otherwise
      */
-    public static boolean checkOfOverlayConfig(String nodeIdString,
-                       List<AbstractTunnelType> requiredTunnelTypes, DataBroker dataBroker) {
+    public static boolean checkOfOverlayConfig(String nodeIdString, List<AbstractTunnelType> requiredTunnelTypes,
+            DataBroker dataBroker) {
         OfOverlayNodeConfig config = getOfOverlayConfig(nodeIdString, dataBroker);
         if (config == null || config.getTunnel() == null) {
-            LOG.debug("No OfOverlay config for {}",nodeIdString);
+            LOG.debug("No OfOverlay config for {}", nodeIdString);
             return false;
         }
 
@@ -158,9 +153,9 @@ public class InventoryHelper {
          * See if the OfOverlayNodeConfig has the
          * tunnel type information.
          */
-        for (AbstractTunnelType tunnelType: requiredTunnelTypes) {
+        for (AbstractTunnelType tunnelType : requiredTunnelTypes) {
             boolean tunnelPresent = false;
-            for (Tunnel tunnel: config.getTunnel()) {
+            for (Tunnel tunnel : config.getTunnel()) {
                 if (tunnelType.getTunnelType().equals(tunnel.getTunnelType())) {
                     tunnelPresent = true;
                     break;
@@ -174,120 +169,121 @@ public class InventoryHelper {
     }
 
     public static void addOfOverlayExternalPort(String nodeIdString, NodeConnectorId ncId, DataBroker dataBroker) {
-        InstanceIdentifier<ExternalInterfaces> nodeExternalInterfacesIid = InstanceIdentifier.builder(
-                Nodes.class)
+        InstanceIdentifier<ExternalInterfaces> nodeExternalInterfacesIid = InstanceIdentifier.builder(Nodes.class)
             .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
             .augmentation(OfOverlayNodeConfig.class)
-            .child(ExternalInterfaces.class,new ExternalInterfacesKey(ncId))
+            .child(ExternalInterfaces.class, new ExternalInterfacesKey(ncId))
             .build();
 
-        ExternalInterfaces externalInterfaces = new ExternalInterfacesBuilder()
-                                                .setKey(new ExternalInterfacesKey(ncId))
-                                                .setNodeConnectorId(ncId)
-                                                .build();
+        ExternalInterfaces externalInterfaces = new ExternalInterfacesBuilder().setKey(new ExternalInterfacesKey(ncId))
+            .setNodeConnectorId(ncId)
+            .build();
         WriteTransaction transaction = dataBroker.newReadWriteTransaction();
         transaction.put(LogicalDatastoreType.CONFIGURATION, nodeExternalInterfacesIid, externalInterfaces, true);
         submitToDs(transaction);
-        LOG.trace("Added external interface node connector {} to node {}", ncId.getValue(),nodeIdString);
+        LOG.trace("Added external interface node connector {} to node {}", ncId.getValue(), nodeIdString);
     }
 
     public static OfOverlayNodeConfig getOfOverlayConfig(String nodeIdString, DataBroker dataBroker) {
-        InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
-                Nodes.class)
+        InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(Nodes.class)
             .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
             .augmentation(OfOverlayNodeConfig.class)
             .build();
 
         ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
-        Optional<OfOverlayNodeConfig> overlayConfig = readFromDs(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, transaction );
+        Optional<OfOverlayNodeConfig> overlayConfig = readFromDs(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid,
+                transaction);
         if (overlayConfig.isPresent()) {
             return overlayConfig.get();
         }
         return null;
     }
 
-    private static void addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) {
-        InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
-                Nodes.class)
+    private static boolean addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) {
+        InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(Nodes.class)
             .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
             .augmentation(OfOverlayNodeConfig.class)
             .build();
 
         WriteTransaction transaction = dataBroker.newReadWriteTransaction();
         transaction.put(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, config, true);
-        submitToDs(transaction);
-    }
-
-    private static void addTunnelToOfOverlayAugmentation(Tunnel tunnel, String nodeIdString, DataBroker dataBroker) {
-        InstanceIdentifier<Tunnel> ofOverlayNodeIid = InstanceIdentifier.builder(
-                Nodes.class)
-            .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
-            .augmentation(OfOverlayNodeConfig.class)
-            .child(Tunnel.class, new TunnelKey(tunnel.getKey()))
-            .build();
-
-        WriteTransaction transaction = dataBroker.newReadWriteTransaction();
-        transaction.put(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, tunnel, true);
-        if(submitToDs(transaction)) {
-            LOG.info("addTunnelToOfOverlayAugmentation: Wrote tunnel {}",tunnel.getKey());
-        } else {
-            LOG.error("addTunnelToOfOverlayAugmentation: submitToDs failed for tunnel {}",tunnel.getKey());
-        }
+        return submitToDs(transaction);
     }
 
     /**
      * Update the {@link OfOverlayConfig} of an Inventory Node
      * using the new tunnel state.
      *
+     * @param ip
      * @param nodeIdString
-     * @param tunnels
+     * @param nodeConnectorIdString
+     * @param tunnelType
      * @param dataBroker
      */
-    public static void updateOfOverlayConfig(IpAddress ip, String nodeIdString,
-            String nodeConnectorIdString, List<AbstractTunnelType> tunnels, DataBroker dataBroker) {
+    public static void updateOfOverlayConfig(IpAddress ip, String nodeIdString, String nodeConnectorIdString,
+            AbstractTunnelType tunnelType, DataBroker dataBroker) {
 
-        if ((ip == null) || (nodeIdString == null)
-                || (nodeConnectorIdString == null)) {
+        if ((ip == null) || (nodeIdString == null) || (nodeConnectorIdString == null)) {
             LOG.debug("Can't update OfOverlay: requisite information not present");
             return;
         }
         NodeConnectorId nodeConnectorId = new NodeConnectorId(nodeConnectorIdString);
-        List<Tunnel> tunnelList = new ArrayList<Tunnel>();
-        List<Tunnel> existingTunnels = new ArrayList<Tunnel>();
+
+
+        // Pull existing augmentation
         OfOverlayNodeConfig ofConfig = getOfOverlayConfig(nodeIdString, dataBroker);
-        if (ofConfig != null && ofConfig.getTunnel() != null) {
-            existingTunnels = ofConfig.getTunnel();
+
+        // If it exists, use it in new augmentation constructor, else new augmentation
+        OfOverlayNodeConfigBuilder ofOverlayNodeConfigBuilder;
+        Set<Tunnel> existingTunnels = new HashSet<Tunnel>();
+        if (ofConfig != null) {
+            ofOverlayNodeConfigBuilder = new OfOverlayNodeConfigBuilder(ofConfig);
+            if(ofConfig.getTunnel() != null) {
+                existingTunnels.addAll(ofConfig.getTunnel());
+            }
+        } else {
+            ofOverlayNodeConfigBuilder = new OfOverlayNodeConfigBuilder();
         }
+
+        // Determine if this is an update to existing tunnel of this type or a new tunnel
         boolean tunnelsUpdated = false;
-        for (AbstractTunnelType tunnelType: tunnels) {
-            boolean tunnelFound = false;
-            for (Tunnel currentTun: existingTunnels) {
-                if (tunnelType.getTunnelType().equals(currentTun.getTunnelType())) {
-                    // tunnel update
-                    TunnelBuilder tunnelBuilder = new TunnelBuilder(currentTun);
-                    tunnelBuilder.setIp(ip);
-                    tunnelBuilder.setPort(tunnelType.getPortNumber());
-                    tunnelBuilder.setNodeConnectorId(nodeConnectorId);
-                    tunnelList.add(tunnelBuilder.build());
-                    tunnelFound = true;
-                    tunnelsUpdated = true;
-                }
-            }
-            // new tunnel
-            if (tunnelFound == false) {
-                TunnelBuilder tunnelBuilder = new TunnelBuilder();
+        TunnelBuilder tunnelBuilder = new TunnelBuilder();
+
+        boolean tunnelFound = false;
+        for (Tunnel currentTun : existingTunnels) {
+            if (tunnelType.getTunnelType().equals(currentTun.getTunnelType())) {
+                // tunnel update
                 tunnelBuilder.setIp(ip);
                 tunnelBuilder.setPort(tunnelType.getPortNumber());
                 tunnelBuilder.setNodeConnectorId(nodeConnectorId);
-                tunnelBuilder.setTunnelType(tunnelType.getTunnelType());
-                tunnelList.add(tunnelBuilder.build());
+                tunnelFound = true;
                 tunnelsUpdated = true;
+                break;
             }
         }
-        if (tunnelsUpdated == true) {
-            for (Tunnel tunnel: tunnelList) {
-                addTunnelToOfOverlayAugmentation(tunnel, nodeIdString, dataBroker);
-            }
+        // new tunnel
+        if (tunnelFound == false) {
+            tunnelBuilder.setIp(ip);
+            tunnelBuilder.setPort(tunnelType.getPortNumber());
+            tunnelBuilder.setNodeConnectorId(nodeConnectorId);
+            tunnelBuilder.setTunnelType(tunnelType.getTunnelType());
+            tunnelsUpdated = true;
+        }
+
+        // Nothing was updated, nothing to see here, move along...
+        if (tunnelsUpdated == false) {
+            return;
+        }
+
+        existingTunnels.add(tunnelBuilder.build());
+
+        // Update the OfOverlayNodeConfig with the new tunnel information
+        OfOverlayNodeConfig newConfig=ofOverlayNodeConfigBuilder.setTunnel(new ArrayList<Tunnel>(existingTunnels)).build();
+        if (addOfOverlayAugmentation(newConfig, nodeIdString, dataBroker)) {
+            LOG.trace("updateOfOverlayConfig - Added Tunnel: {} to Node: {} at NodeConnector: {}",tunnelBuilder.build(), nodeIdString, nodeConnectorIdString);
+            return;
+        } else {
+            LOG.error("updateOfOverlayConfig - could not write OfOverlayNodeConfig: {} to datastore.", newConfig);
         }
     }
 
index 37d8b3b05f9eaaf64a1392a223812a9aa32bbc79..c2badde2adec73b54db400fc70ada6e25ececfce 100755 (executable)
@@ -249,7 +249,7 @@ public class OvsdbHelper {
                 buildOvsdbBridgeAugmentation(bridge,managerNode);
         Node configNode = getNode(node, tps,ovsdbBridgeAugmentation);
         LOG.info("About to write nodeId {} node {}",nodeIid,configNode);
-        transaction.put(LogicalDatastoreType.CONFIGURATION, nodeIid, configNode);
+        transaction.merge(LogicalDatastoreType.CONFIGURATION, nodeIid, configNode);
         submitToDs(transaction);
     }
 
index 031f8ebc2585bb87048f641a37a96a2ff7663f51..214186cac8a60c3f8c79c884cd924fba214b4475 100644 (file)
@@ -28,7 +28,9 @@ public class TunnelTypeTest {
     protected static final String VNID_VALUE = "flow";
     protected static final String REMOTE_IP_KEY = "remote_ip";
     protected static final String REMOTE_IP_VALUE = "flow";
-
+    private static final String DESTPORT_KEY = "dst_port";
+    private static final Integer VXLAN_GPE_PORT_NUMBER = 6633;
+    private static final String DESTPORT_VALUE = VXLAN_GPE_PORT_NUMBER.toString();
     private static final String NSH_NSI_KEY = "nsi";
     private static final String NSH_NSI_VALUE = "flow";
     private static final String NSH_NSP_KEY = "nsp";
@@ -82,6 +84,10 @@ public class TunnelTypeTest {
         ob.setOption(NSH_NSHC4_KEY)
           .setValue(NSH_NSHC4_VALUE);
         nshOptions.add(ob.build());
+        ob = new OptionsBuilder();
+        ob.setOption(DESTPORT_KEY)
+          .setValue(DESTPORT_VALUE);
+        nshOptions.add(ob.build());
     }
 
     @Test
index 90d88c9488ab7f96223b7c7cd59e587a1b986df1..73fa28c5faf7a271fa5d4eff173d3f3465b4ce7f 100755 (executable)
@@ -298,6 +298,8 @@ public class PolicyManager
 
             if (!wrappedFlows.contains(wFlow)) {
                 tableBuilder.getFlow().add(Preconditions.checkNotNull(flow));
+            } else {
+                LOG.debug("Flow already exists in FlowMap - {}", flow);
             }
         }
 
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ChainActionFlows.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ChainActionFlows.java
new file mode 100644 (file)
index 0000000..be88537
--- /dev/null
@@ -0,0 +1,220 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxNsiMatch;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxNspMatch;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;
+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.gotoTableIns;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc1RegAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc2RegAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxTunIpv4DstMatch;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+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.flow.PolicyEnforcer.NetworkElements;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ChainAction;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcNshHeader;
+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.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.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.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.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ChainActionFlows {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ChainAction.class);
+
+    public ChainActionFlows() {
+
+    }
+
+    public static void createChainTunnelFlows(SfcNshHeader sfcNshHeader, NetworkElements netElements, FlowMap flowMap,
+            OfContext ctx) {
+
+        NodeId localNodeId = netElements.getLocalNodeId();
+        NodeId destNodeId = netElements.getDstEp().getAugmentation(OfOverlayContext.class).getNodeId();
+        NodeConnectorId localNodeTunPort = ctx.getSwitchManager().getTunnelPort(localNodeId, TunnelTypeVxlanGpe.class);
+        NodeConnectorId destNodeTunPort = ctx.getSwitchManager().getTunnelPort(destNodeId, TunnelTypeVxlanGpe.class);
+        if (localNodeTunPort == null || destNodeTunPort == null) {
+            LOG.error("createChainTunnelFlows: No valid VXLAN GPE tunnel for Node {} or Node {}", localNodeId,
+                    destNodeId);
+            return;
+        }
+        flowMap.writeFlow(localNodeId, ctx.getPolicyManager().getTABLEID_PORTSECURITY(),
+                allowFromChainPort(localNodeTunPort, ctx.getPolicyManager().getTABLEID_PORTSECURITY(), ctx));
+
+        flowMap.writeFlow(localNodeId, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER(),
+                allowFromChainTunnel(localNodeTunPort, ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()));
+
+        flowMap.writeFlow(
+                localNodeId,
+                ctx.getPolicyManager().getTABLEID_EXTERNAL_MAPPER(),
+                createExternalFlow(sfcNshHeader, localNodeTunPort, netElements, ctx.getPolicyManager()
+                    .getTABLEID_EXTERNAL_MAPPER(), ctx));
+
+        flowMap.writeFlow(
+                destNodeId,
+                ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER(),
+                createChainTunnelFlow(sfcNshHeader, destNodeTunPort, netElements.getSrcEpOrds(), ctx.getPolicyManager()
+                    .getTABLEID_SOURCE_MAPPER(), ctx));
+
+        flowMap.writeFlow(
+                destNodeId,
+                ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER(),
+                createChainBroadcastFlow(sfcNshHeader, destNodeTunPort, netElements.getSrcEpOrds(),
+                        ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER(), ctx));
+
+    }
+
+    private static Flow createChainBroadcastFlow(SfcNshHeader sfcNshHeader, NodeConnectorId tunPort,
+            EndpointFwdCtxOrdinals epFwdCtxOrds, short tableId, OfContext ctx) {
+
+        int fdId = epFwdCtxOrds.getFdId();
+
+        MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
+
+        addNxNsiMatch(mb, sfcNshHeader.getNshNsiFromChain());
+        addNxNspMatch(mb, sfcNshHeader.getNshNspFromChain());
+        addNxTunIdMatch(mb, fdId);
+
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action fdReg = nxLoadRegAction(
+                NxmNxReg5.class, BigInteger.valueOf(fdId));
+
+        Match match = mb.build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainbroadcast", match);
+
+        FlowBuilder flowb = base(tableId).setId(flowId)
+            .setPriority(Integer.valueOf(150))
+            .setMatch(match)
+            .setInstructions(
+                    instructions(applyActionIns(fdReg), gotoTableIns(ctx.getPolicyManager()
+                        .getTABLEID_DESTINATION_MAPPER())));
+        return flowb.build();
+    }
+
+    private static Flow createExternalFlow(SfcNshHeader sfcNshHeader, NodeConnectorId tunPort,
+             NetworkElements netElements, short tableId, OfContext ctx) {
+
+        Integer priority = 1000;
+
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadC1 = nxLoadNshc1RegAction(sfcNshHeader.getNshMetaC1());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadC2 = nxLoadNshc2RegAction(sfcNshHeader.getNshMetaC2());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunVnid =
+                nxLoadTunIdAction(BigInteger.valueOf(netElements.getSrcEpOrds().getTunnelId()), false);
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action loadChainTunDest = nxLoadTunIPv4Action(sfcNshHeader.getNshTunIpDst().getValue(), false);
+
+
+        MatchBuilder mb = new MatchBuilder();
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(netElements.getDstEpOrds().getL3Id())));
+        addNxTunIdMatch(mb, netElements.getSrcEpOrds().getTunnelId());
+        addNxNspMatch(mb, sfcNshHeader.getNshNspToChain());
+        addNxNsiMatch(mb, sfcNshHeader.getNshNsiToChain());
+        if (!netElements.getDstEp().getAugmentation(OfOverlayContext.class).getNodeId().equals(netElements.getLocalNodeId())) {
+            addNxTunIpv4DstMatch(mb, ctx.getSwitchManager().getTunnelIP(netElements.getDstNodeId(), TunnelTypeVxlan.class).getIpv4Address());
+            priority = 1500;
+        }
+
+        Match match = mb.build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainexternal", match);
+        FlowBuilder flowb = base(tableId).setId(flowId)
+            .setPriority(Integer.valueOf(priority))
+            .setMatch(match)
+            .setInstructions(instructions(applyActionIns(loadC1, loadC2, loadChainTunDest, loadChainTunVnid, outputAction(tunPort))));
+        return flowb.build();
+    }
+
+    private static Flow createChainTunnelFlow(SfcNshHeader sfcNshHeader, NodeConnectorId tunPort,
+            EndpointFwdCtxOrdinals epFwdCtxOrds, short tableId, OfContext ctx) {
+
+        int egId = epFwdCtxOrds.getEpgId();
+        int bdId = epFwdCtxOrds.getBdId();
+        int fdId = epFwdCtxOrds.getFdId();
+        int l3Id = epFwdCtxOrds.getL3Id();
+        int tunnelId = epFwdCtxOrds.getTunnelId();
+
+        MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
+        addNxTunIdMatch(mb, tunnelId);
+        addNxNspMatch(mb, sfcNshHeader.getNshNspFromChain());
+        addNxNsiMatch(mb, sfcNshHeader.getNshNsiFromChain());
+
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action segReg = nxLoadRegAction(
+                NxmNxReg0.class, BigInteger.valueOf(egId));
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action scgReg = nxLoadRegAction(
+                NxmNxReg1.class, BigInteger.valueOf(0xffffff));
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action bdReg = nxLoadRegAction(
+                NxmNxReg4.class, BigInteger.valueOf(bdId));
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action fdReg = nxLoadRegAction(
+                NxmNxReg5.class, BigInteger.valueOf(fdId));
+        org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action vrfReg = nxLoadRegAction(
+                NxmNxReg6.class, BigInteger.valueOf(l3Id));
+
+        Match match = mb.build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "chaintunnel", match);
+        FlowBuilder flowb = base(tableId).setId(flowId)
+            .setPriority(Integer.valueOf(150))
+            .setMatch(match)
+            .setInstructions(
+                    instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg),
+                            gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
+        return flowb.build();
+    }
+
+    private static Flow allowFromChainPort(NodeConnectorId port, short tableId, OfContext ctx) {
+
+        Match match = new MatchBuilder().setInPort(port).build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainport", match);
+        FlowBuilder flowb = base(tableId).setId(flowId)
+            .setPriority(Integer.valueOf(200))
+            .setMatch(match)
+            .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
+        return flowb.build();
+    }
+
+    private static Flow allowFromChainTunnel(NodeConnectorId tunPort, short tableId) {
+
+        MatchBuilder mb = new MatchBuilder().setInPort(tunPort);
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg1.class, Long.valueOf(0xffffff)));
+        Match match = mb.build();
+        FlowId flowId = FlowIdUtils.newFlowId(tableId, "chainport", match);
+
+        FlowBuilder flow = base(tableId).setId(flowId)
+            .setMatch(match)
+            .setPriority(65000)
+            .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
+        return flow.build();
+
+    }
+
+    /**
+     * Get a base flow builder with some common features already set
+     */
+    private static FlowBuilder base(short tableId) {
+        return new FlowBuilder().setTableId(tableId).setBarrier(false).setHardTimeout(0).setIdleTimeout(0);
+    }
+}
index 25c3985a4a35aee9cf31f629ddd02f105d058c04..8bdc97691a0fe5e6d659331b0e141ac7b34ca205 100755 (executable)
@@ -378,19 +378,7 @@ public class DestinationMapper extends FlowTable {
             return null;
         }
 
-        /*
-        // commented out because of the new FlowId implementation
-        FlowId flowid = new FlowId(new StringBuilder().append(Integer.toString(epFwdCtxOrds.getL3Id()))
-            .append("|l3prefix|")
-            .append(ikey)
-            .append("|")
-            .append(destSubnetGatewayMac)
-            .append("|")
-            .append(nextHop)
-            .toString());
-        */
         MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, etherType));
-//        MatchBuilder mb = new MatchBuilder();//.setLayer3Match(m);
         addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(epFwdCtxOrds.getL3Id())));
         Match match = mb.build();
         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "L3prefix", match);
@@ -602,15 +590,8 @@ public class DestinationMapper extends FlowTable {
         }
         OfOverlayContext ofc = destEp.getAugmentation(OfOverlayContext.class);
 
-        // ////////////////////////////////////////////////////////////////////////////////////////
-        /*
-         * NOT HANDLING EXTERNALS TODO: alagalah Li: External Gateway
-         * functionality needed here.
-         */
         if (LocationType.External.equals(ofc.getLocationType())) {
-            // XXX - TODO - perform NAT and send to the external network
-            // TODO: Use case neutron gateway interface
-            LOG.warn("External endpoints not yet supported");
+            LOG.error("syncEp(): External endpoints should not be seen here.");
             return;
         }
 
index a37a3b61ba19f51000c3d8b1562fd45c52e11bd8..d2d23662d1ceb1c348db21748064cb5410bbe4b2 100755 (executable)
@@ -10,6 +10,7 @@ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -26,8 +27,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.Fl
 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.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+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.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -61,40 +65,20 @@ public class ExternalMapper extends FlowTable {
         // Default drop all
         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
 
-        // Drop IP traffic that doesn't match a source IP rule
-        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(2), FlowUtils.ARP, TABLE_ID));
-        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(2), FlowUtils.IPv4, TABLE_ID));
-        flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(2), FlowUtils.IPv6, TABLE_ID));
-        l3flow(flowMap,nodeId, 100, true);
-        l3flow(flowMap,nodeId, 200, false);
-    }
-
-    private void l3flow(FlowMap flowMap, NodeId nodeId, Integer priority, boolean arp) {
-
-        List<ActionBuilder> actionBuilderList = new ArrayList<ActionBuilder>();
-
-        Action action = SubjectFeatures.getAction(AllowAction.DEFINITION.getId());
-        actionBuilderList = action.updateAction(actionBuilderList, new HashMap<String, Object>(), 0, null);
+        /*
+         *  Default Egress flow. Other methods may write to this table to augment egress
+         *  functionality, such as bypassing/utilising the NAT table, or ServiceFunctionChaining
+         */
+        flowMap.writeFlow(nodeId, TABLE_ID, defaultFlow());
 
-        Layer3Match m = null;
-        Long etherType = null;
-
-        if (arp) {
-            etherType = FlowUtils.ARP;
-        } else {
-            etherType = FlowUtils.IPv4;
-        }
+    }
 
-        Match match = new MatchBuilder().setEthernetMatch(FlowUtils.ethernetMatch(null, null, etherType))
-                .setLayer3Match(m)
-                .build();
-        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "ExternalMapper", match);
-        Flow flow = base().setPriority(priority)
+    private Flow defaultFlow() {
+        FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "defaultExternalFlow", null);
+        Flow flow = base().setPriority(100)
             .setId(flowid)
-            .setMatch(match)
-            .setInstructions(instructions(applyActionIns(actionBuilderList)))
+            .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
             .build();
-
-        flowMap.writeFlow(nodeId, TABLE_ID, flow);
+        return flow;
     }
 }
index 51d38f49a06504a540efca3040d8a4e4fa64e445..0f10741a8dd50379c8aa90a1a8c41044329433ac 100755 (executable)
@@ -2,6 +2,8 @@ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
+
+import org.apache.commons.lang3.StringUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
@@ -49,6 +51,9 @@ public class FlowIdUtils {
     }
 
     private static String formatMatch(Match match) {
+        if (match == null) {
+            return StringUtils.EMPTY;
+        }
         StringBuilder builder = new StringBuilder(MATCH_PREFIX);
         boolean first = true;
         if (match.getEthernetMatch() != null) {
index 3965fcc472d8f53b6b98aa63a1a4e4a00332a03d..3c68563c4b567a85b77ccfc5ec59ddb0f1cd75c5 100644 (file)
@@ -12,7 +12,6 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
@@ -34,11 +33,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.dst.action._case.SetDlDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.dl.src.action._case.SetDlSrcActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstAction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.dst.action._case.SetNwDstActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.nw.src.action._case.SetNwSrcActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
@@ -157,6 +154,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg6Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg7Key;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxTunIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxTunIpv4DstKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nshc._1.grouping.NxmNxNshc1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nshc._2.grouping.NxmNxNshc2Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nshc._3.grouping.NxmNxNshc3Builder;
@@ -165,8 +163,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.ni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.nsp.grouping.NxmNxNspBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.tun.id.grouping.NxmNxTunIdBuilder;
-import org.opendaylight.yangtools.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.tun.ipv4.dst.grouping.NxmNxTunIpv4DstBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 import com.google.common.collect.ImmutableList;
@@ -430,9 +427,6 @@ public final class FlowUtils {
         return nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(reg).build(), value);
     }
 
-    // TODO: alagalah Li Need to address nicira yang model to make this extend an NxmNxNshFoo case
-    // class
-
     public static Action nxLoadNshc1RegAction(Long value) {
         NxSetNshc1 newNshc1 = new NxSetNshc1Builder().setNshc(value).build();
         return new NxActionSetNshc1NodesNodeTableFlowApplyActionsCaseBuilder().setNxSetNshc1(newNshc1).build();
@@ -502,12 +496,15 @@ public final class FlowUtils {
     }
 
     public static Action nxMoveRegTunDstToNshc1() {
-        return nxMoveRegAction(new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),31,false);
+        return nxMoveRegAction(new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+                new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(), 31, false);
     }
 
     public static Action nxMoveTunIdtoNshc2() {
-        return nxMoveRegAction(new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(), new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),31,false);
+        return nxMoveRegAction(new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+                new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(), 31, false);
     }
+
     public static Action nxMoveRegTunIdAction(Class<? extends NxmNxReg> src, boolean groupBucket) {
         return nxMoveRegAction(new SrcNxRegCaseBuilder().setNxReg(src).build(),
                 new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(), 31, groupBucket);
@@ -595,142 +592,59 @@ public final class FlowUtils {
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
-    // TODO alagalah Be/Li: Once OFP yang refactored to support container/grouping similar to nxreg
-    // we can follow same pattern. For now its match/set per nsh header
     public static void addNxNshc1RegMatch(MatchBuilder match, Long value) {
-        List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
-        ArrayList<ExtensionList> extensions = new ArrayList<>();
-        if(existingExtensions != null && !existingExtensions.isEmpty()) {
-            extensions.addAll(existingExtensions);
-        }
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc1(
                 new NxmNxNshc1Builder().setValue(value).build()).build();
-
-        extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc1Key.class)
-            .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-            .build());
-
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                extensions).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc1Key.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
     public static void addNxNshc2RegMatch(MatchBuilder match, Long value) {
-        List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
-        ArrayList<ExtensionList> extensions = new ArrayList<>();
-        if(existingExtensions != null && !existingExtensions.isEmpty()) {
-            extensions.addAll(existingExtensions);
-        }
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc2(
                 new NxmNxNshc2Builder().setValue(value).build()).build();
-
-        extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc2Key.class)
-            .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-            .build());
-
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                extensions).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc2Key.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
     public static void addNxNshc3RegMatch(MatchBuilder match, Long value) {
-        List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
-        ArrayList<ExtensionList> extensions = new ArrayList<>();
-        if(existingExtensions != null && !existingExtensions.isEmpty()) {
-            extensions.addAll(existingExtensions);
-        }
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc3(
                 new NxmNxNshc3Builder().setValue(value).build()).build();
-
-        extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc3Key.class)
-            .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-            .build());
-
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                extensions).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc3Key.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
     public static void addNxNshc4RegMatch(MatchBuilder match, Long value) {
-        List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
-        ArrayList<ExtensionList> extensions = new ArrayList<>();
-        if(existingExtensions != null && !existingExtensions.isEmpty()) {
-            extensions.addAll(existingExtensions);
-        }
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc4(
                 new NxmNxNshc4Builder().setValue(value).build()).build();
-
-        extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc4Key.class)
-            .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-            .build());
-
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                extensions).build();
-        match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
-    }
-
-    public static void addNxNshcMatch(MatchBuilder match, RegMatch... matches) {
-        ArrayList<ExtensionList> extensions = new ArrayList<>();
-        for (RegMatch rm : matches) {
-            Class<? extends ExtensionKey> key;
-            if (NxmNxReg0.class.equals(rm.reg)) {
-                key = NxmNxReg0Key.class;
-            } else if (NxmNxReg1.class.equals(rm.reg)) {
-                key = NxmNxReg1Key.class;
-            } else if (NxmNxReg2.class.equals(rm.reg)) {
-                key = NxmNxReg2Key.class;
-            } else if (NxmNxReg3.class.equals(rm.reg)) {
-                key = NxmNxReg3Key.class;
-            } else if (NxmNxReg4.class.equals(rm.reg)) {
-                key = NxmNxReg4Key.class;
-            } else if (NxmNxReg5.class.equals(rm.reg)) {
-                key = NxmNxReg5Key.class;
-            } else if (NxmNxReg6.class.equals(rm.reg)) {
-                key = NxmNxReg6Key.class;
-            } else {
-                key = NxmNxReg7Key.class;
-            }
-            NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxReg(
-                    new NxmNxRegBuilder().setReg(rm.reg).setValue(rm.value).build()).build();
-            extensions.add(new ExtensionListBuilder().setExtensionKey(key)
-                .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-                .build());
-        }
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                extensions).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc4Key.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
     public static void addNxTunIdMatch(MatchBuilder match, int tunId) {
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxTunId(
                 new NxmNxTunIdBuilder().setValue(BigInteger.valueOf(tunId)).build()).build();
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxTunIdKey.class)
-                    .setExtension(
-                            new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-                    .build())).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxTunIdKey.class, am, match);
+        match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
+    }
+
+    public static void addNxTunIpv4DstMatch(MatchBuilder match, Ipv4Address ipv4Address) {
+        NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxTunIpv4Dst(
+                new NxmNxTunIpv4DstBuilder().setIpv4Address(ipv4Address).build()).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxTunIpv4DstKey.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
     public static void addNxNsiMatch(MatchBuilder match, short nsi) {
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNsi(
                 new NxmNxNsiBuilder().setNsi(nsi).build()).build();
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxNsiKey.class)
-                    .setExtension(
-                            new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-                    .build())).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNsiKey.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
     public static void addNxNspMatch(MatchBuilder match, Long nsp) {
         NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNsp(
                 new NxmNxNspBuilder().setValue(nsp).build()).build();
-        GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
-                ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxNspKey.class)
-                    .setExtension(
-                            new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
-                    .build())).build();
+        GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNspKey.class, am, match);
         match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
     }
 
@@ -745,6 +659,27 @@ public final class FlowUtils {
         return emb.build();
     }
 
+    private static List<ExtensionList> getExistingGeneralAugMatchNodesNodeTableFlow(MatchBuilder match) {
+        ArrayList<ExtensionList> extensions = new ArrayList<>();
+        if (match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class) != null) {
+            List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class)
+                .getExtensionList();
+            if (existingExtensions != null && !existingExtensions.isEmpty()) {
+                extensions.addAll(existingExtensions);
+            }
+        }
+        return extensions;
+    }
+
+    private static GeneralAugMatchNodesNodeTableFlow addExtensionKeyAugmentationMatcher(
+            Class<? extends ExtensionKey> key, NxAugMatchNodesNodeTableFlow am, MatchBuilder match) {
+        List<ExtensionList> extensions = getExistingGeneralAugMatchNodesNodeTableFlow(match);
+        extensions.add(new ExtensionListBuilder().setExtensionKey(key)
+            .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
+            .build());
+        return new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(extensions).build();
+    }
+
     /**
      * Parse an OF port number from a node connector ID
      *
index d03f943d816b2b3a794e8d8360717d9c3c385d13..9160d00c55988fbc2d44add7e60d42dbf73131f0 100755 (executable)
@@ -8,16 +8,14 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointManager.isExternal;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.writeActionIns;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;
 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.nxOutputRegAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.EndpointManager.isExternal;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -32,7 +30,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 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.node.SwitchManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.Action;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.AllowAction;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf.ClassificationResult;
@@ -52,13 +49,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.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.HasDirection.Direction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.action.refs.ActionRef;
@@ -84,6 +78,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ComparisonChain;
 import com.google.common.collect.Ordering;
 import com.google.common.collect.Table.Cell;
@@ -103,15 +98,11 @@ public class PolicyEnforcer extends FlowTable {
 
     public PolicyEnforcer(OfContext ctx, short tableId) {
         super(ctx);
-        this.TABLE_ID=tableId;
+        this.TABLE_ID = tableId;
         this.gotoEgressNatInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EGRESS_NAT());
-        this.gotoExternalInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EGRESS_NAT());
+        this.gotoExternalInstruction = gotoTableIns(ctx.getPolicyManager().getTABLEID_EXTERNAL_MAPPER());
     }
 
-
-
-
-
     @Override
     public short getTableId() {
         return TABLE_ID;
@@ -122,12 +113,13 @@ public class PolicyEnforcer extends FlowTable {
 
         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
 
-        NodeConnectorId tunPort = SwitchManager.getTunnelPort(nodeId, TunnelTypeVxlan.class);
+        NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
         if (tunPort != null) {
             flowMap.writeFlow(nodeId, TABLE_ID, allowFromTunnel(tunPort));
         }
 
-        HashSet<CgPair> visitedPairs = new HashSet<>();
+        HashSet<PolicyPair> visitedPairs = new HashSet<>();
+        HashSet<PolicyPair> visitedReversePairs = new HashSet<>();
 
         // Used for ARP flows
         Set<Integer> fdIds = new HashSet<>();
@@ -140,7 +132,7 @@ public class PolicyEnforcer extends FlowTable {
                     dstEndpoints.addAll(ctx.getEndpointManager().getEndpointsForGroup(dstEpgKey));
                     dstEndpoints.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(dstEpgKey));
                     for (Endpoint dstEp : dstEndpoints) {
-                        // mEPG ordinals
+
                         EndpointFwdCtxOrdinals srcEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx,
                                 policyInfo, srcEp);
                         EndpointFwdCtxOrdinals dstEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx,
@@ -149,34 +141,53 @@ public class PolicyEnforcer extends FlowTable {
                         int depgId = dstEpFwdCxtOrds.getEpgId();
                         int scgId = srcEpFwdCxtOrds.getCgId();
                         int sepgId = srcEpFwdCxtOrds.getEpgId();
-                        NetworkElements netElements = new NetworkElements(srcEp, dstEp, nodeId, ctx, policyInfo);
+
                         fdIds.add(srcEpFwdCxtOrds.getFdId());
+                        NetworkElements netElements = new NetworkElements(srcEp, dstEp, nodeId, ctx, policyInfo);
 
                         Policy policy = policyInfo.getPolicy(dstEpgKey, srcEpgKey);
-                        for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints: getActiveRulesBetweenEps(policy, dstEp, srcEp)) {
+                        for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
+                                policy, dstEp, srcEp)) {
                             Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
                                 .getL3EpPrefixes());
                             Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
                                 .getL3EpPrefixes());
-                            CgPair p = new CgPair(depgId, sepgId, dcgId, scgId, dIpPrefixes, sIpPrefixes);
-                            if (visitedPairs.contains(p))
+                            PolicyPair policyPair = new PolicyPair(depgId, sepgId, dcgId, scgId, dIpPrefixes,
+                                    sIpPrefixes, netElements.getDstNodeId(), netElements.getSrcNodeId());
+                            if (visitedPairs.contains(policyPair)) {
+                                LOG.trace("PolicyEnforcer: Already visited PolicyPair {}, endpoints {} {} skipped",
+                                        policyPair, srcEp.getKey(), dstEp.getKey());
                                 continue;
-                            visitedPairs.add(p);
-                            syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), p);
+                            } else {
+                                LOG.trace("PolicyEnforcer: Visiting PolicyPair {} endpoints {} {}", policyPair,
+                                        srcEp.getKey(), dstEp.getKey());
+                                visitedPairs.add(policyPair);
+                            }
+                            syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), policyPair);
                         }
 
                         // Reverse
                         policy = policyInfo.getPolicy(srcEpgKey, dstEpgKey);
-                        for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(policy, srcEp, dstEp)) {
+                        for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
+                                policy, srcEp, dstEp)) {
                             Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
                                 .getL3EpPrefixes());
                             Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
                                 .getL3EpPrefixes());
-                            CgPair p = new CgPair(sepgId, depgId, scgId, dcgId, sIpPrefixes, dIpPrefixes);
-                            if (visitedPairs.contains(p))
+                            PolicyPair policyPair = new PolicyPair(sepgId, depgId, scgId, dcgId, sIpPrefixes,
+                                    dIpPrefixes, netElements.getSrcNodeId(), netElements.getDstNodeId());
+                            if (visitedReversePairs.contains(policyPair)) {
+                                LOG.trace(
+                                        "PolicyEnforcer: Reverse: Already visited PolicyPair {}, endpoints {} {} skipped",
+                                        policyPair, srcEp.getKey(), dstEp.getKey());
                                 continue;
-                            visitedPairs.add(p);
-                            syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), p);
+                            } else {
+                                LOG.trace("PolicyEnforcer: Reverse: Visiting: PolicyPair {} via endpoints {} {}",
+                                        policyPair, srcEp.getKey(), dstEp.getKey());
+                                visitedReversePairs.add(policyPair);
+
+                            }
+                            syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), policyPair);
                         }
                     }
                 }
@@ -184,9 +195,7 @@ public class PolicyEnforcer extends FlowTable {
         }
 
         // 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());
@@ -195,11 +204,6 @@ public class PolicyEnforcer extends FlowTable {
 
                 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,
@@ -267,14 +271,14 @@ public class PolicyEnforcer extends FlowTable {
 
     }
 
-    private void syncPolicy(FlowMap flowMap, NetworkElements netElements, List<RuleGroup> rgs, CgPair p) {
+    private void syncPolicy(FlowMap flowMap, NetworkElements netElements, List<RuleGroup> rgs, PolicyPair policyPair) {
         int priority = 65000;
         for (RuleGroup rg : rgs) {
             TenantId tenantId = rg.getContractTenant().getId();
             IndexedTenant tenant = ctx.getPolicyResolver().getTenant(tenantId);
             for (Rule r : rg.getRules()) {
-                syncDirection(flowMap, netElements, tenant, p, r, Direction.In, priority);
-                syncDirection(flowMap, netElements, tenant, p, r, Direction.Out, priority);
+                syncDirection(flowMap, netElements, tenant, policyPair, r, Direction.In, priority);
+                syncDirection(flowMap, netElements, tenant, policyPair, r, Direction.Out, priority);
 
                 priority -= 1;
             }
@@ -301,18 +305,13 @@ public class PolicyEnforcer extends FlowTable {
 
     }
 
-    private void syncDirection(FlowMap flowMap, NetworkElements netElements, IndexedTenant contractTenant, CgPair cgPair, Rule rule,
-            Direction direction, int priority) {
+    private void syncDirection(FlowMap flowMap, NetworkElements netElements, IndexedTenant contractTenant,
+            PolicyPair policyPair, Rule rule, Direction direction, int priority) {
         /*
          * 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: can pass Comparator ActionRefComparator to List constructor, rather than
-        // referencing in sort
         List<ActionBuilder> actionBuilderList = new ArrayList<ActionBuilder>();
         if (rule.getActionRef() != null) {
             /*
@@ -350,11 +349,11 @@ public class PolicyEnforcer extends FlowTable {
                 /*
                  * Convert the GBP Action to one or more OpenFlow Actions
                  */
-                actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(),netElements);
+                if (!(actionRefList.indexOf(actionRule) == (actionRefList.size() - 1) && action.equals(SubjectFeatures.getAction(AllowAction.DEFINITION.getId())))) {
+                    actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(), netElements, policyPair, flowMap, ctx);
+                }
+
             }
-        } else {
-            Action act = SubjectFeatures.getAction(AllowAction.DEFINITION.getId());
-            actionBuilderList = act.updateAction(actionBuilderList, new HashMap<String, Object>(), 0, netElements);
         }
 
         Map<String, ParameterValue> paramsFromClassifier = new HashMap<>();
@@ -384,9 +383,7 @@ public class PolicyEnforcer extends FlowTable {
             classifiers.add(new ClassifierDefinitionId(ci.getClassifierDefinitionId()));
             for (ParameterValue v : ci.getParameterValue()) {
                 if (paramsFromClassifier.get(v.getName().getValue()) == null) {
-                    if (v.getIntValue() != null
-                            || v.getStringValue() != null
-                            || v.getRangeValue() != null) {
+                    if (v.getIntValue() != null || v.getStringValue() != null || v.getRangeValue() != null) {
                         paramsFromClassifier.put(v.getName().getValue(), v);
                     }
                 } else {
@@ -397,28 +394,27 @@ public class PolicyEnforcer extends FlowTable {
                 }
             }
         }
-        if(classifiers.isEmpty()) {
+        if (classifiers.isEmpty()) {
             return;
         }
         List<Map<String, ParameterValue>> derivedParamsByName = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(paramsFromClassifier);
-        String baseId = createBaseFlowId(direction, cgPair, priority);
         List<MatchBuilder> flowMatchBuilders = new ArrayList<>();
         for (Map<String, ParameterValue> params : derivedParamsByName) {
             List<MatchBuilder> matchBuildersToResolve = new ArrayList<>();
-            if (cgPair.sIpPrefixes.isEmpty() && cgPair.dIpPrefixes.isEmpty()) {
-                matchBuildersToResolve.add(createBaseMatch(direction, cgPair, null, null));
-            } else if (!cgPair.sIpPrefixes.isEmpty() && cgPair.dIpPrefixes.isEmpty()) {
-                for (IpPrefix sIpPrefix : cgPair.sIpPrefixes) {
-                    matchBuildersToResolve.add(createBaseMatch(direction, cgPair, sIpPrefix, null));
+            if (policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
+                matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, null));
+            } else if (!policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
+                for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
+                    matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, null));
                 }
-            } else if (cgPair.sIpPrefixes.isEmpty() && !cgPair.dIpPrefixes.isEmpty()) {
-                for (IpPrefix dIpPrefix : cgPair.sIpPrefixes) {
-                    matchBuildersToResolve.add(createBaseMatch(direction, cgPair, null, dIpPrefix));
+            } else if (policyPair.consumerEicIpPrefixes.isEmpty() && !policyPair.providerEicIpPrefixes.isEmpty()) {
+                for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
+                    matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, dIpPrefix));
                 }
             } else {
-                for (IpPrefix sIpPrefix : cgPair.sIpPrefixes) {
-                    for (IpPrefix dIpPrefix : cgPair.sIpPrefixes) {
-                        matchBuildersToResolve.add(createBaseMatch(direction, cgPair, sIpPrefix, dIpPrefix));
+                for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
+                    for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
+                        matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, dIpPrefix));
                     }
                 }
             }
@@ -427,8 +423,8 @@ public class PolicyEnforcer extends FlowTable {
                 ClassificationResult result = classifier.updateMatch(matchBuildersToResolve, params);
                 if (!result.isSuccessfull()) {
                     // TODO consider different handling.
-                    throw new IllegalArgumentException("Classification conflict detected in rule: " + rule.getName() + ".\nCause: "
-                            + result.getErrorMessage());
+                    throw new IllegalArgumentException("Classification conflict detected in rule: " + rule.getName()
+                            + ".\nCause: " + result.getErrorMessage());
                 }
                 matchBuildersToResolve = new ArrayList<>(result.getMatchBuilders());
             }
@@ -439,53 +435,34 @@ public class PolicyEnforcer extends FlowTable {
         for (MatchBuilder mb : flowMatchBuilders) {
             Match match = mb.build();
             FlowId flowId = FlowIdUtils.newFlowId(TABLE_ID, "cg", match);
-            flow.setMatch(match)
-                .setId(flowId)
-                .setPriority(Integer.valueOf(priority));
-                        // If destination is External, the last Action ALLOW must be changed to goto NAT/External table.
-        if (isExternal(netElements.getDst())) {
-            flow.setInstructions(instructions(getGotoEgressNatInstruction()));
-        } else {
-            flow.setInstructions(instructions(applyActionIns(actionBuilderList)));
-        }
-            flowMap.writeFlow(netElements.getNodeId(), TABLE_ID, flow.build());
-        }
-    }
+            flow.setMatch(match).setId(flowId).setPriority(Integer.valueOf(priority));
 
-    private String createBaseFlowId(Direction direction, CgPair cgPair, int priority) {
-        StringBuilder idb = new StringBuilder();
-        if (direction.equals(Direction.In)) {
-            idb.append(cgPair.sepg)
-                    .append("|")
-                    .append(cgPair.scgId)
-                    .append("|")
-                    .append(cgPair.depg)
-                    .append("|")
-                    .append(cgPair.dcgId)
-                    .append("|")
-                    .append(priority);
-        } else {
-            idb.append(cgPair.depg)
-                    .append("|")
-                    .append(cgPair.dcgId)
-                    .append("|")
-                    .append(cgPair.sepg)
-                    .append("|")
-                    .append(cgPair.scgId)
-                    .append("|")
-                    .append(priority);
+            /*
+             * If destination is External, the last Action ALLOW must be changed to goto
+             * NAT/External table.
+             * If actionBuilderList is empty (we removed the last Allow) then go straight to
+             * ExternalMapper table.
+             */
+
+            if (isExternal(netElements.getDstEp())) {
+                flow.setInstructions(instructions(getGotoEgressNatInstruction()));
+            } else if (actionBuilderList.isEmpty()) {
+                flow.setInstructions(instructions(getGotoExternalInstruction()));
+            } else {
+                flow.setInstructions(instructions(applyActionIns(actionBuilderList), getGotoExternalInstruction()));
+            }
+            flowMap.writeFlow(netElements.getLocalNodeId(), TABLE_ID, flow.build());
         }
-        return idb.toString();
     }
 
-    private MatchBuilder createBaseMatch(Direction direction, CgPair cgPair, IpPrefix sIpPrefix, IpPrefix dIpPrefix) {
+    private MatchBuilder createBaseMatch(Direction direction, PolicyPair policyPair, IpPrefix sIpPrefix,
+            IpPrefix dIpPrefix) {
         MatchBuilder baseMatch = new MatchBuilder();
         if (direction.equals(Direction.In)) {
-            addNxRegMatch(baseMatch,
-                    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)));
+            addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, Long.valueOf(policyPair.consumerEpgId)),
+                    RegMatch.of(NxmNxReg1.class, Long.valueOf(policyPair.consumerCondGrpId)),
+                    RegMatch.of(NxmNxReg2.class, Long.valueOf(policyPair.providerEpgId)),
+                    RegMatch.of(NxmNxReg3.class, Long.valueOf(policyPair.providerCondGrpId)));
             if (sIpPrefix != null) {
                 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, true));
             }
@@ -493,11 +470,10 @@ public class PolicyEnforcer extends FlowTable {
                 baseMatch.setLayer3Match(createLayer3Match(dIpPrefix, true));
             }
         } else {
-            addNxRegMatch(baseMatch,
-                    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)));
+            addNxRegMatch(baseMatch, RegMatch.of(NxmNxReg0.class, Long.valueOf(policyPair.providerEpgId)),
+                    RegMatch.of(NxmNxReg1.class, Long.valueOf(policyPair.providerCondGrpId)),
+                    RegMatch.of(NxmNxReg2.class, Long.valueOf(policyPair.consumerEpgId)),
+                    RegMatch.of(NxmNxReg3.class, Long.valueOf(policyPair.consumerCondGrpId)));
             if (sIpPrefix != null) {
                 baseMatch.setLayer3Match(createLayer3Match(sIpPrefix, false));
             }
@@ -525,8 +501,8 @@ public class PolicyEnforcer extends FlowTable {
     }
 
     // TODO: move to a common utils for all renderers
-    public List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>>
-                getActiveRulesBetweenEps(Policy policy, Endpoint consEp, Endpoint provEp) {
+    public List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> getActiveRulesBetweenEps(Policy policy,
+            Endpoint consEp, Endpoint provEp) {
         List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> rulesWithEpConstraints = new ArrayList<>();
         if (policy.getRuleMap() != null) {
             for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> cell : policy.getRuleMap().cellSet()) {
@@ -557,35 +533,59 @@ public class PolicyEnforcer extends FlowTable {
     }
 
     @Immutable
-    private static class CgPair {
+    public static class PolicyPair {
+
+        private final int consumerEpgId;
+        private final int providerEpgId;
+        private final int consumerCondGrpId;
+        private final int providerCondGrpId;
+        private final Set<IpPrefix> consumerEicIpPrefixes;
+        private final Set<IpPrefix> providerEicIpPrefixes;
+        private NodeId consumerEpNodeId;
+        private NodeId providerEpNodeId;
+
+        public int getConsumerEpgId() {
+            return consumerEpgId;
+        }
+
+        public int getProviderEpgId() {
+            return providerEpgId;
+        }
+
+        public NodeId getConsumerEpNodeId() {
+            return consumerEpNodeId;
+        }
 
-        private final int sepg;
-        private final int depg;
-        private final int scgId;
-        private final int dcgId;
-        private final Set<IpPrefix> sIpPrefixes;
-        private final Set<IpPrefix> dIpPrefixes;
+        public NodeId getProviderEpNodeId() {
+            return providerEpNodeId;
+        }
 
-        public CgPair(int sepg, int depg, int scgId, int dcgId, Set<IpPrefix> sIpPrefixes, Set<IpPrefix> dIpPrefixes) {
+        public PolicyPair(int consumerEpgId, int providerEpgId, int consumerCondGrpId, int providerCondGrpId,
+                Set<IpPrefix> consumerEicIpPrefixes, Set<IpPrefix> providerEicIpPrefixes, NodeId consumerEpNodeId, NodeId providerEpNodeId) {
             super();
-            this.sepg = sepg;
-            this.depg = depg;
-            this.scgId = scgId;
-            this.dcgId = dcgId;
-            this.sIpPrefixes = sIpPrefixes;
-            this.dIpPrefixes = dIpPrefixes;
+            this.consumerEpgId = consumerEpgId;
+            this.providerEpgId = providerEpgId;
+            this.consumerCondGrpId = consumerCondGrpId;
+            this.providerCondGrpId = providerCondGrpId;
+            this.consumerEicIpPrefixes = consumerEicIpPrefixes;
+            this.providerEicIpPrefixes = providerEicIpPrefixes;
+            this.consumerEpNodeId = consumerEpNodeId;
+            this.providerEpNodeId = providerEpNodeId;
         }
 
         @Override
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + ((dIpPrefixes == null) ? 0 : dIpPrefixes.hashCode());
-            result = prime * result + dcgId;
-            result = prime * result + depg;
-            result = prime * result + ((sIpPrefixes == null) ? 0 : sIpPrefixes.hashCode());
-            result = prime * result + scgId;
-            result = prime * result + sepg;
+            result = prime * result + ((providerEicIpPrefixes == null) ? 0 : providerEicIpPrefixes.hashCode());
+            result = prime * result + providerCondGrpId;
+            result = prime * result + providerEpgId;
+            result = prime * result + ((consumerEicIpPrefixes == null) ? 0 : consumerEicIpPrefixes.hashCode());
+            result = prime * result + consumerCondGrpId;
+            result = prime * result + consumerEpgId;
+            result = prime * result + ((consumerEpNodeId == null) ? 0 : consumerEpNodeId.hashCode());
+            result = prime * result + ((providerEpNodeId == null) ? 0 : providerEpNodeId.hashCode());
+
             return result;
         }
 
@@ -597,71 +597,129 @@ public class PolicyEnforcer extends FlowTable {
                 return false;
             if (getClass() != obj.getClass())
                 return false;
-            CgPair other = (CgPair) obj;
-            if (dIpPrefixes == null) {
-                if (other.dIpPrefixes != null)
+            PolicyPair other = (PolicyPair) obj;
+            if (providerEicIpPrefixes == null) {
+                if (other.providerEicIpPrefixes != null) {
                     return false;
-            } else if (!dIpPrefixes.equals(other.dIpPrefixes))
+                }
+            } else if (!providerEicIpPrefixes.equals(other.providerEicIpPrefixes)) {
                 return false;
-            if (dcgId != other.dcgId)
+            }
+            if (consumerEicIpPrefixes == null) {
+                if (other.consumerEicIpPrefixes != null) {
+                    return false;
+                }
+            } else if (!consumerEicIpPrefixes.equals(other.consumerEicIpPrefixes)) {
                 return false;
-            if (sIpPrefixes == null) {
-                if (other.sIpPrefixes != null)
+            }
+            if (consumerEpNodeId == null) {
+                if (other.consumerEpNodeId != null) {
                     return false;
-            } else if (!sIpPrefixes.equals(other.sIpPrefixes))
+                }
+            } else if (!consumerEpNodeId.getValue().equals(other.consumerEpNodeId.getValue())) {
                 return false;
-            if (depg != other.depg)
+            }
+            if (providerEpNodeId == null) {
+                if (other.providerEpNodeId != null) {
+                    return false;
+                }
+            } else if (!providerEpNodeId.getValue().equals(other.providerEpNodeId.getValue())) {
                 return false;
-            if (scgId != other.scgId)
+            }
+            if (providerCondGrpId != other.providerCondGrpId)
+                return false;
+            if (providerEpgId != other.providerEpgId)
                 return false;
-            if (sepg != other.sepg)
+            if (consumerCondGrpId != other.consumerCondGrpId)
                 return false;
+            if (consumerEpgId != other.consumerEpgId)
+                return false;
+
             return true;
         }
+
+        @Override
+        public String toString() {
+            return new StringBuilder().append("consumerEPG: ")
+                .append(consumerEpgId)
+                .append("consumerCG: ")
+                .append(consumerCondGrpId)
+                .append("providerEPG: ")
+                .append(providerEpgId)
+                .append("providerCG: ")
+                .append(providerCondGrpId)
+                .append("consumerEpNodeId: ")
+                .append(consumerEpNodeId)
+                .append("providerEpNodeId: ")
+                .append(providerEpNodeId)
+                .append("consumerEicIpPrefixes: ")
+                .append(consumerEicIpPrefixes)
+                .append("providerEicIpPrefixes: ")
+                .append(providerEicIpPrefixes)
+                .toString();
+        }
     }
 
     public class NetworkElements {
-        Endpoint src;
-        Endpoint dst;
-        NodeId nodeId;
-        EndpointFwdCtxOrdinals srcOrds;
-        EndpointFwdCtxOrdinals dstOrds;
-
-        public NetworkElements(Endpoint src, Endpoint dst, NodeId nodeId, OfContext ctx, PolicyInfo policyInfo) throws Exception {
-            this.src=src;
-            this.dst=dst;
-            this.nodeId = nodeId;
-            this.srcOrds=OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, src);
-            this.dstOrds=OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, dst);
+
+        private Endpoint srcEp;
+        private Endpoint dstEp;
+        private NodeId srcNodeId;
+        private NodeId dstNodeId;
+        private NodeId localNodeId;
+        private EndpointFwdCtxOrdinals srcEpOrds;
+        private EndpointFwdCtxOrdinals dstEpOrds;
+
+        public NetworkElements(Endpoint srcEp, Endpoint dstEp, NodeId nodeId, OfContext ctx, PolicyInfo policyInfo)
+                throws Exception {
+            Preconditions.checkArgument(srcEp.getAugmentation(OfOverlayContext.class) != null);
+            Preconditions.checkArgument(dstEp.getAugmentation(OfOverlayContext.class) != null);
+
+            this.srcEp = srcEp;
+            this.dstEp = dstEp;
+            this.localNodeId = nodeId;
+            this.srcEpOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, srcEp);
+            this.dstEpOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, dstEp);
+            this.dstNodeId = dstEp.getAugmentation(OfOverlayContext.class).getNodeId();
+            this.srcNodeId = srcEp.getAugmentation(OfOverlayContext.class).getNodeId();
         }
 
 
+        Endpoint getSrcEp() {
+            return srcEp;
+        }
+
 
-        public EndpointFwdCtxOrdinals getSrcOrds() {
-            return srcOrds;
+        Endpoint getDstEp() {
+            return dstEp;
         }
 
 
+        NodeId getSrcNodeId() {
+            return srcNodeId;
+        }
+
 
-        public EndpointFwdCtxOrdinals getDstOrds() {
-            return dstOrds;
+        public NodeId getDstNodeId() {
+            return dstNodeId;
         }
 
 
-        public Endpoint getSrc() {
-            return src;
+        public NodeId getLocalNodeId() {
+            return localNodeId;
         }
 
 
-        public Endpoint getDst() {
-            return dst;
+        public EndpointFwdCtxOrdinals getSrcEpOrds() {
+            return srcEpOrds;
         }
 
 
-        public NodeId getNodeId() {
-            return nodeId;
+        EndpointFwdCtxOrdinals getDstEpOrds() {
+            return dstEpOrds;
         }
 
 
+
     }
 }
index 93a515d4152610524f5bb277c7463da5699660d6..5e6991387126399618805d4bbf457d3413d65dc9 100755 (executable)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
+import java.util.Collection;
 import java.util.Set;
 
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
index 34f382783774ec016e8ee5b5be8378060d815b0c..f67851c18b42fa633a1f75d70c4a2032383e6ac7 100755 (executable)
@@ -80,7 +80,6 @@ public class SourceMapper extends FlowTable {
         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
 
         // Handle case where packets from from External
-        Map<EndpointKey, EndpointL3> l3EpWithNatByL2Key = ctx.getEndpointManager().getL3EpWithNatByL2Key();
         for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
             OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
 
@@ -89,7 +88,6 @@ public class SourceMapper extends FlowTable {
                 continue;
 
             EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, ep);
-            EgKey sepg = new EgKey(ep.getTenant(), ep.getEndpointGroup());
 
             createRemoteTunnels(flowMap, nodeId, ep, policyInfo, epFwdCtxOrds);
 
@@ -103,15 +101,7 @@ public class SourceMapper extends FlowTable {
                  * Sync the local EP information.
                  */
                 syncEP(flowMap, nodeId, ep, ofc.getNodeConnectorId(), epFwdCtxOrds);
-
             }
-//            if (l3EpWithNatByL2Key.containsKey(ep.getKey())) {
-//                Set<NodeConnectorId> external = ctx.getSwitchManager().getExternalPorts(nodeId);
-//                for (NodeConnectorId ncId : external) {
-//                    // TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
-//                    syncEP(flowMap, nodeId, ep, ncId, epFwdCtxOrds);
-//                }
-//            }
         }
     }
 
index a211147e696be11436d5a2ffa866f158c775e12b..3ec0a16aa0eedf3615730a1adfbee6e7a573ee19 100644 (file)
@@ -40,6 +40,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeBase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -47,6 +48,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
@@ -139,7 +141,23 @@ public class SwitchManager implements AutoCloseable {
         return ImmutableSet.copyOf(state.externalPorts);
     }
 
-    public static synchronized NodeConnectorId getTunnelPort(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
+    public synchronized Collection<NodeConnectorId> getTunnelPorts(NodeId nodeId) {
+        Collection<NodeConnectorId> ncIds = new HashSet<>();
+        SwitchState state = switches.get(nodeId);
+        if (state == null ) {
+            return Collections.emptySet();
+        }
+        ncIds = Collections2.transform(state.tunnelBuilderByType.values(),new Function<TunnelBuilder, NodeConnectorId>() {
+
+            @Override
+            public NodeConnectorId apply(TunnelBuilder input) {
+                return input.getNodeConnectorId();
+            }
+        });
+
+        return ncIds;
+    }
+    public synchronized NodeConnectorId getTunnelPort(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
         SwitchState state = switches.get(nodeId);
         if (state == null) {
             return null;
@@ -151,7 +169,7 @@ public class SwitchManager implements AutoCloseable {
         return tunnel.getNodeConnectorId();
     }
 
-    public static synchronized IpAddress getTunnelIP(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
+    public synchronized IpAddress getTunnelIP(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
         SwitchState state = switches.get(nodeId);
         if (state == null) {
             return null;
@@ -302,23 +320,6 @@ public class SwitchManager implements AutoCloseable {
         private void update() {
             tunnelBuilderByType = new HashMap<>();
             externalPorts = new HashSet<>();
-            for (Entry<InstanceIdentifier<NodeConnector>, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) {
-                FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue();
-                if (fcnc.getName() == null) {
-                    continue;
-                }
-                InstanceIdentifier<NodeConnector> ncIid = fcncByNcIidEntry.getKey();
-                NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
-                if (fcnc.getName().matches(".*(vxlan).*")) {
-                    TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlan.class);
-                    if (tunnelBuilder == null) {
-                        tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlan.class);
-                        tunnelBuilderByType.put(TunnelTypeVxlan.class, tunnelBuilder);
-                    }
-                    tunnelBuilder.setNodeConnectorId(ncId);
-                }
-            }
-
             if (nodeConfig != null && nodeConfig.getExternalInterfaces() != null) {
                 for (ExternalInterfaces nc : nodeConfig.getExternalInterfaces()) {
                     externalPorts.add(nc.getNodeConnectorId());
@@ -342,6 +343,29 @@ public class SwitchManager implements AutoCloseable {
                     }
                 }
             }
+            for (Entry<InstanceIdentifier<NodeConnector>, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) {
+                FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue();
+                if (fcnc.getName() == null) {
+                    continue;
+                }
+                InstanceIdentifier<NodeConnector> ncIid = fcncByNcIidEntry.getKey();
+                NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+                if (fcnc.getName().matches(".*(vxlan-).*")) {
+                    TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlan.class);
+                    if (tunnelBuilder == null) {
+                        tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlan.class);
+                        tunnelBuilderByType.put(TunnelTypeVxlan.class, tunnelBuilder);
+                    }
+                    tunnelBuilder.setNodeConnectorId(ncId);
+                } else if (fcnc.getName().matches(".*(vxlangpe-).*")) {
+                    TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlanGpe.class);
+                    if (tunnelBuilder == null) {
+                        tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlanGpe.class);
+                        tunnelBuilderByType.put(TunnelTypeVxlanGpe.class, tunnelBuilder);
+                    }
+                    tunnelBuilder.setNodeConnectorId(ncId);
+                }
+            }
         }
 
         private void updateStatus() {
@@ -373,14 +397,10 @@ public class SwitchManager implements AutoCloseable {
             LOG.trace("Iterating over tunnel till tunnel with IP and node-connector is not found.");
             for (TunnelBuilder tb : tunnelBuilderByType.values()) {
                 if (tb.getIp() != null && tb.getNodeConnectorId() != null) {
-//                    LOG.trace("Tunnel found. Type: {} IP: {} Port: {} Node-connector: {}", tb.getTunnelType()
-//                        .getSimpleName(), tb.getIp(), tb.getPort(), tb.getNodeConnectorId());
-                    LOG.trace("Tunnel found.");
+                    LOG.trace("Tunnel {} found.",tb.toString());
                     return true;
                 } else {
-//                    LOG.trace("Tunnel which is not completed: Type: {} IP: {} Port: {} Node-connector: {}",
-//                            tb.getTunnelType().getSimpleName(), tb.getIp(), tb.getPort(), tb.getNodeConnectorId());
-                    LOG.trace("Tunnel which is not completed");
+                    LOG.trace("Tunnel is not complete for node: {}", nodeId.getValue());
                 }
             }
             return false;
index bb0641eeb263eac6193c09199af70baaeff516ee..4e615fe2be196f08edc4d5e8e8e3b731e1789be8 100644 (file)
@@ -12,12 +12,13 @@ import java.util.List;
 import java.util.Map;
 
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.NetworkElements;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.PolicyPair;
 import org.opendaylight.groupbasedpolicy.resolver.ActionInstanceValidator;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 
 /**
  * Represent an action definition, and provide tools for generating
@@ -48,5 +49,8 @@ public abstract class Action implements ActionInstanceValidator{
     public abstract List<ActionBuilder> updateAction(List<ActionBuilder> actions,
                                                      Map<String, Object> params,
                                                      Integer order,
-                                                     NetworkElements netElements);
+                                                     NetworkElements netElements,
+                                                     PolicyPair policyPair,
+                                                     FlowMap flowMap,
+                                                     OfContext ctx);
 }
index 4b75328bd45637447335ed8fb0a80ee52be52def..ea7703adafeec743d7e7b992923987057cb46a25 100644 (file)
@@ -14,7 +14,9 @@ import java.util.List;
 import java.util.Map;
 
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.NetworkElements;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.PolicyPair;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
@@ -22,7 +24,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinitionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
 
 
@@ -57,7 +58,10 @@ public class AllowAction extends Action {
     public List<ActionBuilder> updateAction(List<ActionBuilder> actions,
                                             Map<String, Object> params,
                                             Integer order,
-                                            NetworkElements netElements) {
+                                            NetworkElements netElements,
+                                            PolicyPair policyPair,
+                                            FlowMap flowMap,
+                                            OfContext ctx) {
         /*
          * Allow action doesn't use parameters
          * TODO: check to make sure ActionBuilder w/allow isn't already present
@@ -71,7 +75,6 @@ public class AllowAction extends Action {
 
     @Override
     public boolean isValid(ActionInstance actionInstance) {
-        // TODO Auto-generated method stub
         return true;
     }
 
index d480f6dfed58eff479e08d0deeb6feb336a5b689..fc851b01d30a99826d6964d46b261393abc3e62d 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * 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.sf;
 
 /*
@@ -8,20 +16,23 @@ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sf;
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc1RegAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc2RegAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
+import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.ChainActionFlows.createChainTunnelFlows;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxSetNsiAction;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxSetNspAction;
-import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
 
-import java.math.BigInteger;
 import java.util.List;
 import java.util.Map;
 
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.NetworkElements;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.PolicyEnforcer.PolicyPair;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcIidFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcNshHeader;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcNshHeader.SfcNshHeaderBuilder;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServiceChainAPI;
 import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
@@ -29,17 +40,16 @@ import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev1407
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
 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.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ParameterName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.IsRequired;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.Parameter.Type;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definition.ParameterBuilder;
@@ -47,14 +57,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinitionBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
-import com.google.common.net.InetAddresses;
+import com.google.common.collect.Iterables;
 
 /**
  * Chain action for the OpenFlow Overlay renderer
@@ -98,17 +108,15 @@ public class ChainAction extends Action {
     }
 
     @Override
-    public List<ActionBuilder> updateAction(List<ActionBuilder> actions,
-                                            Map<String, Object> params,
-                                            Integer order,
-                                            NetworkElements netElements) {
+    public List<ActionBuilder> updateAction(List<ActionBuilder> actions, Map<String, Object> params, Integer order,
+            NetworkElements netElements, PolicyPair policyPair, FlowMap flowMap, OfContext ctx) {
         /*
          * Get the named chain
          */
         ServiceFunctionPath sfcPath = null;
         String chainName = null;
         if (params != null) {
-            LOG.debug("Searching for named chain");
+            LOG.debug("ChainAction: Searching for named chain");
             for (String name : params.keySet()) {
                 if (name instanceof String) {
                     if (name.equals(SFC_CHAIN_NAME)) {
@@ -126,13 +134,21 @@ public class ChainAction extends Action {
             return null;
         }
 
+        /*
+         * If path is symmetrical
+         *      if src == consumer, chainName
+         *      else src == provider, chainName-Reverse.
+         */
         if (sfcPath == null) {
             LOG.error("ChainAction: SFC Path null for chain {}", chainName);
             return null;
         }
+
+        // Find existing RSP based on following naming convention, else create it.
         String rspName = sfcPath.getName() + "-gbp-rsp";
-        RenderedServicePathFirstHop rspFirstHop = SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(rspName);
-        if (rspFirstHop == null) {
+        ReadOnlyTransaction rTx = ctx.getDataBroker().newReadOnlyTransaction();
+        RenderedServicePath renderedServicePath = getRspByName(rspName, rTx);
+        if (renderedServicePath == null) {
             LOG.info("ChainAction: Could not find RSP {} for Chain {}", rspName, chainName);
 
             CreateRenderedPathInput rspInput = new CreateRenderedPathInputBuilder().setParentServiceFunctionPath(
@@ -140,117 +156,107 @@ public class ChainAction extends Action {
                 .setName(rspName)
                 .setSymmetric(Boolean.FALSE)
                 .build();
-            RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(
-                    sfcPath, rspInput);
+            renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfcPath, rspInput);
             if (renderedServicePath == null) {
-                LOG.error("Could not find or create RSP for chain {}", chainName);
+                LOG.error("ChainAction: Could not find or create RSP for chain {}", chainName);
                 return null;
             }
-            rspFirstHop=SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(renderedServicePath.getName());
         }
 
-        IpAddress sfcTunIpDst = rspFirstHop.getIp();
-        sfcTunIpDst.getIpv4Address();
-        if (sfcTunIpDst == null || sfcTunIpDst.getIpv4Address() == null || sfcTunIpDst.getIpv6Address() != null) {
-            LOG.error("Invalid IP Tunnel destination for SFC RSP First Hop {}", rspName);
-            return null;
-        }
-        PortNumber sfcTunUdpPort = rspFirstHop.getPort();
-        if (sfcTunUdpPort == null) {
-            LOG.error("Invalid UDP Port Number for SFC RSP {}", rspName);
-            return null;
-        }
-        Long sfcNsp = rspFirstHop.getPathId();
-        if (sfcNsp == null) {
-            LOG.error("Invalid NSP for SFC RSP {}", rspName);
-            return null;
-        }
-        Short sfcNsi = rspFirstHop.getStartingIndex();
-        if (sfcNsi == null) {
-            LOG.error("Invalid NSI for SFC RSP {}", rspName);
+        RenderedServicePathFirstHop rspFirstHop = SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(rspName);
+
+        if (!isValidRspFirstHop(rspFirstHop)) {
+            // Errors logged in method.
             return null;
         }
 
-        NodeConnectorId tunOpenFlowPort = SwitchManager.getTunnelPort(netElements.getNodeId(), TunnelTypeVxlanGpe.class);
-
-        /*
-         * Setting NSH Network Context Headers for post-SFC encapsulation
-         * VXLAN header encap:
-         * - TunnelDestination IP: NSH C1
-         * - Tunnel ID (VNID) NSH C2
-         */
-        long postSfcTunnelDst = 999L;
-        IpAddress tunnelDest;
-
-        if (netElements.getDst().getAugmentation(OfOverlayContext.class).getNodeId().equals(netElements.getNodeId())) {
+        NodeId tunnelDestNodeId;
+        if (netElements.getDstNodeId().equals(netElements.getLocalNodeId())) {
             // Return destination is here
-            tunnelDest=SwitchManager.getTunnelIP(netElements.getNodeId(), TunnelTypeVxlanGpe.class);
+            tunnelDestNodeId = netElements.getLocalNodeId();
         } else {
-            tunnelDest=SwitchManager.getTunnelIP(netElements.getDst().getAugmentation(OfOverlayContext.class).getNodeId(), TunnelTypeVxlanGpe.class);
+            tunnelDestNodeId = netElements.getDstNodeId();
         }
-        postSfcTunnelDst = (InetAddresses.coerceToInteger(InetAddresses.forString(tunnelDest.getIpv4Address().getValue()))) & 0xFFFFFFFFL;
 
-        // TunnelDestination after Chain
-        actions = addActionBuilder(actions, nxLoadNshc1RegAction(postSfcTunnelDst), order++);
-        // VNID after Chain
-        actions = addActionBuilder(actions, nxLoadNshc2RegAction((long) netElements.getSrcOrds().getTunnelId()), order++);
+        IpAddress tunnelDest = ctx.getSwitchManager().getTunnelIP(tunnelDestNodeId, TunnelTypeVxlanGpe.class);
 
-        /*
-         * Set the tunnel destination IP
-         */
-        if (sfcTunIpDst.getIpv4Address() != null) {
-            String nextHop = sfcTunIpDst.getIpv4Address().getValue();
-            actions = addActionBuilder(actions, nxLoadTunIPv4Action(nextHop, false), order);
-        } else if (sfcTunIpDst.getIpv6Address() != null) {
-            LOG.error("IPv6 tunnel destination {} not supported", sfcTunIpDst.getIpv6Address().getValue());
-            return actions;
-        } else {
-            // this shouldn't happen
-            LOG.error("Tunnel IP is invalid");
-            return actions;
+        if (tunnelDest == null || tunnelDest.getIpv4Address() == null) {
+            LOG.error("ChainAction: Invalid tunnelDest for NodeId: {}", tunnelDestNodeId);
+            return null;
         }
 
-        /*
-         * Put TunID - with NSH we don't really care about this.
-         */
-        actions = addActionBuilder(actions,
-                nxLoadTunIdAction(BigInteger.valueOf(netElements.getSrcOrds().getTunnelId()), false), order);
 
-        /*
-         * Set the NSH header fields, based on RSP
-         */
-         actions = addActionBuilder(actions,nxSetNsiAction(sfcNsi),order);
-         actions = addActionBuilder(actions,nxSetNspAction(sfcNsp),order);
-         /*
-         * Set up the actions to send to the destination port
-         */
-         actions = addActionBuilder(actions,outputAction(tunOpenFlowPort), order);
+        RenderedServicePathHop firstRspHop = renderedServicePath.getRenderedServicePathHop().get(0);
+        RenderedServicePathHop lastRspHop = Iterables.getLast(renderedServicePath.getRenderedServicePathHop());
+
+        SfcNshHeader sfcNshHeader = new SfcNshHeaderBuilder().setNshTunIpDst(rspFirstHop.getIp().getIpv4Address())
+            .setNshTunUdpPort(rspFirstHop.getPort())
+            .setNshNsiToChain(firstRspHop.getServiceIndex())
+            .setNshNspToChain(renderedServicePath.getPathId())
+            .setNshNsiFromChain((short) (lastRspHop.getServiceIndex().intValue() - 1))
+            .setNshNspFromChain(renderedServicePath.getPathId())
+            .setNshMetaC1(SfcNshHeader.convertIpAddressToLong(tunnelDest.getIpv4Address()))
+            .setNshMetaC2((long) netElements.getSrcEpOrds().getTunnelId())
+            .build();
+
+        // Cannot set all actions here. Some actions are destination specific, and we don't know a destination is to be
+        // chained until we reach this point. Need to write match/action in External Table for chained packets.
+        actions = addActionBuilder(actions, nxSetNsiAction(sfcNshHeader.getNshNsiToChain()), order);
+        actions = addActionBuilder(actions, nxSetNspAction(sfcNshHeader.getNshNspToChain()), order);
+
+        createChainTunnelFlows(sfcNshHeader, netElements, flowMap, ctx);
 
         return actions;
     }
 
-    private List<ActionBuilder> addActionBuilder(List<ActionBuilder> actions,
-            org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action, Integer order) {
-        ActionBuilder ab = new ActionBuilder();
-        ab.setAction(action);
-        ab.setOrder(order);
-        actions.add(ab);
-        return actions;
+    private boolean isValidRspFirstHop(RenderedServicePathFirstHop rspFirstHop) {
+        boolean valid = true;
+        if (rspFirstHop == null) {
+            LOG.error("isValidRspFirstHop: rspFirstHop is null.");
+            return false;
+        }
+        if (rspFirstHop.getIp() == null || rspFirstHop.getIp().getIpv4Address() == null
+                || rspFirstHop.getIp().getIpv6Address() != null) {
+            LOG.error("isValidRspFirstHop: rspFirstHop has invalid IP address.");
+            valid = false;
+        }
+        if (rspFirstHop.getPort() == null) {
+            LOG.error("isValidRspFirstHop: rspFirstHop has no IP port .");
+            valid = false;
+        }
+        if (rspFirstHop.getPathId() == null) {
+            LOG.error("isValidRspFirstHop: rspFirstHop has no Path Id (NSP).");
+            valid = false;
+        }
+        if (rspFirstHop.getStartingIndex() == null) {
+            LOG.error("isValidRspFirstHop: rspFirstHop has no Starting Index (NSI)");
+            valid = false;
+        }
+        return valid;
+    }
+
+    private RenderedServicePath getRspByName(String rspName, ReadOnlyTransaction rTx) {
+        Optional<RenderedServicePath> optRsp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+                SfcIidFactory.rspIid(rspName), rTx);
+        if (optRsp.isPresent()) {
+            return optRsp.get();
+        }
+        return null;
     }
 
     @Override
     public boolean isValid(ActionInstance actionInstance) {
-        return validChain(actionInstance.getParameterValue());
+        return isValidGbpChain(actionInstance.getParameterValue());
     }
 
-    private boolean validChain(List<ParameterValue> paramValue) {
+    private boolean isValidGbpChain(List<ParameterValue> paramValue) {
         ParameterValue pv = getChainNameParameter(paramValue);
         if (pv == null) {
             return false;
         }
         LOG.trace("Invoking RPC for chain {}", pv.getStringValue());
         ServiceFunctionChain chain = SfcProviderServiceChainAPI.readServiceFunctionChain(pv.getStringValue());
-        return chain != null;
+        return (chain != null);
     }
 
     public ServiceFunctionPath getSfcPath(String chainName) {
@@ -275,4 +281,13 @@ public class ChainAction extends Action {
         return null;
     }
 
+    private List<ActionBuilder> addActionBuilder(List<ActionBuilder> actions,
+            org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action, Integer order) {
+        ActionBuilder ab = new ActionBuilder();
+        ab.setAction(action);
+        ab.setOrder(order);
+        actions.add(ab);
+        return actions;
+    }
+
 }
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcDataStoreHelper.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcDataStoreHelper.java
deleted file mode 100644 (file)
index 4b6b2df..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.sfcutils;
-
-import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
-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.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
-/**
- * @author Martin Sunal
- */
-public class SfcDataStoreHelper {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SfcDataStoreHelper.class);
-
-    /**
-     * Reads data from datastore as synchrone call.
-     * @return {@link Optional#isPresent()} is {@code true} if reading was successful and data exists in datastore; {@link Optional#isPresent()} is {@code false} otherwise
-     */
-    public static <U extends DataObject> U readFromDs(LogicalDatastoreType store,InstanceIdentifier<U> iid, ReadTransaction rTx) {
-        U ret = null;
-        Optional<U> optionalDataObject;
-        CheckedFuture<Optional<U>, ReadFailedException> submitFuture = rTx.read(store, iid);
-        try {
-            optionalDataObject = submitFuture.checkedGet();
-            if (optionalDataObject != null && optionalDataObject.isPresent()) {
-                ret = optionalDataObject.get();
-            } else {
-                LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
-            }
-        } catch (ReadFailedException e) {
-            LOG.warn("failed to ....", e);
-        }
-        return ret;
-    }
-
-    /**
-     * Calls {@link WriteTransaction#submit()} on write transaction.
-     * @param wTx write transaction
-     * @return {@code true} if transaction commit was successful; {@code false} otherwise
-     */
-    public static boolean submitToDs(WriteTransaction wTx) {
-        CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
-        try {
-            submitFuture.checkedGet();
-            return true;
-        } catch (TransactionCommitFailedException e) {
-            LOG.warn("Transaction commit failed to DS.", e);
-            return false;
-        }
-    }
-
-}
index 3d9bffeeafade7cd2a41ba48c11f282402e6fb25..1e067e83d844782430c817a2764c2b3e0113ddce 100644 (file)
@@ -8,6 +8,9 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils;
 
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainKey;
@@ -35,6 +38,12 @@ public class SfcIidFactory {
         ServiceFunctionPathKey serviceFunctionPathKey = new ServiceFunctionPathKey(sfpName);
         return InstanceIdentifier.builder(ServiceFunctionPaths.class)
                 .child(ServiceFunctionPath.class, serviceFunctionPathKey).build();
+    }
+
+    public static InstanceIdentifier<RenderedServicePath> rspIid(String rspName) {
 
+        RenderedServicePathKey rspKey = new RenderedServicePathKey(rspName);
+        return InstanceIdentifier.builder(RenderedServicePaths.class)
+                .child(RenderedServicePath.class, rspKey).build();
     }
 }
diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcNshHeader.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcNshHeader.java
new file mode 100644 (file)
index 0000000..b6f61b7
--- /dev/null
@@ -0,0 +1,188 @@
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+
+import com.google.common.net.InetAddresses;
+
+
+public class SfcNshHeader {
+    private final Ipv4Address nshTunIpDst;
+    private final PortNumber nshTunUdpPort;
+    private final Long nshNspToChain;
+    private final Short nshNsiToChain;
+    private final Long nshNspFromChain;
+    private final Short nshNsiFromChain;
+    private final Long nshMetaC1;
+    private final Long nshMetaC2;
+    private final Long nshMetaC3;
+    private final Long nshMetaC4;
+
+    private static final int TYPE = 1;
+
+    private SfcNshHeader(SfcNshHeaderBuilder builder) {
+        this.nshMetaC1 = builder.nshMetaC1;
+        this.nshMetaC2 = builder.nshMetaC2;
+        this.nshMetaC3 = builder.nshMetaC3;
+        this.nshMetaC4 = builder.nshMetaC4;
+        this.nshTunIpDst = builder.nshTunIpDst;
+        this.nshTunUdpPort = builder.nshTunUdpPort;
+        this.nshNspToChain = builder.nshNspToChain;
+        this.nshNspFromChain = builder.nshNspFromChain;
+        this.nshNsiToChain = builder.nshNsiToChain;
+        this.nshNsiFromChain = builder.nshNsiFromChain;
+
+    }
+
+    public boolean isValid(SfcNshHeader sfcNshHeader) {
+        if (sfcNshHeader.nshTunIpDst == null) return false;
+        if (sfcNshHeader.nshNspToChain == null) return false;
+        if (sfcNshHeader.nshNspFromChain == null) return false;
+        if (sfcNshHeader.nshNsiToChain == null) return false;
+        if (sfcNshHeader.nshNsiFromChain == null) return false;
+        if (sfcNshHeader.nshMetaC1 == null) return false;
+        if (sfcNshHeader.nshMetaC2 == null) return false;
+        return true;
+    }
+
+    public Ipv4Address getNshTunIpDst() {
+        return nshTunIpDst;
+    }
+
+
+    public PortNumber getNshTunUdpPort() {
+        return nshTunUdpPort;
+    }
+
+
+    public Long getNshNspToChain() {
+        return nshNspToChain;
+    }
+
+    public Short getNshNsiToChain() {
+        return nshNsiToChain;
+    }
+
+    public Long getNshNspFromChain() {
+        return nshNspFromChain;
+    }
+
+
+
+    public Short getNshNsiFromChain() {
+        return nshNsiFromChain;
+    }
+
+
+    public Long getNshMetaC1() {
+        return nshMetaC1;
+    }
+
+    public Long getNshMetaC2() {
+        return nshMetaC2;
+    }
+
+    public static Long convertIpAddressToLong(Ipv4Address ipv4Address) {
+        return (InetAddresses.coerceToInteger(InetAddresses.forString(ipv4Address.getValue()))) & 0xFFFFFFFFL;
+    }
+
+    public static int getType() {
+        return TYPE;
+    }
+
+    public static class SfcNshHeaderBuilder {
+        private Ipv4Address nshTunIpDst;
+        private PortNumber nshTunUdpPort;
+        private Long nshNspToChain;
+        private  Short nshNsiToChain;
+        private Long nshNspFromChain;
+        private Short nshNsiFromChain;
+        private Long nshMetaC1;
+        private Long nshMetaC2;
+        private Long nshMetaC3;
+        private Long nshMetaC4;
+
+        public SfcNshHeader build() {
+            SfcNshHeader sfcNshHeader = new SfcNshHeader(this);
+            return sfcNshHeader;
+        }
+        /**
+         * SfcNshHeaderBuilder requires following in constructor:
+         *
+         * @param nshNspToChain
+         * @param nshNsiToChain
+         * @param nshTunIpDst
+         */
+        public SfcNshHeaderBuilder() {
+
+        }
+
+        public SfcNshHeaderBuilder(SfcNshHeader sfcNshHeader) {
+
+            this.nshTunIpDst = sfcNshHeader.nshTunIpDst;
+            this.nshTunUdpPort = sfcNshHeader.nshTunUdpPort;
+            this.nshNspToChain = sfcNshHeader.nshNspToChain;
+            this.nshNsiToChain = sfcNshHeader.nshNsiToChain;
+            this.nshNspFromChain = sfcNshHeader.nshNspFromChain;
+            this.nshNsiFromChain = sfcNshHeader.nshNsiFromChain;
+            this.nshMetaC1 = sfcNshHeader.nshMetaC1;
+            this.nshMetaC2 = sfcNshHeader.nshMetaC2;
+            this.nshMetaC3 = sfcNshHeader.nshMetaC3;
+            this.nshMetaC4 = sfcNshHeader.nshMetaC4;
+        }
+
+        public SfcNshHeaderBuilder setNshTunIpDst(Ipv4Address nshTunIpDst) {
+            this.nshTunIpDst = nshTunIpDst;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshTunUdpPort(PortNumber nshTunUdpPort) {
+            this.nshTunUdpPort = nshTunUdpPort;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshNspToChain(Long nshNspToChain) {
+            this.nshNspToChain = nshNspToChain;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshNsiToChain(Short nshNsiToChain) {
+            this.nshNsiToChain = nshNsiToChain;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshNspFromChain(Long nshNspFromChain) {
+            this.nshNspFromChain = nshNspFromChain;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshNsiFromChain(Short nshNsiFromChain) {
+            this.nshNsiFromChain = nshNsiFromChain;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshMetaC1(Long nshMetaC1) {
+            this.nshMetaC1 = nshMetaC1;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshMetaC2(Long nshMetaC2) {
+            this.nshMetaC2 = nshMetaC2;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshMetaC3(Long nshMetaC3) {
+            this.nshMetaC3 = nshMetaC3;
+            return this;
+        }
+
+        public SfcNshHeaderBuilder setNshMetaC4(Long nshMetaC4) {
+            this.nshMetaC4 = nshMetaC4;
+            return this;
+        }
+
+    }
+
+
+
+}