<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
+ <argLine>${testvm.argLine}</argLine>
<systemProperties>
<property>
<name>logback.configurationFile</name>
--- /dev/null
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl">
+ prefix:toaster-provider-impl
+ </type>
+ <name>toaster-provider-impl</name>
+
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+
+ <notification-service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-notification-service
+ </type>
+ <name>binding-notification-broker</name>
+ </notification-service>
+ </module>
+
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl">
+ prefix:toaster-consumer-impl
+ </type>
+ <name>toaster-consumer-impl</name>
+
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+
+ <notification-service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-notification-service
+ </type>
+ <name>binding-notification-broker</name>
+ </notification-service>
+ </module>
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider">toaster:toaster-provider</type>
+ <instance>
+ <name>toaster-provider</name>
+ <provider>/modules/module[type='toaster-provider-impl'][name='toaster-provider-impl']</provider>
+ </instance>
+ </service>
+ <service>
+ <type xmlns:toaster="urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer">toaster:toaster-consumer</type>
+ <instance>
+ <name>toaster-consumer</name>
+ <provider>/modules/module[type='toaster-consumer-impl'][name='toaster-consumer-impl']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+
+ </configuration>
+
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer?module=toaster-consumer&revision=2014-01-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-consumer:impl?module=toaster-consumer-impl&revision=2014-01-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider?module=toaster-provider&revision=2014-01-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:toaster-provider:impl?module=toaster-provider-impl&revision=2014-01-31</capability>
+ </required-capabilities>
+
+</snapshot>
+
package org.opendaylight.controller.forwardingrulesmanager;
+import java.io.Serializable;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+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.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;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import java.io.Serializable;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* Configuration Java Object which represents a flow configuration information
* for Forwarding Rules Manager.
return true;
}
- public boolean isPortValid(Switch sw, String port) {
- if (sw == null) {
- log.debug("switch info is not available. Skip checking if port is part of a switch or not.");
- return true;
- }
- NodeConnector nc = NodeConnectorCreator.createNodeConnector(port, sw.getNode());
- return sw.getNodeConnectors().contains(nc);
- }
-
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 {
// Flow name cannot be internal flow signature
if (!isValidResourceName(name) || isInternalFlow()) {
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) {
- if (!isPortValid(sw, ingressPort)) {
- String msg = String.format("Ingress port %s is not valid for the Switch", ingressPort);
- 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(",")) {
- if (t != null) {
- if (!isPortValid(sw, t)) {
- String msg = String.format("Output port %s is not valid for this switch", t);
- if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
- msg += " in Container " + containerName;
- }
- return new Status(StatusCode.BADREQUEST, msg);
- }
- }
- }
- continue;
- }
- // check enqueue
- sstr = Pattern.compile("ENQUEUE=(.*)").matcher(actiongrp);
- if (sstr.matches()) {
- for (String t : sstr.group(1).split(",")) {
- if (t != null) {
- String port = t.split(":")[0];
- if (!isPortValid(sw, port)) {
- 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);
- }
- }
- }
- 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;
}
}
- // Check against the container flow
- Status status;
- if (!containerName.equals(GlobalConstants.DEFAULT.toString()) && !(status = conflictWithContainerFlow(container)).isSuccess()) {
- return status;
- }
} catch (NumberFormatException e) {
return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage()));
}
FlowConfig flowConfig = new FlowConfig();
Assert.assertFalse(flowConfig.isInternalFlow());
flowConfig.setName("__Internal__");
- Status status = flowConfig.validate(null);
+ Status status = flowConfig.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("name"));
Assert.assertTrue(flowConfig.isInternalFlow());
@Test
public void testValid() throws UnknownHostException {
FlowConfig fc2 = createSampleFlowConfig();
- Assert.assertTrue(fc2.validate(null).isSuccess());
+ Assert.assertTrue(fc2.validate().isSuccess());
FlowConfig fc = new FlowConfig();
- Status status = fc.validate(null);
+ Status status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Invalid name"));
fc.setName("Config");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Node is null"));
fc.setNode(Node.fromString(Node.NodeIDType.OPENFLOW, "1"));
- Assert.assertFalse(fc.validate(null).isSuccess());
+ Assert.assertFalse(fc.validate().isSuccess());
List<String> actions = new ArrayList<String>();
fc.setActions(actions);
- Assert.assertFalse(fc.validate(null).isSuccess());
+ Assert.assertFalse(fc.validate().isSuccess());
actions.add("OUTPUT=2");
fc.setActions(actions);
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setPriority("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 65535"));
fc.setPriority("100000");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 65535"));
fc.setPriority("2000");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setCookie("100");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setIngressPort("100");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setVlanId(("-1"));
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 4095"));
fc.setVlanId("5000");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 4095"));
fc.setVlanId("100");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setVlanPriority("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 7"));
fc.setVlanPriority("9");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 7"));
fc.setVlanPriority("5");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setEtherType("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Ethernet type"));
fc.setEtherType("0xfffff");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Ethernet type"));
fc.setEtherType("0x800");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setTosBits("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("IP ToS bits"));
fc.setTosBits("65");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("IP ToS bits"));
fc.setTosBits("60");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setSrcPort("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Transport source port"));
fc.setSrcPort("0xfffff");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Transport source port"));
fc.setSrcPort("0");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setSrcPort("0x00ff");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setSrcPort("0xffff");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setDstPort("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Transport destination port"));
fc.setDstPort("0xfffff");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Transport destination port"));
fc.setDstPort("0");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setDstPort("0x00ff");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setDstPort("0xffff");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setSrcMac("abc");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Ethernet source address"));
fc.setSrcMac("00:A0:C9:14:C8:29");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setDstMac("abc");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Ethernet destination address"));
fc.setDstMac("00:A0:C9:22:AB:11");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setSrcIp("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("IP source address"));
fc.setSrcIp("2001:420:281:1004:407a:57f4:4d15:c355");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Src IP"));
fc.setEtherType("0x86dd");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setSrcIp("1.1.1.1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Src IP"));
fc.setEtherType("0x800");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setDstIp("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("IP destination address"));
fc.setDstIp("2001:420:281:1004:407a:57f4:4d15:c355");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Dst IP"));
fc.setEtherType("0x86dd");
fc.setSrcIp("2001:420:281:1004:407a:57f4:4d15:c355");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setDstIp("2.2.2.2");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Dst IP"));
fc.setEtherType("0x800");
fc.setSrcIp("1.1.1.1");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setEtherType(null);
fc.setSrcIp("2001:420:281:1004:407a:57f4:4d15:c355");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("IP Src Dest Type mismatch"));
fc.setSrcIp("1.1.1.1");
fc.setIdleTimeout("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Idle Timeout value"));
fc.setIdleTimeout("0xfffff");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Idle Timeout value"));
fc.setIdleTimeout("10");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
fc.setHardTimeout("-1");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Hard Timeout value"));
fc.setHardTimeout("0xfffff");
- status = fc.validate(null);
+ status = fc.validate();
Assert.assertFalse(status.isSuccess());
Assert.assertTrue(status.getDescription().contains("Hard Timeout value"));
fc.setHardTimeout("10");
- Assert.assertTrue(fc.validate(null).isSuccess());
+ Assert.assertTrue(fc.validate().isSuccess());
}
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) {
// 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(StatusCode.SUCCESS.toString());
break;
default:
+ break;
}
}
}
}
// 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;
this.reinstallAllFlowEntries();
break;
default:
+ break;
}
// Update our configuration DB
DataModification<InstanceIdentifier<? extends DataObject>, DataObject> source) {
DataModificationTransaction target = biDataService.beginTransaction();
LOG.debug("Created DOM Transaction {} for {},", target.getIdentifier(),source.getIdentifier());
+ for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+ target.removeConfigurationData(biEntry);
+ LOG.debug("Delete of Binding Configuration Data {} is translated to {}",entry,biEntry);
+ }
+ for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
+ org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
+ target.removeOperationalData(biEntry);
+ LOG.debug("Delete of Binding Operational Data {} is translated to {}",entry,biEntry);
+ }
for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : source.getUpdatedConfigurationData()
.entrySet()) {
Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> biEntry = mappingService
target.putOperationalData(biEntry.getKey(), biEntry.getValue());
LOG.debug("Update of Binding Operational Data {} is translated to {}",entry,biEntry);
}
- for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedConfigurationData()) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
- target.removeConfigurationData(biEntry);
- LOG.debug("Delete of Binding Configuration Data {} is translated to {}",entry,biEntry);
- }
- for (InstanceIdentifier<? extends DataObject> entry : source.getRemovedOperationalData()) {
- org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry);
- target.removeOperationalData(biEntry);
- LOG.debug("Delete of Binding Operational Data {} is translated to {}",entry,biEntry);
- }
+
return target;
}
DataModification<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> source) {
org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction target = baDataService
.beginTransaction();
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
+ try {
+
+ InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+ target.removeConfigurationData(baEntry);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}.", entry, e);
+ }
+ }
+ for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
+ try {
+
+ InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
+ target.removeOperationalData(baEntry);
+ } catch (DeserializationException e) {
+ LOG.error("Ommiting from BA transaction: {}.", entry, e);
+ }
+ }
for (Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> entry : source
.getUpdatedConfigurationData().entrySet()) {
try {
LOG.error("Ommiting from BA transaction: {}.", entry.getKey(), e);
}
}
- for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedConfigurationData()) {
- try {
-
- InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
- target.removeConfigurationData(baEntry);
- } catch (DeserializationException e) {
- LOG.error("Ommiting from BA transaction: {}.", entry, e);
- }
- }
- for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier entry : source.getRemovedOperationalData()) {
- try {
-
- InstanceIdentifier<?> baEntry = mappingService.fromDataDom(entry);
- target.removeOperationalData(baEntry);
- } catch (DeserializationException e) {
- LOG.error("Ommiting from BA transaction: {}.", entry, e);
- }
- }
return target;
}
broker.setRouter(new SchemaAwareRpcBroker("/", SchemaContextProviders.fromSchemaService(schemaService)));
dataService = new DataBrokerImpl();
- dataService.setExecutor(broker.getExecutor());
+ //dataService.setExecutor(broker.getExecutor());
dataReg = context.registerService(DataBrokerService, dataService, emptyProperties);
dataProviderReg = context.registerService(DataProviderService, dataService, emptyProperties);
import static com.google.common.base.Preconditions.checkState;
-import java.io.Console;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Set;
import java.util.concurrent.Future;
-import javax.activation.UnsupportedDataTypeException;
-
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.DataModification;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
-import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
private NormalizedDataModification prepareMergedTransaction(
DataModification<InstanceIdentifier, CompositeNode> original) {
NormalizedDataModification normalized = new NormalizedDataModification(original);
- for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
- normalized.putDeepConfigurationData(entry.getKey(), entry.getValue());
- }
- for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
- normalized.putDeepOperationalData(entry.getKey(), entry.getValue());
- }
+ LOG.trace("Transaction: {} Removed Configuration {}, Removed Operational {}", original.getIdentifier(),
+ original.getRemovedConfigurationData(), original.getRemovedConfigurationData());
+ LOG.trace("Transaction: {} Created Configuration {}, Created Operational {}", original.getIdentifier(),
+ original.getCreatedConfigurationData().entrySet(), original.getCreatedOperationalData().entrySet());
+ LOG.trace("Transaction: {} Updated Configuration {}, Updated Operational {}", original.getIdentifier(),
+ original.getUpdatedConfigurationData().entrySet(), original.getUpdatedOperationalData().entrySet());
+
for (InstanceIdentifier entry : original.getRemovedConfigurationData()) {
normalized.deepRemoveConfigurationData(entry);
}
for (InstanceIdentifier entry : original.getRemovedOperationalData()) {
normalized.deepRemoveOperationalData(entry);
}
+ for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
+ normalized.putDeepConfigurationData(entry.getKey(), entry.getValue());
+ }
+ for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
+ normalized.putDeepOperationalData(entry.getKey(), entry.getValue());
+ }
return normalized;
}
public void putDeepConfigurationData(InstanceIdentifier entryKey, CompositeNode entryData) {
this.putCompositeNodeData(entryKey, entryData, CONFIGURATIONAL_DATA_STORE_MARKER);
}
-
+
public void putDeepOperationalData(InstanceIdentifier entryKey, CompositeNode entryData) {
this.putCompositeNodeData(entryKey, entryData, OPERATIONAL_DATA_STORE_MARKER);
}
this.putOperationalData(entryKey, entryData);
break;
- default :
+ default:
LOG.error(dataStoreIdentifier + " is NOT valid DataStore switch marker");
throw new RuntimeException(dataStoreIdentifier + " is NOT valid DataStore switch marker");
}
}
}
- private void putCompositeNodeData(InstanceIdentifier entryKey, CompositeNode entryData, String dataStoreIdentifier) {
+ private void putCompositeNodeData(InstanceIdentifier entryKey, CompositeNode entryData,
+ String dataStoreIdentifier) {
this.putData(entryKey, entryData, dataStoreIdentifier);
-
+
for (Node<?> child : entryData.getChildren()) {
- InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType()).toInstance();
+ InstanceIdentifier subEntryId = InstanceIdentifier.builder(entryKey).node(child.getNodeType())
+ .toInstance();
if (child instanceof CompositeNode) {
DataSchemaNode subSchema = schemaNodeFor(subEntryId);
CompositeNode compNode = (CompositeNode) child;
if (subSchema instanceof ListSchemaNode) {
ListSchemaNode listSubSchema = (ListSchemaNode) subSchema;
- Map<QName, Object> mapOfSubValues = this.getValuesFromListSchema(listSubSchema, (CompositeNode) child);
+ Map<QName, Object> mapOfSubValues = this.getValuesFromListSchema(listSubSchema,
+ (CompositeNode) child);
if (mapOfSubValues != null) {
- instanceId = InstanceIdentifier.builder(entryKey).nodeWithKey(listSubSchema.getQName(), mapOfSubValues).toInstance();
+ instanceId = InstanceIdentifier.builder(entryKey)
+ .nodeWithKey(listSubSchema.getQName(), mapOfSubValues).toInstance();
}
- }
- else if (subSchema instanceof ContainerSchemaNode) {
+ } else if (subSchema instanceof ContainerSchemaNode) {
ContainerSchemaNode containerSchema = (ContainerSchemaNode) subSchema;
instanceId = InstanceIdentifier.builder(entryKey).node(subSchema.getQName()).toInstance();
}
}
}
- private Map<QName, Object> getValuesFromListSchema (ListSchemaNode listSchema, CompositeNode entryData) {
+ private Map<QName, Object> getValuesFromListSchema(ListSchemaNode listSchema, CompositeNode entryData) {
List<QName> keyDef = listSchema.getKeyDefinition();
- if (keyDef != null && ! keyDef.isEmpty()) {
+ if (keyDef != null && !keyDef.isEmpty()) {
Map<QName, Object> map = new HashMap<QName, Object>();
for (QName key : keyDef) {
List<Node<?>> data = entryData.get(key);
- if (data != null && ! data.isEmpty()) {
+ if (data != null && !data.isEmpty()) {
for (Node<?> nodeData : data) {
if (nodeData instanceof SimpleNode<?>) {
map.put(key, data.get(0).getValue());
@Consumes({Draft02.MediaTypes.OPERATION+JSON, Draft02.MediaTypes.OPERATION+XML,
Draft02.MediaTypes.DATA+JSON, Draft02.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
- public StructuredData invokeRpc(@PathParam("identifier") String identifier, CompositeNode payload);
+ public StructuredData invokeRpc(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
@POST
@Path("/operations/{identifier:.+}")
@Produces({Draft02.MediaTypes.OPERATION+JSON, Draft02.MediaTypes.OPERATION+XML,
Draft02.MediaTypes.DATA+JSON, Draft02.MediaTypes.DATA+XML,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
- public StructuredData invokeRpc(@PathParam("identifier") String identifier, @DefaultValue("") String noPayload);
+ public StructuredData invokeRpc(@Encoded @PathParam("identifier") String identifier, @DefaultValue("") String noPayload);
@GET
@Path("/config/{identifier:.+}")
private def toUriString(Object object) {
if(object === null) return "";
-// return object.toString.replace("/",URI_SLASH_PLACEHOLDER)
return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET)
}
decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET))
}
return decodedPathArgs
+ }
+
+ def urlPathArgDecode(String pathArg) {
+ if (pathArg !== null) {
+ return URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET)
+ }
+ return null
}
}
}
override invokeRpc(String identifier, CompositeNode payload) {
- val rpc = identifier.rpcDefinition
- if (rpc === null) {
- throw new ResponseException(NOT_FOUND, "RPC does not exist.");
- }
+ val rpc = resolveIdentifierInInvokeRpc(identifier)
if (rpc.QName.namespace.toString == SAL_REMOTE_NAMESPACE && rpc.QName.localName == SAL_REMOTE_RPC_SUBSRCIBE) {
val value = normalizeNode(payload, rpc.input, null)
val pathNode = value?.getFirstSimpleByName(QName.create(rpc.QName, "path"))
if (!noPayload.nullOrEmpty) {
throw new ResponseException(UNSUPPORTED_MEDIA_TYPE, "Content-Type contains unsupported Media Type.");
}
- return callRpc(identifier.rpcDefinition, null)
+ val rpc = resolveIdentifierInInvokeRpc(identifier)
+ return callRpc(rpc, null)
+ }
+
+ def resolveIdentifierInInvokeRpc(String identifier) {
+ if (identifier.indexOf("/") === -1) {
+ val identifierDecoded = identifier.urlPathArgDecode
+ val rpc = identifierDecoded.rpcDefinition
+ if (rpc !== null) {
+ return rpc
+ }
+ throw new ResponseException(NOT_FOUND, "RPC does not exist.");
+ }
+ val slashErrorMsg = String.format("Identifier %n%s%ncan't contain slash character (/). +
+ If slash is part of identifier name then use %2F placeholder.",identifier)
+ throw new ResponseException(NOT_FOUND, slashErrorMsg);
}
private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) {
c.add(createServiceDependency()
.setService(IFlowProgrammerNotifier.class)
.setCallbacks("setFlowProgrammerNotifier",
- "unsetsetFlowProgrammerNotifier")
+ "unsetFlowProgrammerNotifier")
.setRequired(false));
c.add(createServiceDependency()
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
for (int i = 0; i < edges.size() - 1; i++) {
Edge current = edges.get(i);
Edge next = edges.get(i + 1);
- if (!current.getHeadNodeConnector().getNode()
- .equals(
- next.getTailNodeConnector()
- .getNode())) {
+ if (!current.getHeadNodeConnector().getNode().equals(next.getTailNodeConnector().getNode())) {
sequential = false;
+ break;
}
}
} else if (edges.size() == 0) {
* getter method for the Path
*
*
- * @return Return the list of edges that constitue the Path
+ * @return Return the list of edges that constitute the Path
*/
public List<Edge> getEdges() {
- return this.edges;
+ return (edges == null) ? Collections.<Edge>emptyList() : new ArrayList<Edge>(edges);
}
@Override
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
Path other = (Path) obj;
if (edges == null) {
- if (other.edges != null)
+ if (other.edges != null) {
return false;
- } else if (!edges.equals(other.edges))
+ }
+ } else if (!edges.equals(other.edges)) {
return false;
+ }
return true;
}