- Added specific ChainActionFlow class for handling of chain specific flows.
- Added simultaneous multiencap support (VXLAN, VXLANGPE)
- Ensure non-symmetric chain, path. Not supported Li
- Added setting of C1/C2 in ExternalTable per destination
- "visited" pairs fixed for assymetry
Change-Id: Icf9118dec65a8d1e57a24d5702c9334b3b33aea3
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
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";
return false;
}
+ protected String getDestPort(OvsdbTerminationPointAugmentation tpAugmentation) {
+ List<Options> options = tpAugmentation.getOptions();
+ if (options == null) {
+ return null;
+ }
+ for (Options opt: options) {
+ if (DESTPORT_KEY.equals(opt.getOption())) {
+ return opt.getValue();
+ }
+ }
+ return null;
+ }
+
/**
* Return the {@link List<Options>} valid for this tunnel type
*
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;
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 {
private List<AbstractTunnelType> createSupportedTunnelsList() {
List<AbstractTunnelType> required = new ArrayList<AbstractTunnelType>();
- // required.add(new VxlanGpeTunnelType());
required.add(new VxlanTunnelType());
+ required.add(new VxlanGpeTunnelType());
return Collections.unmodifiableList(required);
}
if (old instanceof OvsdbTerminationPointAugmentation) {
OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation) old;
@SuppressWarnings("unchecked")
- InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid =
- (InstanceIdentifier<OvsdbTerminationPointAugmentation>) iid;
+ InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid = (InstanceIdentifier<OvsdbTerminationPointAugmentation>) iid;
OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker);
if (ovsdbBridge != null) {
processRemovedTp(ovsdbBridge, ovsdbTp, ovsdbTpIid);
/*
* Check if Neutron External port was announed in Node before TerminationPoint it refers to
- * was actually instantiated. This may or may not have external information in the future, hence
+ * was actually instantiated. This may or may not have external information in the future,
+ * hence
* not process as IF/ELSE externalID.
*/
ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
Optional<Node> node = readFromDs(LogicalDatastoreType.OPERATIONAL, nodeIid, transaction);
- if (node.isPresent()
- && node.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
+ if (node.isPresent() && node.get().getAugmentation(OvsdbNodeAugmentation.class) != null) {
OvsdbNodeAugmentation ovsdbNodeAug = node.get().getAugmentation(OvsdbNodeAugmentation.class);
if (getProviderMapping(ovsdbNodeAug) != null) {
processNodeNotification(ovsdbNodeAug);
* 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();
* @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
* @param ovsdbTpIid termination point's IID {@link InstanceIdentifier}
*/
- private void processRemovedTp(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp, InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid) {
+ private void processRemovedTp(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp,
+ InstanceIdentifier<OvsdbTerminationPointAugmentation> ovsdbTpIid) {
checkNotNull(ovsdbBridge);
if (ovsdbBridge.getBridgeName().getValue().equals(ovsdbTp.getName())) {
- LOG.debug("Termination Point {} same as Bridge {}. Not processing.", ovsdbTp.getName(), ovsdbBridge.getBridgeName().getValue());
+ LOG.debug("Termination Point {} same as Bridge {}. Not processing.", ovsdbTp.getName(),
+ ovsdbBridge.getBridgeName().getValue());
return;
}
*
* @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);
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());
}
/**
+ * Check to see if the {@link OvsdbTerminationPointAugmentation} is also a Tunnel port that we
+ * care about.
+ *
+ * @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+ * @param requiredTunnelTypes {@link List} of tunnel types
+ */
+ private static AbstractTunnelType getTunnelType(OvsdbTerminationPointAugmentation ovsdbTp,
+ List<AbstractTunnelType> requiredTunnelTypes) {
+ if (ovsdbTp.getInterfaceType() != null) {
+ for (AbstractTunnelType tunnelType : requiredTunnelTypes) {
+ if (tunnelType.isValidTunnelPort(ovsdbTp)) {
+ return tunnelType;
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
* Check to see if the {@link OvsdbTerminationPointAugmentation}
* is also a Tunnel port that we care about.
*
* @param ovsdbTp {@link OvsdbTerminationPointAugmentation}
+ *
* @param requiredTunnelTypes {@link List} of tunnel types
+ *
* @return true if it's a required tunnel port, false if it isn't
*/
private boolean isTunnelPort(OvsdbTerminationPointAugmentation ovsdbTp, List<AbstractTunnelType> requiredTunnelTypes) {
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";
private static final String NSH_NSHC3_VALUE = "flow";
private static final String NSH_NSHC4_KEY = "nshc4";
private static final String NSH_NSHC4_VALUE = "flow";
+ private static final String DESTPORT_KEY = "dst_port";
+ private static final String DESTPORT_VALUE = VXLAN_GPE_PORT_NUMBER.toString();
- private static final String VXLAN_GPE_TUNNEL_PREFIX = "vxlangpe-";
- private static final Integer VXLAN_GPE_PORT_NUMBER = 6633;
private final PortNumber udpTunnelPort;
private final List<Options> optionsList;
private static final Class<? extends TunnelTypeBase> tunnelType = TunnelTypeVxlanGpe.class;
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);
}
@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;
@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;
*/
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 {
/*
- * 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,
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;
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";
*/
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.
}
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;
* @return String representation of the Inventory NodeConnectorId, null if it fails
*/
public static String getInventoryNodeConnectorIdString(String inventoryNodeId,
- OvsdbTerminationPointAugmentation ovsdbTp,
- InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid,
- DataBroker dataBroker) {
+ OvsdbTerminationPointAugmentation ovsdbTp, InstanceIdentifier<OvsdbTerminationPointAugmentation> tpIid,
+ DataBroker dataBroker) {
Long ofport = null;
- if (ovsdbTp.getOfport() != null && ovsdbTp.getOfport()>MAX_OF_PORT) {
- LOG.debug("Invalid OpenFlow port {} for {}",ovsdbTp.getOfport(), ovsdbTp);
+ if (ovsdbTp.getOfport() != null && ovsdbTp.getOfport() > MAX_OF_PORT) {
+ LOG.debug("Invalid OpenFlow port {} for {}", ovsdbTp.getOfport(), ovsdbTp);
return null;
}
if (ovsdbTp.getOfport() == null) {
- OvsdbTerminationPointAugmentation readOvsdbTp =
- getOvsdbTerminationPoint(tpIid, dataBroker);
- if (readOvsdbTp == null
- || readOvsdbTp.getOfport() == null
- || readOvsdbTp.getOfport() >MAX_OF_PORT) {
- LOG.debug("Couldn't get OpenFlow port for {}",ovsdbTp);
+ OvsdbTerminationPointAugmentation readOvsdbTp = getOvsdbTerminationPoint(tpIid, dataBroker);
+ if (readOvsdbTp == null || readOvsdbTp.getOfport() == null || readOvsdbTp.getOfport() > MAX_OF_PORT) {
+ LOG.debug("Couldn't get OpenFlow port for {}", ovsdbTp);
return null;
}
ofport = readOvsdbTp.getOfport();
}
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;
*
* @return true if tunnel types are present, false otherwise
*/
- public static boolean checkOfOverlayConfig(String nodeIdString,
- List<AbstractTunnelType> requiredTunnelTypes, DataBroker dataBroker) {
+ public static boolean checkOfOverlayConfig(String nodeIdString, List<AbstractTunnelType> requiredTunnelTypes,
+ DataBroker dataBroker) {
OfOverlayNodeConfig config = getOfOverlayConfig(nodeIdString, dataBroker);
if (config == null || config.getTunnel() == null) {
- LOG.debug("No OfOverlay config for {}",nodeIdString);
+ LOG.debug("No OfOverlay config for {}", nodeIdString);
return false;
}
* 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;
}
public static void addOfOverlayExternalPort(String nodeIdString, NodeConnectorId ncId, DataBroker dataBroker) {
- InstanceIdentifier<ExternalInterfaces> nodeExternalInterfacesIid = InstanceIdentifier.builder(
- Nodes.class)
+ InstanceIdentifier<ExternalInterfaces> nodeExternalInterfacesIid = InstanceIdentifier.builder(Nodes.class)
.child(Node.class, new NodeKey(new NodeId(nodeIdString)))
.augmentation(OfOverlayNodeConfig.class)
- .child(ExternalInterfaces.class,new ExternalInterfacesKey(ncId))
+ .child(ExternalInterfaces.class, new ExternalInterfacesKey(ncId))
.build();
- ExternalInterfaces externalInterfaces = new ExternalInterfacesBuilder()
- .setKey(new ExternalInterfacesKey(ncId))
- .setNodeConnectorId(ncId)
- .build();
+ ExternalInterfaces externalInterfaces = new ExternalInterfacesBuilder().setKey(new ExternalInterfacesKey(ncId))
+ .setNodeConnectorId(ncId)
+ .build();
WriteTransaction transaction = dataBroker.newReadWriteTransaction();
transaction.put(LogicalDatastoreType.CONFIGURATION, nodeExternalInterfacesIid, externalInterfaces, true);
submitToDs(transaction);
- LOG.trace("Added external interface node connector {} to node {}", ncId.getValue(),nodeIdString);
+ LOG.trace("Added external interface node connector {} to node {}", ncId.getValue(), nodeIdString);
}
public static OfOverlayNodeConfig getOfOverlayConfig(String nodeIdString, DataBroker dataBroker) {
- InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
- Nodes.class)
+ InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(Nodes.class)
.child(Node.class, new NodeKey(new NodeId(nodeIdString)))
.augmentation(OfOverlayNodeConfig.class)
.build();
ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();
- Optional<OfOverlayNodeConfig> overlayConfig = readFromDs(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, transaction );
+ Optional<OfOverlayNodeConfig> overlayConfig = readFromDs(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid,
+ transaction);
if (overlayConfig.isPresent()) {
return overlayConfig.get();
}
return null;
}
- private static void addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) {
- InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(
- Nodes.class)
+ private static boolean addOfOverlayAugmentation(OfOverlayNodeConfig config, String nodeIdString, DataBroker dataBroker) {
+ InstanceIdentifier<OfOverlayNodeConfig> ofOverlayNodeIid = InstanceIdentifier.builder(Nodes.class)
.child(Node.class, new NodeKey(new NodeId(nodeIdString)))
.augmentation(OfOverlayNodeConfig.class)
.build();
WriteTransaction transaction = dataBroker.newReadWriteTransaction();
transaction.put(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, config, true);
- submitToDs(transaction);
- }
-
- private static void addTunnelToOfOverlayAugmentation(Tunnel tunnel, String nodeIdString, DataBroker dataBroker) {
- InstanceIdentifier<Tunnel> ofOverlayNodeIid = InstanceIdentifier.builder(
- Nodes.class)
- .child(Node.class, new NodeKey(new NodeId(nodeIdString)))
- .augmentation(OfOverlayNodeConfig.class)
- .child(Tunnel.class, new TunnelKey(tunnel.getKey()))
- .build();
-
- WriteTransaction transaction = dataBroker.newReadWriteTransaction();
- transaction.put(LogicalDatastoreType.CONFIGURATION, ofOverlayNodeIid, tunnel, true);
- if(submitToDs(transaction)) {
- LOG.info("addTunnelToOfOverlayAugmentation: Wrote tunnel {}",tunnel.getKey());
- } else {
- LOG.error("addTunnelToOfOverlayAugmentation: submitToDs failed for tunnel {}",tunnel.getKey());
- }
+ return submitToDs(transaction);
}
/**
* Update the {@link OfOverlayConfig} of an Inventory Node
* using the new tunnel state.
*
+ * @param ip
* @param nodeIdString
- * @param tunnels
+ * @param nodeConnectorIdString
+ * @param tunnelType
* @param dataBroker
*/
- public static void updateOfOverlayConfig(IpAddress ip, String nodeIdString,
- String nodeConnectorIdString, List<AbstractTunnelType> tunnels, DataBroker dataBroker) {
+ public static void updateOfOverlayConfig(IpAddress ip, String nodeIdString, String nodeConnectorIdString,
+ AbstractTunnelType tunnelType, DataBroker dataBroker) {
- if ((ip == null) || (nodeIdString == null)
- || (nodeConnectorIdString == null)) {
+ if ((ip == null) || (nodeIdString == null) || (nodeConnectorIdString == null)) {
LOG.debug("Can't update OfOverlay: requisite information not present");
return;
}
NodeConnectorId nodeConnectorId = new NodeConnectorId(nodeConnectorIdString);
- List<Tunnel> tunnelList = new ArrayList<Tunnel>();
- List<Tunnel> existingTunnels = new ArrayList<Tunnel>();
+
+
+ // Pull existing augmentation
OfOverlayNodeConfig ofConfig = getOfOverlayConfig(nodeIdString, dataBroker);
- if (ofConfig != null && ofConfig.getTunnel() != null) {
- existingTunnels = ofConfig.getTunnel();
+
+ // If it exists, use it in new augmentation constructor, else new augmentation
+ OfOverlayNodeConfigBuilder ofOverlayNodeConfigBuilder;
+ Set<Tunnel> existingTunnels = new HashSet<Tunnel>();
+ if (ofConfig != null) {
+ ofOverlayNodeConfigBuilder = new OfOverlayNodeConfigBuilder(ofConfig);
+ if(ofConfig.getTunnel() != null) {
+ existingTunnels.addAll(ofConfig.getTunnel());
+ }
+ } else {
+ ofOverlayNodeConfigBuilder = new OfOverlayNodeConfigBuilder();
}
+
+ // Determine if this is an update to existing tunnel of this type or a new tunnel
boolean tunnelsUpdated = false;
- for (AbstractTunnelType tunnelType: tunnels) {
- boolean tunnelFound = false;
- for (Tunnel currentTun: existingTunnels) {
- if (tunnelType.getTunnelType().equals(currentTun.getTunnelType())) {
- // tunnel update
- TunnelBuilder tunnelBuilder = new TunnelBuilder(currentTun);
- tunnelBuilder.setIp(ip);
- tunnelBuilder.setPort(tunnelType.getPortNumber());
- tunnelBuilder.setNodeConnectorId(nodeConnectorId);
- tunnelList.add(tunnelBuilder.build());
- tunnelFound = true;
- tunnelsUpdated = true;
- }
- }
- // new tunnel
- if (tunnelFound == false) {
- TunnelBuilder tunnelBuilder = new TunnelBuilder();
+ TunnelBuilder tunnelBuilder = new TunnelBuilder();
+
+ boolean tunnelFound = false;
+ for (Tunnel currentTun : existingTunnels) {
+ if (tunnelType.getTunnelType().equals(currentTun.getTunnelType())) {
+ // tunnel update
tunnelBuilder.setIp(ip);
tunnelBuilder.setPort(tunnelType.getPortNumber());
tunnelBuilder.setNodeConnectorId(nodeConnectorId);
- tunnelBuilder.setTunnelType(tunnelType.getTunnelType());
- tunnelList.add(tunnelBuilder.build());
+ tunnelFound = true;
tunnelsUpdated = true;
+ break;
}
}
- if (tunnelsUpdated == true) {
- for (Tunnel tunnel: tunnelList) {
- addTunnelToOfOverlayAugmentation(tunnel, nodeIdString, dataBroker);
- }
+ // new tunnel
+ if (tunnelFound == false) {
+ tunnelBuilder.setIp(ip);
+ tunnelBuilder.setPort(tunnelType.getPortNumber());
+ tunnelBuilder.setNodeConnectorId(nodeConnectorId);
+ tunnelBuilder.setTunnelType(tunnelType.getTunnelType());
+ tunnelsUpdated = true;
+ }
+
+ // Nothing was updated, nothing to see here, move along...
+ if (tunnelsUpdated == false) {
+ return;
+ }
+
+ existingTunnels.add(tunnelBuilder.build());
+
+ // Update the OfOverlayNodeConfig with the new tunnel information
+ OfOverlayNodeConfig newConfig=ofOverlayNodeConfigBuilder.setTunnel(new ArrayList<Tunnel>(existingTunnels)).build();
+ if (addOfOverlayAugmentation(newConfig, nodeIdString, dataBroker)) {
+ LOG.trace("updateOfOverlayConfig - Added Tunnel: {} to Node: {} at NodeConnector: {}",tunnelBuilder.build(), nodeIdString, nodeConnectorIdString);
+ return;
+ } else {
+ LOG.error("updateOfOverlayConfig - could not write OfOverlayNodeConfig: {} to datastore.", newConfig);
}
}
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);
}
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";
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
if (!wrappedFlows.contains(wFlow)) {
tableBuilder.getFlow().add(Preconditions.checkNotNull(flow));
+ } else {
+ LOG.debug("Flow already exists in FlowMap - {}", flow);
}
}
--- /dev/null
+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);
+ }
+}
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);
}
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;
}
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;
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;
// Default drop all
flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
- // Drop IP traffic that doesn't match a source IP rule
- flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(2), FlowUtils.ARP, TABLE_ID));
- flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(2), FlowUtils.IPv4, TABLE_ID));
- flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(2), FlowUtils.IPv6, TABLE_ID));
- l3flow(flowMap,nodeId, 100, true);
- l3flow(flowMap,nodeId, 200, false);
- }
-
- private void l3flow(FlowMap flowMap, NodeId nodeId, Integer priority, boolean arp) {
-
- List<ActionBuilder> actionBuilderList = new ArrayList<ActionBuilder>();
-
- Action action = SubjectFeatures.getAction(AllowAction.DEFINITION.getId());
- actionBuilderList = action.updateAction(actionBuilderList, new HashMap<String, Object>(), 0, null);
+ /*
+ * Default Egress flow. Other methods may write to this table to augment egress
+ * functionality, such as bypassing/utilising the NAT table, or ServiceFunctionChaining
+ */
+ flowMap.writeFlow(nodeId, TABLE_ID, defaultFlow());
- Layer3Match m = null;
- Long etherType = null;
-
- if (arp) {
- etherType = FlowUtils.ARP;
- } else {
- etherType = FlowUtils.IPv4;
- }
+ }
- Match match = new MatchBuilder().setEthernetMatch(FlowUtils.ethernetMatch(null, null, etherType))
- .setLayer3Match(m)
- .build();
- FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "ExternalMapper", match);
- Flow flow = base().setPriority(priority)
+ private Flow defaultFlow() {
+ FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "defaultExternalFlow", null);
+ Flow flow = base().setPriority(100)
.setId(flowid)
- .setMatch(match)
- .setInstructions(instructions(applyActionIns(actionBuilderList)))
+ .setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))))
.build();
-
- flowMap.writeFlow(nodeId, TABLE_ID, flow);
+ return flow;
}
}
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;
}
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) {
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;
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;
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;
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;
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();
}
public static Action nxMoveRegTunDstToNshc1() {
- return nxMoveRegAction(new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(),31,false);
+ return nxMoveRegAction(new SrcNxTunIpv4DstCaseBuilder().setNxTunIpv4Dst(Boolean.TRUE).build(),
+ new DstNxNshc1CaseBuilder().setNxNshc1Dst(Boolean.TRUE).build(), 31, false);
}
public static Action nxMoveTunIdtoNshc2() {
- return nxMoveRegAction(new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(), new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(),31,false);
+ return nxMoveRegAction(new SrcNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(),
+ new DstNxNshc2CaseBuilder().setNxNshc2Dst(Boolean.TRUE).build(), 31, false);
}
+
public static Action nxMoveRegTunIdAction(Class<? extends NxmNxReg> src, boolean groupBucket) {
return nxMoveRegAction(new SrcNxRegCaseBuilder().setNxReg(src).build(),
new DstNxTunIdCaseBuilder().setNxTunId(Boolean.TRUE).build(), 31, groupBucket);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
- // TODO alagalah Be/Li: Once OFP yang refactored to support container/grouping similar to nxreg
- // we can follow same pattern. For now its match/set per nsh header
public static void addNxNshc1RegMatch(MatchBuilder match, Long value) {
- List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
- ArrayList<ExtensionList> extensions = new ArrayList<>();
- if(existingExtensions != null && !existingExtensions.isEmpty()) {
- extensions.addAll(existingExtensions);
- }
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc1(
new NxmNxNshc1Builder().setValue(value).build()).build();
-
- extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc1Key.class)
- .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build());
-
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- extensions).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc1Key.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
public static void addNxNshc2RegMatch(MatchBuilder match, Long value) {
- List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
- ArrayList<ExtensionList> extensions = new ArrayList<>();
- if(existingExtensions != null && !existingExtensions.isEmpty()) {
- extensions.addAll(existingExtensions);
- }
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc2(
new NxmNxNshc2Builder().setValue(value).build()).build();
-
- extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc2Key.class)
- .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build());
-
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- extensions).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc2Key.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
public static void addNxNshc3RegMatch(MatchBuilder match, Long value) {
- List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
- ArrayList<ExtensionList> extensions = new ArrayList<>();
- if(existingExtensions != null && !existingExtensions.isEmpty()) {
- extensions.addAll(existingExtensions);
- }
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc3(
new NxmNxNshc3Builder().setValue(value).build()).build();
-
- extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc3Key.class)
- .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build());
-
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- extensions).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc3Key.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
public static void addNxNshc4RegMatch(MatchBuilder match, Long value) {
- List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class).getExtensionList();
- ArrayList<ExtensionList> extensions = new ArrayList<>();
- if(existingExtensions != null && !existingExtensions.isEmpty()) {
- extensions.addAll(existingExtensions);
- }
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNshc4(
new NxmNxNshc4Builder().setValue(value).build()).build();
-
- extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxNshc4Key.class)
- .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build());
-
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- extensions).build();
- match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
- }
-
- public static void addNxNshcMatch(MatchBuilder match, RegMatch... matches) {
- ArrayList<ExtensionList> extensions = new ArrayList<>();
- for (RegMatch rm : matches) {
- Class<? extends ExtensionKey> key;
- if (NxmNxReg0.class.equals(rm.reg)) {
- key = NxmNxReg0Key.class;
- } else if (NxmNxReg1.class.equals(rm.reg)) {
- key = NxmNxReg1Key.class;
- } else if (NxmNxReg2.class.equals(rm.reg)) {
- key = NxmNxReg2Key.class;
- } else if (NxmNxReg3.class.equals(rm.reg)) {
- key = NxmNxReg3Key.class;
- } else if (NxmNxReg4.class.equals(rm.reg)) {
- key = NxmNxReg4Key.class;
- } else if (NxmNxReg5.class.equals(rm.reg)) {
- key = NxmNxReg5Key.class;
- } else if (NxmNxReg6.class.equals(rm.reg)) {
- key = NxmNxReg6Key.class;
- } else {
- key = NxmNxReg7Key.class;
- }
- NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxReg(
- new NxmNxRegBuilder().setReg(rm.reg).setValue(rm.value).build()).build();
- extensions.add(new ExtensionListBuilder().setExtensionKey(key)
- .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build());
- }
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- extensions).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNshc4Key.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
public static void addNxTunIdMatch(MatchBuilder match, int tunId) {
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxTunId(
new NxmNxTunIdBuilder().setValue(BigInteger.valueOf(tunId)).build()).build();
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxTunIdKey.class)
- .setExtension(
- new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build())).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxTunIdKey.class, am, match);
+ match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
+ }
+
+ public static void addNxTunIpv4DstMatch(MatchBuilder match, Ipv4Address ipv4Address) {
+ NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxTunIpv4Dst(
+ new NxmNxTunIpv4DstBuilder().setIpv4Address(ipv4Address).build()).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxTunIpv4DstKey.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
public static void addNxNsiMatch(MatchBuilder match, short nsi) {
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNsi(
new NxmNxNsiBuilder().setNsi(nsi).build()).build();
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxNsiKey.class)
- .setExtension(
- new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build())).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNsiKey.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
public static void addNxNspMatch(MatchBuilder match, Long nsp) {
NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxNsp(
new NxmNxNspBuilder().setValue(nsp).build()).build();
- GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(
- ImmutableList.of(new ExtensionListBuilder().setExtensionKey(NxmNxNspKey.class)
- .setExtension(
- new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
- .build())).build();
+ GeneralAugMatchNodesNodeTableFlow m = addExtensionKeyAugmentationMatcher(NxmNxNspKey.class, am, match);
match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m);
}
return emb.build();
}
+ private static List<ExtensionList> getExistingGeneralAugMatchNodesNodeTableFlow(MatchBuilder match) {
+ ArrayList<ExtensionList> extensions = new ArrayList<>();
+ if (match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class) != null) {
+ List<ExtensionList> existingExtensions = match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class)
+ .getExtensionList();
+ if (existingExtensions != null && !existingExtensions.isEmpty()) {
+ extensions.addAll(existingExtensions);
+ }
+ }
+ return extensions;
+ }
+
+ private static GeneralAugMatchNodesNodeTableFlow addExtensionKeyAugmentationMatcher(
+ Class<? extends ExtensionKey> key, NxAugMatchNodesNodeTableFlow am, MatchBuilder match) {
+ List<ExtensionList> extensions = getExistingGeneralAugMatchNodesNodeTableFlow(match);
+ extensions.add(new ExtensionListBuilder().setExtensionKey(key)
+ .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build())
+ .build());
+ return new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(extensions).build();
+ }
+
/**
* Parse an OF port number from a node connector ID
*
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;
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;
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;
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;
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;
flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
- NodeConnectorId tunPort = SwitchManager.getTunnelPort(nodeId, TunnelTypeVxlan.class);
+ NodeConnectorId tunPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
if (tunPort != null) {
flowMap.writeFlow(nodeId, TABLE_ID, allowFromTunnel(tunPort));
}
- HashSet<CgPair> visitedPairs = new HashSet<>();
+ HashSet<PolicyPair> visitedPairs = new HashSet<>();
+ HashSet<PolicyPair> visitedReversePairs = new HashSet<>();
// Used for ARP flows
Set<Integer> fdIds = new HashSet<>();
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,
int depgId = dstEpFwdCxtOrds.getEpgId();
int scgId = srcEpFwdCxtOrds.getCgId();
int sepgId = srcEpFwdCxtOrds.getEpgId();
- NetworkElements netElements = new NetworkElements(srcEp, dstEp, nodeId, ctx, policyInfo);
+
fdIds.add(srcEpFwdCxtOrds.getFdId());
+ NetworkElements netElements = new NetworkElements(srcEp, dstEp, nodeId, ctx, policyInfo);
Policy policy = policyInfo.getPolicy(dstEpgKey, srcEpgKey);
- for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints: getActiveRulesBetweenEps(policy, dstEp, srcEp)) {
+ for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
+ policy, dstEp, srcEp)) {
Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
.getL3EpPrefixes());
Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
.getL3EpPrefixes());
- CgPair p = new CgPair(depgId, sepgId, dcgId, scgId, dIpPrefixes, sIpPrefixes);
- if (visitedPairs.contains(p))
+ PolicyPair policyPair = new PolicyPair(depgId, sepgId, dcgId, scgId, dIpPrefixes,
+ sIpPrefixes, netElements.getDstNodeId(), netElements.getSrcNodeId());
+ if (visitedPairs.contains(policyPair)) {
+ LOG.trace("PolicyEnforcer: Already visited PolicyPair {}, endpoints {} {} skipped",
+ policyPair, srcEp.getKey(), dstEp.getKey());
continue;
- visitedPairs.add(p);
- syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), p);
+ } else {
+ LOG.trace("PolicyEnforcer: Visiting PolicyPair {} endpoints {} {}", policyPair,
+ srcEp.getKey(), dstEp.getKey());
+ visitedPairs.add(policyPair);
+ }
+ syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), policyPair);
}
// Reverse
policy = policyInfo.getPolicy(srcEpgKey, dstEpgKey);
- for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(policy, srcEp, dstEp)) {
+ for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> activeRulesByConstraints : getActiveRulesBetweenEps(
+ policy, srcEp, dstEp)) {
Set<IpPrefix> sIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getRowKey()
.getL3EpPrefixes());
Set<IpPrefix> dIpPrefixes = Policy.getIpPrefixesFrom(activeRulesByConstraints.getColumnKey()
.getL3EpPrefixes());
- CgPair p = new CgPair(sepgId, depgId, scgId, dcgId, sIpPrefixes, dIpPrefixes);
- if (visitedPairs.contains(p))
+ PolicyPair policyPair = new PolicyPair(sepgId, depgId, scgId, dcgId, sIpPrefixes,
+ dIpPrefixes, netElements.getSrcNodeId(), netElements.getDstNodeId());
+ if (visitedReversePairs.contains(policyPair)) {
+ LOG.trace(
+ "PolicyEnforcer: Reverse: Already visited PolicyPair {}, endpoints {} {} skipped",
+ policyPair, srcEp.getKey(), dstEp.getKey());
continue;
- visitedPairs.add(p);
- syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), p);
+ } else {
+ LOG.trace("PolicyEnforcer: Reverse: Visiting: PolicyPair {} via endpoints {} {}",
+ policyPair, srcEp.getKey(), dstEp.getKey());
+ visitedReversePairs.add(policyPair);
+
+ }
+ syncPolicy(flowMap, netElements, activeRulesByConstraints.getValue(), policyPair);
}
}
}
}
// Allow same EPG
- // Set<Endpoint> visitedEps = new HashSet<>();
for (Endpoint srcEp : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
- // visitedEps.add(srcEp);
for (EgKey srcEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(srcEp)) {
IndexedTenant tenant = ctx.getPolicyResolver().getTenant(srcEpgKey.getTenantId());
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,
}
- private void syncPolicy(FlowMap flowMap, NetworkElements netElements, List<RuleGroup> rgs, CgPair p) {
+ private void syncPolicy(FlowMap flowMap, NetworkElements netElements, List<RuleGroup> rgs, PolicyPair policyPair) {
int priority = 65000;
for (RuleGroup rg : rgs) {
TenantId tenantId = rg.getContractTenant().getId();
IndexedTenant tenant = ctx.getPolicyResolver().getTenant(tenantId);
for (Rule r : rg.getRules()) {
- syncDirection(flowMap, netElements, tenant, p, r, Direction.In, priority);
- syncDirection(flowMap, netElements, tenant, p, r, Direction.Out, priority);
+ syncDirection(flowMap, netElements, tenant, policyPair, r, Direction.In, priority);
+ syncDirection(flowMap, netElements, tenant, policyPair, r, Direction.Out, priority);
priority -= 1;
}
}
- private void syncDirection(FlowMap flowMap, NetworkElements netElements, IndexedTenant contractTenant, CgPair cgPair, Rule rule,
- Direction direction, int priority) {
+ private void syncDirection(FlowMap flowMap, NetworkElements netElements, IndexedTenant contractTenant,
+ PolicyPair policyPair, Rule rule, Direction direction, int priority) {
/*
* Create the ordered action list. The implicit action is "allow", and
* is therefore always in the list
- *
- * TODO: revisit implicit vs. default for "allow" TODO: look into
- * incorporating operational policy for actions
*/
- // TODO: can pass Comparator ActionRefComparator to List constructor, rather than
- // referencing in sort
List<ActionBuilder> actionBuilderList = new ArrayList<ActionBuilder>();
if (rule.getActionRef() != null) {
/*
/*
* Convert the GBP Action to one or more OpenFlow Actions
*/
- actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(),netElements);
+ if (!(actionRefList.indexOf(actionRule) == (actionRefList.size() - 1) && action.equals(SubjectFeatures.getAction(AllowAction.DEFINITION.getId())))) {
+ actionBuilderList = action.updateAction(actionBuilderList, params, actionRule.getOrder(), netElements, policyPair, flowMap, ctx);
+ }
+
}
- } else {
- Action act = SubjectFeatures.getAction(AllowAction.DEFINITION.getId());
- actionBuilderList = act.updateAction(actionBuilderList, new HashMap<String, Object>(), 0, netElements);
}
Map<String, ParameterValue> paramsFromClassifier = new HashMap<>();
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 {
}
}
}
- if(classifiers.isEmpty()) {
+ if (classifiers.isEmpty()) {
return;
}
List<Map<String, ParameterValue>> derivedParamsByName = ParamDerivator.ETHER_TYPE_DERIVATOR.deriveParameter(paramsFromClassifier);
- String baseId = createBaseFlowId(direction, cgPair, priority);
List<MatchBuilder> flowMatchBuilders = new ArrayList<>();
for (Map<String, ParameterValue> params : derivedParamsByName) {
List<MatchBuilder> matchBuildersToResolve = new ArrayList<>();
- if (cgPair.sIpPrefixes.isEmpty() && cgPair.dIpPrefixes.isEmpty()) {
- matchBuildersToResolve.add(createBaseMatch(direction, cgPair, null, null));
- } else if (!cgPair.sIpPrefixes.isEmpty() && cgPair.dIpPrefixes.isEmpty()) {
- for (IpPrefix sIpPrefix : cgPair.sIpPrefixes) {
- matchBuildersToResolve.add(createBaseMatch(direction, cgPair, sIpPrefix, null));
+ if (policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
+ matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, null));
+ } else if (!policyPair.consumerEicIpPrefixes.isEmpty() && policyPair.providerEicIpPrefixes.isEmpty()) {
+ for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
+ matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, null));
}
- } else if (cgPair.sIpPrefixes.isEmpty() && !cgPair.dIpPrefixes.isEmpty()) {
- for (IpPrefix dIpPrefix : cgPair.sIpPrefixes) {
- matchBuildersToResolve.add(createBaseMatch(direction, cgPair, null, dIpPrefix));
+ } else if (policyPair.consumerEicIpPrefixes.isEmpty() && !policyPair.providerEicIpPrefixes.isEmpty()) {
+ for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
+ matchBuildersToResolve.add(createBaseMatch(direction, policyPair, null, dIpPrefix));
}
} else {
- for (IpPrefix sIpPrefix : cgPair.sIpPrefixes) {
- for (IpPrefix dIpPrefix : cgPair.sIpPrefixes) {
- matchBuildersToResolve.add(createBaseMatch(direction, cgPair, sIpPrefix, dIpPrefix));
+ for (IpPrefix sIpPrefix : policyPair.consumerEicIpPrefixes) {
+ for (IpPrefix dIpPrefix : policyPair.consumerEicIpPrefixes) {
+ matchBuildersToResolve.add(createBaseMatch(direction, policyPair, sIpPrefix, dIpPrefix));
}
}
}
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());
}
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));
}
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));
}
}
// TODO: move to a common utils for all renderers
- public List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>>
- getActiveRulesBetweenEps(Policy policy, Endpoint consEp, Endpoint provEp) {
+ public List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> getActiveRulesBetweenEps(Policy policy,
+ Endpoint consEp, Endpoint provEp) {
List<Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>>> rulesWithEpConstraints = new ArrayList<>();
if (policy.getRuleMap() != null) {
for (Cell<EndpointConstraint, EndpointConstraint, List<RuleGroup>> cell : policy.getRuleMap().cellSet()) {
}
@Immutable
- private static class CgPair {
+ public static class PolicyPair {
+
+ private final int consumerEpgId;
+ private final int providerEpgId;
+ private final int consumerCondGrpId;
+ private final int providerCondGrpId;
+ private final Set<IpPrefix> consumerEicIpPrefixes;
+ private final Set<IpPrefix> providerEicIpPrefixes;
+ private NodeId consumerEpNodeId;
+ private NodeId providerEpNodeId;
+
+ public int getConsumerEpgId() {
+ return consumerEpgId;
+ }
+
+ public int getProviderEpgId() {
+ return providerEpgId;
+ }
+
+ public NodeId getConsumerEpNodeId() {
+ return consumerEpNodeId;
+ }
- private final int sepg;
- private final int depg;
- private final int scgId;
- private final int dcgId;
- private final Set<IpPrefix> sIpPrefixes;
- private final Set<IpPrefix> dIpPrefixes;
+ public NodeId getProviderEpNodeId() {
+ return providerEpNodeId;
+ }
- public CgPair(int sepg, int depg, int scgId, int dcgId, Set<IpPrefix> sIpPrefixes, Set<IpPrefix> dIpPrefixes) {
+ public PolicyPair(int consumerEpgId, int providerEpgId, int consumerCondGrpId, int providerCondGrpId,
+ Set<IpPrefix> consumerEicIpPrefixes, Set<IpPrefix> providerEicIpPrefixes, NodeId consumerEpNodeId, NodeId providerEpNodeId) {
super();
- this.sepg = sepg;
- this.depg = depg;
- this.scgId = scgId;
- this.dcgId = dcgId;
- this.sIpPrefixes = sIpPrefixes;
- this.dIpPrefixes = dIpPrefixes;
+ this.consumerEpgId = consumerEpgId;
+ this.providerEpgId = providerEpgId;
+ this.consumerCondGrpId = consumerCondGrpId;
+ this.providerCondGrpId = providerCondGrpId;
+ this.consumerEicIpPrefixes = consumerEicIpPrefixes;
+ this.providerEicIpPrefixes = providerEicIpPrefixes;
+ this.consumerEpNodeId = consumerEpNodeId;
+ this.providerEpNodeId = providerEpNodeId;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((dIpPrefixes == null) ? 0 : dIpPrefixes.hashCode());
- result = prime * result + dcgId;
- result = prime * result + depg;
- result = prime * result + ((sIpPrefixes == null) ? 0 : sIpPrefixes.hashCode());
- result = prime * result + scgId;
- result = prime * result + sepg;
+ result = prime * result + ((providerEicIpPrefixes == null) ? 0 : providerEicIpPrefixes.hashCode());
+ result = prime * result + providerCondGrpId;
+ result = prime * result + providerEpgId;
+ result = prime * result + ((consumerEicIpPrefixes == null) ? 0 : consumerEicIpPrefixes.hashCode());
+ result = prime * result + consumerCondGrpId;
+ result = prime * result + consumerEpgId;
+ result = prime * result + ((consumerEpNodeId == null) ? 0 : consumerEpNodeId.hashCode());
+ result = prime * result + ((providerEpNodeId == null) ? 0 : providerEpNodeId.hashCode());
+
return result;
}
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;
}
+
}
}
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+import java.util.Collection;
import java.util.Set;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
// Handle case where packets from from External
- Map<EndpointKey, EndpointL3> l3EpWithNatByL2Key = ctx.getEndpointManager().getL3EpWithNatByL2Key();
for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
continue;
EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, ep);
- EgKey sepg = new EgKey(ep.getTenant(), ep.getEndpointGroup());
createRemoteTunnels(flowMap, nodeId, ep, policyInfo, epFwdCtxOrds);
* Sync the local EP information.
*/
syncEP(flowMap, nodeId, ep, ofc.getNodeConnectorId(), epFwdCtxOrds);
-
}
-// if (l3EpWithNatByL2Key.containsKey(ep.getKey())) {
-// Set<NodeConnectorId> external = ctx.getSwitchManager().getExternalPorts(nodeId);
-// for (NodeConnectorId ncId : external) {
-// // TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
-// syncEP(flowMap, nodeId, ep, ncId, epFwdCtxOrds);
-// }
-// }
}
}
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;
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;
return ImmutableSet.copyOf(state.externalPorts);
}
- public static synchronized NodeConnectorId getTunnelPort(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
+ public synchronized Collection<NodeConnectorId> getTunnelPorts(NodeId nodeId) {
+ Collection<NodeConnectorId> ncIds = new HashSet<>();
+ SwitchState state = switches.get(nodeId);
+ if (state == null ) {
+ return Collections.emptySet();
+ }
+ ncIds = Collections2.transform(state.tunnelBuilderByType.values(),new Function<TunnelBuilder, NodeConnectorId>() {
+
+ @Override
+ public NodeConnectorId apply(TunnelBuilder input) {
+ return input.getNodeConnectorId();
+ }
+ });
+
+ return ncIds;
+ }
+ public synchronized NodeConnectorId getTunnelPort(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
SwitchState state = switches.get(nodeId);
if (state == null) {
return null;
return tunnel.getNodeConnectorId();
}
- public static synchronized IpAddress getTunnelIP(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
+ public synchronized IpAddress getTunnelIP(NodeId nodeId, Class<? extends TunnelTypeBase> tunnelType) {
SwitchState state = switches.get(nodeId);
if (state == null) {
return null;
private void update() {
tunnelBuilderByType = new HashMap<>();
externalPorts = new HashSet<>();
- for (Entry<InstanceIdentifier<NodeConnector>, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) {
- FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue();
- if (fcnc.getName() == null) {
- continue;
- }
- InstanceIdentifier<NodeConnector> ncIid = fcncByNcIidEntry.getKey();
- NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
- if (fcnc.getName().matches(".*(vxlan).*")) {
- TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlan.class);
- if (tunnelBuilder == null) {
- tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlan.class);
- tunnelBuilderByType.put(TunnelTypeVxlan.class, tunnelBuilder);
- }
- tunnelBuilder.setNodeConnectorId(ncId);
- }
- }
-
if (nodeConfig != null && nodeConfig.getExternalInterfaces() != null) {
for (ExternalInterfaces nc : nodeConfig.getExternalInterfaces()) {
externalPorts.add(nc.getNodeConnectorId());
}
}
}
+ for (Entry<InstanceIdentifier<NodeConnector>, FlowCapableNodeConnector> fcncByNcIidEntry : fcncByNcIid.entrySet()) {
+ FlowCapableNodeConnector fcnc = fcncByNcIidEntry.getValue();
+ if (fcnc.getName() == null) {
+ continue;
+ }
+ InstanceIdentifier<NodeConnector> ncIid = fcncByNcIidEntry.getKey();
+ NodeConnectorId ncId = ncIid.firstKeyOf(NodeConnector.class, NodeConnectorKey.class).getId();
+ if (fcnc.getName().matches(".*(vxlan-).*")) {
+ TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlan.class);
+ if (tunnelBuilder == null) {
+ tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlan.class);
+ tunnelBuilderByType.put(TunnelTypeVxlan.class, tunnelBuilder);
+ }
+ tunnelBuilder.setNodeConnectorId(ncId);
+ } else if (fcnc.getName().matches(".*(vxlangpe-).*")) {
+ TunnelBuilder tunnelBuilder = tunnelBuilderByType.get(TunnelTypeVxlanGpe.class);
+ if (tunnelBuilder == null) {
+ tunnelBuilder = new TunnelBuilder().setTunnelType(TunnelTypeVxlanGpe.class);
+ tunnelBuilderByType.put(TunnelTypeVxlanGpe.class, tunnelBuilder);
+ }
+ tunnelBuilder.setNodeConnectorId(ncId);
+ }
+ }
}
private void updateStatus() {
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;
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
public abstract List<ActionBuilder> updateAction(List<ActionBuilder> actions,
Map<String, Object> params,
Integer order,
- NetworkElements netElements);
+ NetworkElements netElements,
+ PolicyPair policyPair,
+ FlowMap flowMap,
+ OfContext ctx);
}
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;
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;
public List<ActionBuilder> updateAction(List<ActionBuilder> actions,
Map<String, Object> params,
Integer order,
- NetworkElements netElements) {
+ NetworkElements netElements,
+ PolicyPair policyPair,
+ FlowMap flowMap,
+ OfContext ctx) {
/*
* Allow action doesn't use parameters
* TODO: check to make sure ActionBuilder w/allow isn't already present
@Override
public boolean isValid(ActionInstance actionInstance) {
- // TODO Auto-generated method stub
return true;
}
+/*
+ * 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;
/*
* 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;
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;
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
}
@Override
- public List<ActionBuilder> updateAction(List<ActionBuilder> actions,
- Map<String, Object> params,
- Integer order,
- NetworkElements netElements) {
+ public List<ActionBuilder> updateAction(List<ActionBuilder> actions, Map<String, Object> params, Integer order,
+ NetworkElements netElements, PolicyPair policyPair, FlowMap flowMap, OfContext ctx) {
/*
* Get the named chain
*/
ServiceFunctionPath sfcPath = null;
String chainName = null;
if (params != null) {
- LOG.debug("Searching for named chain");
+ LOG.debug("ChainAction: Searching for named chain");
for (String name : params.keySet()) {
if (name instanceof String) {
if (name.equals(SFC_CHAIN_NAME)) {
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(
.setName(rspName)
.setSymmetric(Boolean.FALSE)
.build();
- RenderedServicePath renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(
- sfcPath, rspInput);
+ renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfcPath, rspInput);
if (renderedServicePath == null) {
- LOG.error("Could not find or create RSP for chain {}", chainName);
+ LOG.error("ChainAction: Could not find or create RSP for chain {}", chainName);
return null;
}
- rspFirstHop=SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(renderedServicePath.getName());
}
- IpAddress sfcTunIpDst = rspFirstHop.getIp();
- sfcTunIpDst.getIpv4Address();
- if (sfcTunIpDst == null || sfcTunIpDst.getIpv4Address() == null || sfcTunIpDst.getIpv6Address() != null) {
- LOG.error("Invalid IP Tunnel destination for SFC RSP First Hop {}", rspName);
- return null;
- }
- PortNumber sfcTunUdpPort = rspFirstHop.getPort();
- if (sfcTunUdpPort == null) {
- LOG.error("Invalid UDP Port Number for SFC RSP {}", rspName);
- return null;
- }
- Long sfcNsp = rspFirstHop.getPathId();
- if (sfcNsp == null) {
- LOG.error("Invalid NSP for SFC RSP {}", rspName);
- return null;
- }
- Short sfcNsi = rspFirstHop.getStartingIndex();
- if (sfcNsi == null) {
- LOG.error("Invalid NSI for SFC RSP {}", rspName);
+ RenderedServicePathFirstHop rspFirstHop = SfcProviderRenderedPathAPI.readRenderedServicePathFirstHop(rspName);
+
+ if (!isValidRspFirstHop(rspFirstHop)) {
+ // Errors logged in method.
return null;
}
- NodeConnectorId tunOpenFlowPort = SwitchManager.getTunnelPort(netElements.getNodeId(), TunnelTypeVxlanGpe.class);
-
- /*
- * Setting NSH Network Context Headers for post-SFC encapsulation
- * VXLAN header encap:
- * - TunnelDestination IP: NSH C1
- * - Tunnel ID (VNID) NSH C2
- */
- long postSfcTunnelDst = 999L;
- IpAddress tunnelDest;
-
- if (netElements.getDst().getAugmentation(OfOverlayContext.class).getNodeId().equals(netElements.getNodeId())) {
+ NodeId tunnelDestNodeId;
+ if (netElements.getDstNodeId().equals(netElements.getLocalNodeId())) {
// Return destination is here
- tunnelDest=SwitchManager.getTunnelIP(netElements.getNodeId(), TunnelTypeVxlanGpe.class);
+ tunnelDestNodeId = netElements.getLocalNodeId();
} else {
- tunnelDest=SwitchManager.getTunnelIP(netElements.getDst().getAugmentation(OfOverlayContext.class).getNodeId(), TunnelTypeVxlanGpe.class);
+ tunnelDestNodeId = netElements.getDstNodeId();
}
- postSfcTunnelDst = (InetAddresses.coerceToInteger(InetAddresses.forString(tunnelDest.getIpv4Address().getValue()))) & 0xFFFFFFFFL;
- // TunnelDestination after Chain
- actions = addActionBuilder(actions, nxLoadNshc1RegAction(postSfcTunnelDst), order++);
- // VNID after Chain
- actions = addActionBuilder(actions, nxLoadNshc2RegAction((long) netElements.getSrcOrds().getTunnelId()), order++);
+ IpAddress tunnelDest = ctx.getSwitchManager().getTunnelIP(tunnelDestNodeId, TunnelTypeVxlanGpe.class);
- /*
- * Set the tunnel destination IP
- */
- if (sfcTunIpDst.getIpv4Address() != null) {
- String nextHop = sfcTunIpDst.getIpv4Address().getValue();
- actions = addActionBuilder(actions, nxLoadTunIPv4Action(nextHop, false), order);
- } else if (sfcTunIpDst.getIpv6Address() != null) {
- LOG.error("IPv6 tunnel destination {} not supported", sfcTunIpDst.getIpv6Address().getValue());
- return actions;
- } else {
- // this shouldn't happen
- LOG.error("Tunnel IP is invalid");
- return actions;
+ if (tunnelDest == null || tunnelDest.getIpv4Address() == null) {
+ LOG.error("ChainAction: Invalid tunnelDest for NodeId: {}", tunnelDestNodeId);
+ return null;
}
- /*
- * Put TunID - with NSH we don't really care about this.
- */
- actions = addActionBuilder(actions,
- nxLoadTunIdAction(BigInteger.valueOf(netElements.getSrcOrds().getTunnelId()), false), order);
- /*
- * Set the NSH header fields, based on RSP
- */
- actions = addActionBuilder(actions,nxSetNsiAction(sfcNsi),order);
- actions = addActionBuilder(actions,nxSetNspAction(sfcNsp),order);
- /*
- * Set up the actions to send to the destination port
- */
- actions = addActionBuilder(actions,outputAction(tunOpenFlowPort), order);
+ RenderedServicePathHop firstRspHop = renderedServicePath.getRenderedServicePathHop().get(0);
+ RenderedServicePathHop lastRspHop = Iterables.getLast(renderedServicePath.getRenderedServicePathHop());
+
+ SfcNshHeader sfcNshHeader = new SfcNshHeaderBuilder().setNshTunIpDst(rspFirstHop.getIp().getIpv4Address())
+ .setNshTunUdpPort(rspFirstHop.getPort())
+ .setNshNsiToChain(firstRspHop.getServiceIndex())
+ .setNshNspToChain(renderedServicePath.getPathId())
+ .setNshNsiFromChain((short) (lastRspHop.getServiceIndex().intValue() - 1))
+ .setNshNspFromChain(renderedServicePath.getPathId())
+ .setNshMetaC1(SfcNshHeader.convertIpAddressToLong(tunnelDest.getIpv4Address()))
+ .setNshMetaC2((long) netElements.getSrcEpOrds().getTunnelId())
+ .build();
+
+ // Cannot set all actions here. Some actions are destination specific, and we don't know a destination is to be
+ // chained until we reach this point. Need to write match/action in External Table for chained packets.
+ actions = addActionBuilder(actions, nxSetNsiAction(sfcNshHeader.getNshNsiToChain()), order);
+ actions = addActionBuilder(actions, nxSetNspAction(sfcNshHeader.getNshNspToChain()), order);
+
+ createChainTunnelFlows(sfcNshHeader, netElements, flowMap, ctx);
return actions;
}
- private List<ActionBuilder> addActionBuilder(List<ActionBuilder> actions,
- org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action, Integer order) {
- ActionBuilder ab = new ActionBuilder();
- ab.setAction(action);
- ab.setOrder(order);
- actions.add(ab);
- return actions;
+ private boolean isValidRspFirstHop(RenderedServicePathFirstHop rspFirstHop) {
+ boolean valid = true;
+ if (rspFirstHop == null) {
+ LOG.error("isValidRspFirstHop: rspFirstHop is null.");
+ return false;
+ }
+ if (rspFirstHop.getIp() == null || rspFirstHop.getIp().getIpv4Address() == null
+ || rspFirstHop.getIp().getIpv6Address() != null) {
+ LOG.error("isValidRspFirstHop: rspFirstHop has invalid IP address.");
+ valid = false;
+ }
+ if (rspFirstHop.getPort() == null) {
+ LOG.error("isValidRspFirstHop: rspFirstHop has no IP port .");
+ valid = false;
+ }
+ if (rspFirstHop.getPathId() == null) {
+ LOG.error("isValidRspFirstHop: rspFirstHop has no Path Id (NSP).");
+ valid = false;
+ }
+ if (rspFirstHop.getStartingIndex() == null) {
+ LOG.error("isValidRspFirstHop: rspFirstHop has no Starting Index (NSI)");
+ valid = false;
+ }
+ return valid;
+ }
+
+ private RenderedServicePath getRspByName(String rspName, ReadOnlyTransaction rTx) {
+ Optional<RenderedServicePath> optRsp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
+ SfcIidFactory.rspIid(rspName), rTx);
+ if (optRsp.isPresent()) {
+ return optRsp.get();
+ }
+ return null;
}
@Override
public boolean isValid(ActionInstance actionInstance) {
- return validChain(actionInstance.getParameterValue());
+ return isValidGbpChain(actionInstance.getParameterValue());
}
- private boolean validChain(List<ParameterValue> paramValue) {
+ private boolean isValidGbpChain(List<ParameterValue> paramValue) {
ParameterValue pv = getChainNameParameter(paramValue);
if (pv == null) {
return false;
}
LOG.trace("Invoking RPC for chain {}", pv.getStringValue());
ServiceFunctionChain chain = SfcProviderServiceChainAPI.readServiceFunctionChain(pv.getStringValue());
- return chain != null;
+ return (chain != null);
}
public ServiceFunctionPath getSfcPath(String chainName) {
return null;
}
+ private List<ActionBuilder> addActionBuilder(List<ActionBuilder> actions,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action action, Integer order) {
+ ActionBuilder ab = new ActionBuilder();
+ ab.setAction(action);
+ ab.setOrder(order);
+ actions.add(ab);
+ return actions;
+ }
+
}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils;
-
-import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
-/**
- * @author Martin Sunal
- */
-public class SfcDataStoreHelper {
-
- private static final Logger LOG = LoggerFactory.getLogger(SfcDataStoreHelper.class);
-
- /**
- * Reads data from datastore as synchrone call.
- * @return {@link Optional#isPresent()} is {@code true} if reading was successful and data exists in datastore; {@link Optional#isPresent()} is {@code false} otherwise
- */
- public static <U extends DataObject> U readFromDs(LogicalDatastoreType store,InstanceIdentifier<U> iid, ReadTransaction rTx) {
- U ret = null;
- Optional<U> optionalDataObject;
- CheckedFuture<Optional<U>, ReadFailedException> submitFuture = rTx.read(store, iid);
- try {
- optionalDataObject = submitFuture.checkedGet();
- if (optionalDataObject != null && optionalDataObject.isPresent()) {
- ret = optionalDataObject.get();
- } else {
- LOG.debug("{}: Failed to read", Thread.currentThread().getStackTrace()[1]);
- }
- } catch (ReadFailedException e) {
- LOG.warn("failed to ....", e);
- }
- return ret;
- }
-
- /**
- * Calls {@link WriteTransaction#submit()} on write transaction.
- * @param wTx write transaction
- * @return {@code true} if transaction commit was successful; {@code false} otherwise
- */
- public static boolean submitToDs(WriteTransaction wTx) {
- CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
- try {
- submitFuture.checkedGet();
- return true;
- } catch (TransactionCommitFailedException e) {
- LOG.warn("Transaction commit failed to DS.", e);
- return false;
- }
- }
-
-}
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;
ServiceFunctionPathKey serviceFunctionPathKey = new ServiceFunctionPathKey(sfpName);
return InstanceIdentifier.builder(ServiceFunctionPaths.class)
.child(ServiceFunctionPath.class, serviceFunctionPathKey).build();
+ }
+
+ public static InstanceIdentifier<RenderedServicePath> rspIid(String rspName) {
+ RenderedServicePathKey rspKey = new RenderedServicePathKey(rspName);
+ return InstanceIdentifier.builder(RenderedServicePaths.class)
+ .child(RenderedServicePath.class, rspKey).build();
}
}
--- /dev/null
+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;
+ }
+
+ }
+
+
+
+}