From: Keith Burns (alagalah) Date: Thu, 4 Jun 2015 05:18:50 +0000 (-0700) Subject: Bug 3244 - SFC Improvements for distributed classifier, robustness X-Git-Tag: release/beryllium~165 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=8e06c107791d70e4bf0a7088249910a1fa9637c1;p=groupbasedpolicy.git Bug 3244 - SFC Improvements for distributed classifier, robustness - 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) --- diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/AbstractTunnelType.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/AbstractTunnelType.java index 15825c508..84dec31fd 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/AbstractTunnelType.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/AbstractTunnelType.java @@ -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 = 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} valid for this tunnel type * diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java index b8f6ce6af..a078e2c6a 100755 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java @@ -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 createSupportedTunnelsList() { List required = new ArrayList(); - // 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 ovsdbTpIid = - (InstanceIdentifier) iid; + InstanceIdentifier ovsdbTpIid = (InstanceIdentifier) 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 = 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 ovsdbTpIid) { + private void processRemovedTp(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp, + InstanceIdentifier 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 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 requiredTunnelTypes) { diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanGpeTunnelType.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanGpeTunnelType.java index e3e5d96db..0408db766 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanGpeTunnelType.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanGpeTunnelType.java @@ -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 optionsList; private static final Class 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; diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanTunnelType.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanTunnelType.java index fcf988224..c3e7b8756 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanTunnelType.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/VxlanTunnelType.java @@ -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; diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/EndpointHelper.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/EndpointHelper.java index 58a709ace..7df6a65aa 100755 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/EndpointHelper.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/EndpointHelper.java @@ -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 { diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/InventoryHelper.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/InventoryHelper.java index 76545d13a..7498c61cd 100755 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/InventoryHelper.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/InventoryHelper.java @@ -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 tpIid, - DataBroker dataBroker) { + OvsdbTerminationPointAugmentation ovsdbTp, InstanceIdentifier 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 requiredTunnelTypes, DataBroker dataBroker) { + public static boolean checkOfOverlayConfig(String nodeIdString, List 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 nodeExternalInterfacesIid = InstanceIdentifier.builder( - Nodes.class) + InstanceIdentifier 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 ofOverlayNodeIid = InstanceIdentifier.builder( - Nodes.class) + InstanceIdentifier ofOverlayNodeIid = InstanceIdentifier.builder(Nodes.class) .child(Node.class, new NodeKey(new NodeId(nodeIdString))) .augmentation(OfOverlayNodeConfig.class) .build(); ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction(); - Optional overlayConfig = readFromDs(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, transaction ); + Optional 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 ofOverlayNodeIid = InstanceIdentifier.builder( - Nodes.class) + private static boolean addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) { + InstanceIdentifier 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 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 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 tunnelList = new ArrayList(); - List existingTunnels = new ArrayList(); + + + // 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 existingTunnels = new HashSet(); + 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(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); } } diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/OvsdbHelper.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/OvsdbHelper.java index 37d8b3b05..c2badde2a 100755 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/OvsdbHelper.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/OvsdbHelper.java @@ -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); } diff --git a/neutron-ovsdb/src/test/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TunnelTypeTest.java b/neutron-ovsdb/src/test/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TunnelTypeTest.java index 031f8ebc2..214186cac 100644 --- a/neutron-ovsdb/src/test/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TunnelTypeTest.java +++ b/neutron-ovsdb/src/test/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TunnelTypeTest.java @@ -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 diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java index 90d88c948..73fa28c5f 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java @@ -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 index 000000000..be88537d2 --- /dev/null +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ChainActionFlows.java @@ -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); + } +} diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.java index 25c3985a4..8bdc97691 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.java @@ -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; } diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapper.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapper.java index a37a3b61b..d2d23662d 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapper.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapper.java @@ -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 actionBuilderList = new ArrayList(); - - Action action = SubjectFeatures.getAction(AllowAction.DEFINITION.getId()); - actionBuilderList = action.updateAction(actionBuilderList, new HashMap(), 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; } } diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowIdUtils.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowIdUtils.java index 51d38f49a..0f10741a8 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowIdUtils.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowIdUtils.java @@ -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) { diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java index 3965fcc47..3c68563c4 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java @@ -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 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 existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList(); - ArrayList 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 existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList(); - ArrayList 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 existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList(); - ArrayList 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 existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList(); - ArrayList 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 extensions = new ArrayList<>(); - for (RegMatch rm : matches) { - Class 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 getExistingGeneralAugMatchNodesNodeTableFlow(MatchBuilder match) { + ArrayList extensions = new ArrayList<>(); + if (match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class) != null) { + List existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class) + .getExtensionList(); + if (existingExtensions != null && !existingExtensions.isEmpty()) { + extensions.addAll(existingExtensions); + } + } + return extensions; + } + + private static GeneralAugMatchNodesNodeTableFlow addExtensionKeyAugmentationMatcher( + Class key, NxAugMatchNodesNodeTableFlow am, MatchBuilder match) { + List 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 * diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java index d03f943d8..9160d00c5 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java @@ -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 visitedPairs = new HashSet<>(); + HashSet visitedPairs = new HashSet<>(); + HashSet visitedReversePairs = new HashSet<>(); // Used for ARP flows Set 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> activeRulesByConstraints: getActiveRulesBetweenEps(policy, dstEp, srcEp)) { + for (Cell> activeRulesByConstraints : getActiveRulesBetweenEps( + policy, dstEp, srcEp)) { Set sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey() .getL3EpPrefixes()); Set 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> activeRulesByConstraints : getActiveRulesBetweenEps(policy, srcEp, dstEp)) { + for (Cell> activeRulesByConstraints : getActiveRulesBetweenEps( + policy, srcEp, dstEp)) { Set sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey() .getL3EpPrefixes()); Set 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 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 rgs, CgPair p) { + private void syncPolicy(FlowMap flowMap, NetworkElements netElements, List 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 actionBuilderList = new ArrayList(); 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(), 0, netElements); } Map 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> derivedParamsByName = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(paramsFromClassifier); - String baseId = createBaseFlowId(direction, cgPair, priority); List flowMatchBuilders = new ArrayList<>(); for (Map params : derivedParamsByName) { List 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>> - getActiveRulesBetweenEps(Policy policy, Endpoint consEp, Endpoint provEp) { + public List>> getActiveRulesBetweenEps(Policy policy, + Endpoint consEp, Endpoint provEp) { List>> rulesWithEpConstraints = new ArrayList<>(); if (policy.getRuleMap() != null) { for (Cell> 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 consumerEicIpPrefixes; + private final Set 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 sIpPrefixes; - private final Set dIpPrefixes; + public NodeId getProviderEpNodeId() { + return providerEpNodeId; + } - public CgPair(int sepg, int depg, int scgId, int dcgId, Set sIpPrefixes, Set dIpPrefixes) { + public PolicyPair(int consumerEpgId, int providerEpgId, int consumerCondGrpId, int providerCondGrpId, + Set consumerEicIpPrefixes, Set 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; } + } } diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PortSecurity.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PortSecurity.java index 93a515d41..5e6991387 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PortSecurity.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PortSecurity.java @@ -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; diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/SourceMapper.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/SourceMapper.java index 34f382783..f67851c18 100755 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/SourceMapper.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/SourceMapper.java @@ -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 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 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); -// } -// } } } diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/node/SwitchManager.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/node/SwitchManager.java index a211147e6..3ec0a16aa 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/node/SwitchManager.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/node/SwitchManager.java @@ -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 tunnelType) { + public synchronized Collection getTunnelPorts(NodeId nodeId) { + Collection ncIds = new HashSet<>(); + SwitchState state = switches.get(nodeId); + if (state == null ) { + return Collections.emptySet(); + } + ncIds = Collections2.transform(state.tunnelBuilderByType.values(),new Function() { + + @Override + public NodeConnectorId apply(TunnelBuilder input) { + return input.getNodeConnectorId(); + } + }); + + return ncIds; + } + public synchronized NodeConnectorId getTunnelPort(NodeId nodeId, Class 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 tunnelType) { + public synchronized IpAddress getTunnelIP(NodeId nodeId, Class 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, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) { - FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue(); - if (fcnc.getName() == null) { - continue; - } - InstanceIdentifier 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, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) { + FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue(); + if (fcnc.getName() == null) { + continue; + } + InstanceIdentifier 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; diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Action.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Action.java index bb0641eeb..4e615fe2b 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Action.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/Action.java @@ -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 updateAction(List actions, Map params, Integer order, - NetworkElements netElements); + NetworkElements netElements, + PolicyPair policyPair, + FlowMap flowMap, + OfContext ctx); } diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/AllowAction.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/AllowAction.java index 4b75328bd..ea7703ada 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/AllowAction.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/AllowAction.java @@ -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 updateAction(List actions, Map 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; } diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ChainAction.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ChainAction.java index d480f6dfe..fc851b01d 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ChainAction.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sf/ChainAction.java @@ -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 updateAction(List actions, - Map params, - Integer order, - NetworkElements netElements) { + public List updateAction(List actions, Map 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 addActionBuilder(List 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 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 paramValue) { + private boolean isValidGbpChain(List 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 addActionBuilder(List 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 index 4b6b2df1b..000000000 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcDataStoreHelper.java +++ /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 readFromDs(LogicalDatastoreType store,InstanceIdentifier iid, ReadTransaction rTx) { - U ret = null; - Optional optionalDataObject; - CheckedFuture, 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 submitFuture = wTx.submit(); - try { - submitFuture.checkedGet(); - return true; - } catch (TransactionCommitFailedException e) { - LOG.warn("Transaction commit failed to DS.", e); - return false; - } - } - -} diff --git a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcIidFactory.java b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcIidFactory.java index 3d9bffeea..1e067e83d 100644 --- a/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcIidFactory.java +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcIidFactory.java @@ -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 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 index 000000000..b6f61b739 --- /dev/null +++ b/renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/sfcutils/SfcNshHeader.java @@ -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; + } + + } + + + +}