import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.sal.action.Action;
import org.opendaylight.controller.sal.action.ActionType;
import org.opendaylight.controller.sal.action.Controller;
import org.opendaylight.controller.sal.action.Drop;
+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.HwPath;
import org.opendaylight.controller.sal.action.Loopback;
import org.opendaylight.controller.sal.action.Output;
import org.opendaylight.controller.sal.action.SetVlanId;
import org.opendaylight.controller.sal.action.SetVlanPcp;
import org.opendaylight.controller.sal.action.SwPath;
-import org.opendaylight.controller.sal.core.ContainerFlow;
-import org.opendaylight.controller.sal.core.IContainer;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.flowprogrammer.Flow;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.IPProtocols;
import org.opendaylight.controller.sal.utils.NetUtils;
-import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
-import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.Switch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class FlowConfig implements Serializable {
+public class FlowConfig extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
- private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
public static final String STATICFLOWGROUP = "__StaticFlows__";
public static final String INTERNALSTATICFLOWGROUP = "__InternalStaticFlows__";
public static final String INTERNALSTATICFLOWBEGIN = "__";
return true;
}
- public boolean isPortValid(Switch sw, Short port) {
- if (port < 1) {
- log.debug("port {} is not valid", port);
- return false;
- }
-
- if (sw == null) {
- log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
- return true;
- }
-
- Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
- for (NodeConnector nodeConnector : nodeConnectorSet) {
- if (((Short) nodeConnector.getID()).equals(port)) {
- return true;
- }
- }
- log.debug("port {} is not a valid port of node {}", port, sw.getNode());
- return false;
- }
-
public boolean isVlanIdValid(String vlanId) {
int vlan = Integer.decode(vlanId);
return ((vlan >= 0) && (vlan < 4096));
return (proto != null);
}
- private Status conflictWithContainerFlow(IContainer container) {
- // Return true if it's default container
- if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
- return new Status(StatusCode.SUCCESS);
- }
-
- // No container flow = no conflict
- List<ContainerFlow> cFlowList = container.getContainerFlows();
- if (((cFlowList == null)) || cFlowList.isEmpty()) {
- return new Status(StatusCode.SUCCESS);
- }
-
- // Check against each container's flow
- Flow flow = this.getFlow();
-
- // Configuration is rejected if it conflicts with _all_ the container
- // flows
- for (ContainerFlow cFlow : cFlowList) {
- if (cFlow.allowsFlow(flow)) {
- log.trace("Config is congruent with at least one container flow");
- return new Status(StatusCode.SUCCESS);
- }
- }
- String msg = "Flow Config conflicts with all existing container flows";
- log.trace(msg);
-
- return new Status(StatusCode.BADREQUEST, msg);
- }
-
- public Status validate(IContainer container) {
+ public Status validate() {
EtherIPType etype = EtherIPType.ANY;
EtherIPType ipsrctype = EtherIPType.ANY;
EtherIPType ipdsttype = EtherIPType.ANY;
- String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName();
- ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
- this);
-
- Switch sw = null;
try {
- if (name == null || name.trim().isEmpty() || !name.matches(FlowConfig.NAMEREGEX)) {
+ // Flow name cannot be internal flow signature
+ if (!isValidResourceName(name) || isInternalFlow()) {
return new Status(StatusCode.BADREQUEST, "Invalid name");
}
return new Status(StatusCode.BADREQUEST, "Node is null");
}
- if (switchManager != null) {
- for (Switch device : switchManager.getNetworkDevices()) {
- if (device.getNode().equals(node)) {
- sw = device;
- break;
- }
- }
- if (sw == null) {
- return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node));
- }
- } else {
- log.debug("switchmanager is not set yet");
- }
-
if (priority != null) {
if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) {
return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535",
Long.decode(cookie);
}
- if (ingressPort != null) {
- Short port = Short.decode(ingressPort);
- if (isPortValid(sw, port) == false) {
- String msg = String.format("Ingress port %d is not valid for the Switch", port);
- if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
- msg += " in Container " + containerName;
- }
- return new Status(StatusCode.BADREQUEST, msg);
- }
+ if (ingressPort != null && ingressPort.isEmpty()) {
+ return new Status(StatusCode.BADREQUEST, "Invalid ingress port");
}
if ((vlanId != null) && !isVlanIdValid(vlanId)) {
return new Status(StatusCode.BADREQUEST, "Actions value is null or empty");
}
for (String actiongrp : actions) {
- // check output ports
- sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
- if (sstr.matches()) {
- for (String t : sstr.group(1).split(",")) {
- Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
- if (n.matches()) {
- if (n.group(1) != null) {
- Short port = Short.parseShort(n.group(1));
- if (isPortValid(sw, port) == false) {
- String msg = String.format("Output port %d is not valid for this switch", port);
- if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
- msg += " in Container " + containerName;
- }
- return new Status(StatusCode.BADREQUEST, msg);
- }
- }
- } else {
- String msg = String.format("Output port %s is not valid", t);
- return new Status(StatusCode.BADREQUEST, msg);
- }
- }
- continue;
- }
- // Check src IP
- sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
- if (sstr.matches()) {
- if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
- return new Status(StatusCode.BADREQUEST, String.format(
- "flood is not allowed in container %s", containerName));
- }
- continue;
- }
// Check src IP
sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp);
if (sstr.matches()) {
continue;
}
+ sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
+ if (sstr.matches()) {
+ for (String t : sstr.group(1).split(",")) {
+ if (t != null) {
+ String parts[] = t.split(":");
+ String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
+ if (NodeConnector.fromString(nc) == null) {
+ return new Status(StatusCode.BADREQUEST, String.format("Enqueue port is not valid"));
+ }
+ if (parts.length > 1) {
+ try {
+ Integer.parseInt(parts[1]);
+ } catch (NumberFormatException e) {
+ return new Status(StatusCode.BADREQUEST, String.format("Enqueue %s is not in the range 0 - 2147483647", parts[1]));
+ }
+ }
+ }
+ }
+ continue;
+ }
+
sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp);
if (sstr.matches()) {
if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) {
}
continue;
}
+
sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp);
if (sstr.matches()) {
if (!NetUtils.isIPAddressValid(sstr.group(1))) {
}
continue;
}
- }
- // Check against the container flow
- Status status;
- if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
- return status;
- }
+
+ sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ continue;
+ }
+
+ // If execution reached here, it means there is an Action
+ // which is not recognized by the controller. Return error
+
+ return new Status(StatusCode.BADREQUEST, String.format("%s is an UnSupported Action", actiongrp));
+ }
} catch (NumberFormatException e) {
return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
}
if (this.ingressPort != null) {
match.setField(MatchType.IN_PORT,
- NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode()));
+ NodeConnector.fromString(String.format("%s|%s@%s", node.getType(), ingressPort, node.toString())));
}
if (this.dlSrc != null) {
match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc));
}
Flow flow = new Flow(match, getActionList());
+
if (this.cookie != null) {
flow.setId(Long.parseLong(cookie));
}
if (this.priority != null) {
flow.setPriority(Integer.decode(this.priority).shortValue());
}
+
+
return flow;
}
sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp);
if (sstr.matches()) {
for (String t : sstr.group(1).split(",")) {
- Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
- if (n.matches()) {
- if (n.group(1) != null) {
- short ofPort = Short.parseShort(n.group(1));
- actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort,
- this.getNode())));
+ if (t != null) {
+ String nc = String.format("%s|%s@%s", node.getType(), t, node.toString());
+ actionList.add(new Output(NodeConnector.fromString(nc)));
+ }
+ }
+ continue;
+ }
+
+ sstr = Pattern.compile(ActionType.ENQUEUE + "=(.*)").matcher(actiongrp);
+ if (sstr.matches()) {
+ for (String t : sstr.group(1).split(",")) {
+ if (t != null) {
+ String parts[] = t.split(":");
+ String nc = String.format("%s|%s@%s", node.getType(), parts[0], node.toString());
+ if (parts.length == 1) {
+ actionList.add(new Enqueue(NodeConnector.fromString(nc)));
+ } else {
+ actionList
+ .add(new Enqueue(NodeConnector.fromString(nc), Integer.parseInt(parts[1])));
}
}
}
continue;
}
+ sstr = Pattern.compile(ActionType.FLOOD_ALL.toString()).matcher(actiongrp);
+ if (sstr.matches()) {
+ actionList.add(new FloodAll());
+ continue;
+ }
+
sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp);
if (sstr.matches()) {
actionList.add(new SwPath());