import org.opendaylight.controller.forwardingrulesmanager.implementation.data.FlowEntryDistributionOrder;
import org.opendaylight.controller.sal.action.Action;
import org.opendaylight.controller.sal.action.ActionType;
+import org.opendaylight.controller.sal.action.Enqueue;
+import org.opendaylight.controller.sal.action.Flood;
+import org.opendaylight.controller.sal.action.FloodAll;
import org.opendaylight.controller.sal.action.Output;
import org.opendaylight.controller.sal.connection.ConnectionLocality;
import org.opendaylight.controller.sal.core.Config;
return null;
}
+ /**
+ * Checks if the FlowEntry targets are valid for this container
+ *
+ * @param flowEntry
+ * The flow entry to test
+ * @return a Status object representing the result of the validation
+ */
+ private Status validateEntry(FlowEntry flowEntry) {
+ // Node presence check
+ Node node = flowEntry.getNode();
+ if (!switchManager.getNodes().contains(node)) {
+ return new Status(StatusCode.BADREQUEST, String.format("Node %s is not present in this container", node));
+ }
+
+ // Ports and actions validation check
+ Flow flow = flowEntry.getFlow();
+ Match match = flow.getMatch();
+ if (match.isPresent(MatchType.IN_PORT)) {
+ NodeConnector inputPort = (NodeConnector)match.getField(MatchType.IN_PORT).getValue();
+ if (!switchManager.getNodeConnectors(node).contains(inputPort)) {
+ String msg = String.format("Ingress port %s is not present on this container", inputPort);
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
+ }
+ for (Action action : flow.getActions()) {
+ if (action instanceof Flood && !GlobalConstants.DEFAULT.toString().equals(getContainerName())) {
+ return new Status(StatusCode.BADREQUEST, String.format("Flood is only allowed in default container"));
+ }
+ if (action instanceof FloodAll && !GlobalConstants.DEFAULT.toString().equals(getContainerName())) {
+ return new Status(StatusCode.BADREQUEST, String.format("FloodAll is only allowed in default container"));
+ }
+ if (action instanceof Output) {
+ Output out = (Output)action;
+ NodeConnector outputPort = out.getPort();
+ if (!switchManager.getNodeConnectors(node).contains(outputPort)) {
+ String msg = String.format("Output port %s is not present on this container", outputPort);
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
+ }
+ if (action instanceof Enqueue) {
+ Enqueue out = (Enqueue)action;
+ NodeConnector outputPort = out.getPort();
+ if (!switchManager.getNodeConnectors(node).contains(outputPort)) {
+ String msg = String.format("Enqueue port %s is not present on this container", outputPort);
+ return new Status(StatusCode.BADREQUEST, msg);
+ }
+ }
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
+
/**
* Adds a flow entry onto the network node It runs various validity checks
* and derive the final container flows merged entries that will be
return new Status(StatusCode.NOTACCEPTABLE, INVALID_FLOW_ENTRY);
}
+ // Operational check: input, output and queue ports presence check and
+ // action validation for this container
+ Status status = validateEntry(flowEntry);
+ if (!status.isSuccess()) {
+ String msg = String.format("%s: %s", INVALID_FLOW_ENTRY, status.getDescription());
+ log.warn("{}: {}", msg, flowEntry);
+ return new Status(StatusCode.NOTACCEPTABLE, msg);
+ }
+
/*
* Redundant Check: Check if the request is a redundant one from the
* same application the flowEntry is equal to an existing one. Given we
return new Status(StatusCode.SUCCESS, msg);
}
+ // Operational check: input, output and queue ports presence check and
+ // action validation for this container
+ Status status = validateEntry(newFlowEntry);
+ if (!status.isSuccess()) {
+ String msg = String.format("Modify: %s: %s", INVALID_FLOW_ENTRY, status.getDescription());
+ log.warn("{}: {}", msg, newFlowEntry);
+ return new Status(StatusCode.NOTACCEPTABLE, msg);
+ }
+
/*
* Conflict Check: Verify the new entry would not conflict with an
* existing one. This is a loose check on the previous original flow
List<FlowEntryInstall> list = new ArrayList<FlowEntryInstall>(groupFlows.get(groupName));
toBeRemoved = list.size();
for (FlowEntryInstall entry : list) {
- Status status = this.removeEntry(entry.getOriginal(), false);
+ // since this is the entry that was stored in groupFlows
+ // it is already validated and merged
+ // so can call removeEntryInternal directly
+ Status status = this.removeEntryInternal(entry, false);
if (status.isSuccess()) {
toBeRemoved -= 1;
} else {
@Override
public Status addStaticFlow(FlowConfig config) {
+ return addStaticFlow(config, false);
+ }
+
+ private Status addStaticFlow(FlowConfig config, boolean async) {
// Configuration object validation
- Status status = config.validate(container);
+ Status status = config.validate();
if (!status.isSuccess()) {
log.warn("Invalid Configuration for flow {}. The failure is {}", config, status.getDescription());
String error = "Invalid Configuration (" + status.getDescription() + ")";
config.setStatus(error);
return new Status(StatusCode.BADREQUEST, error);
}
- return addStaticFlowInternal(config, false);
+ return addStaticFlowInternal(config, async, false);
+ }
+
+
+ @Override
+ public Status addStaticFlowAsync(FlowConfig config) {
+ return addStaticFlow(config, true);
}
/**
* installation on the network node was successful
* @return The status of this request
*/
- private Status addStaticFlowInternal(FlowConfig config, boolean restore) {
+ private Status addStaticFlowInternal(FlowConfig config, boolean async, boolean restore) {
boolean multipleFlowPush = false;
String error;
Status status;
// Program hw
if (config.installInHw()) {
FlowEntry entry = config.getFlowEntry();
- status = this.installFlowEntry(entry);
+ status = async ? this.installFlowEntryAsync(entry) : this.installFlowEntry(entry);
if (!status.isSuccess()) {
config.setStatus(status.getDescription());
if (!restore) {
config.setStatus(StatusCode.SUCCESS.toString());
break;
default:
+ break;
}
}
}
@Override
public Status removeStaticFlow(FlowConfig config) {
+ return removeStaticFlow(config, false);
+ }
+
+ @Override
+ public Status removeStaticFlowAsync(FlowConfig config) {
+ return removeStaticFlow(config, true);
+ }
+
+ private Status removeStaticFlow(FlowConfig config, boolean async) {
/*
* No config.isInternal() check as NB does not take this path and GUI
* cannot issue a delete on an internal generated flow. We need this
}
// Program the network node
- Status status = this.uninstallFlowEntry(config.getFlowEntry());
+ Status status = async ? this.uninstallFlowEntryAsync(config.getFlowEntry()) : this.uninstallFlowEntry(config
+ .getFlowEntry());
// Update configuration database if programming was successful
if (status.isSuccess()) {
@Override
public Status removeStaticFlow(String name, Node node) {
+ return removeStaticFlow(name, node, false);
+ }
+
+ @Override
+ public Status removeStaticFlowAsync(String name, Node node) {
+ return removeStaticFlow(name, node, true);
+ }
+
+ private Status removeStaticFlow(String name, Node node, boolean async) {
// Look for the target configuration entry
Integer key = 0;
FlowConfig target = null;
}
// Program the network node
- Status status = this.removeEntry(target.getFlowEntry(), false);
+ Status status = this.removeEntry(target.getFlowEntry(), async);
// Update configuration database if programming was successful
if (status.isSuccess()) {
}
// Validity Check
- Status status = newFlowConfig.validate(container);
+ Status status = newFlowConfig.validate();
if (!status.isSuccess()) {
String msg = "Invalid Configuration (" + status.getDescription() + ")";
newFlowConfig.setStatus(msg);
}
}
if (target != null) {
- Status status = target.validate(container);
+ Status status = target.validate();
if (!status.isSuccess()) {
log.warn(status.getDescription());
return status;
}
for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, STATIC_FLOWS_FILE_NAME)) {
- addStaticFlowInternal((FlowConfig) conf, true);
+ addStaticFlowInternal((FlowConfig) conf, false, true);
}
}
// check if the frm really needs to act on the notification.
// this is to check against duplicate notifications
if(programInternalFlow(proactive, fc)) {
- Status status = (proactive) ? addStaticFlowInternal(fc, false) : removeStaticFlow(fc);
+ Status status = (proactive) ? addStaticFlowInternal(fc, false, false) : removeStaticFlow(fc);
if (status.isSuccess()) {
log.trace("{} Proactive Static flow: {}", (proactive ? "Installed" : "Removed"), fc.getName());
} else {
if ((staticFlow.getNode().equals(node)) && (staticFlow.getPortGroup().equals(config.getName()))) {
for (Short port : data.getPorts()) {
FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, config.getName(), port);
- addStaticFlowInternal(derivedFlow, false);
+ addStaticFlowInternal(derivedFlow, false, false);
}
}
}
this.reinstallAllFlowEntries();
break;
default:
+ break;
}
// Update our configuration DB
}
return list;
}
+
}