import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
import org.opendaylight.controller.sal.connection.IPluginOutConnectionService;
import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.IContainerAware;
import org.opendaylight.controller.sal.core.IContainerListener;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.Node.NodeIDType;
import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.EtherTypes;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NodeCreator;
*/
public class FlowProgrammerService implements IPluginInFlowProgrammerService,
IMessageListener, IContainerListener, IInventoryShimExternalListener,
- CommandProvider {
+ CommandProvider, IContainerAware {
private static final Logger log = LoggerFactory
.getLogger(FlowProgrammerService.class);
private IController controller;
action, "Invalid node type"));
}
+ Status status = validateFlow(flow);
+ if (!status.isSuccess()) {
+ return status;
+ }
+
if (controller != null) {
ISwitch sw = controller.getSwitch((Long) node.getID());
if (sw != null) {
"Internal plugin error"));
}
+ /*
+ * Method which runs openflow 1.0 specific validation on the requested flow
+ * This validation is needed because the openflow switch will silently accept
+ * the request and install only the applicable match fields
+ */
+ private Status validateFlow(Flow flow) {
+ Match m = flow.getMatch();
+ boolean isIPEthertypeSet = m.isPresent(MatchType.DL_TYPE)
+ && (m.getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.IPv4.shortValue()) || m
+ .getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.IPv6.shortValue()));
+
+ // network address check
+ if ((m.isPresent(MatchType.NW_SRC) || m.isPresent(MatchType.NW_DST)) && !isIPEthertypeSet) {
+ return new Status(StatusCode.NOTACCEPTABLE,
+ "The match on network source or destination address cannot be accepted if the match "
+ + "on proper ethertype is missing");
+ }
+
+ // transport protocol check
+ if (m.isPresent(MatchType.NW_PROTO) && !isIPEthertypeSet) {
+ return new Status(StatusCode.NOTACCEPTABLE,
+ "The match on network protocol cannot be accepted if the match on proper ethertype is missing");
+ }
+
+ // transport ports check
+ if ((m.isPresent(MatchType.TP_SRC) || m.isPresent(MatchType.TP_DST))
+ && (!isIPEthertypeSet || m.isAny(MatchType.NW_PROTO))) {
+ return new Status(
+ StatusCode.NOTACCEPTABLE,
+ "The match on transport source or destination port cannot be accepted if the match on network protocol and match on IP ethertype are missing");
+ }
+ return new Status(StatusCode.SUCCESS);
+ }
+
private Status modifyFlowInternal(Node node, Flow oldFlow, Flow newFlow, long rid) {
String action = "modify";
if (!node.getType().equals(NodeIDType.OPENFLOW)) {
return new Status(StatusCode.NOTACCEPTABLE, errorString("send",
action, "Invalid node type"));
}
+
+ Status status = validateFlow(newFlow);
+ if (!status.isSuccess()) {
+ return status;
+ }
+
if (controller != null) {
ISwitch sw = controller.getSwitch((Long) node.getID());
if (sw != null) {
*/
if (inPort == null
|| container.equals(GlobalConstants.DEFAULT.toString())
- || this.containerToNc.get(container).contains(inPort)) {
+ || (containerToNc.containsKey(container) && containerToNc.get(container).contains(inPort))) {
notifier.flowRemoved(node, flow);
}
}
for (Map.Entry<String, IFlowProgrammerNotifier> containerNotifier : flowProgrammerNotifiers
.entrySet()) {
IFlowProgrammerNotifier notifier = containerNotifier.getValue();
- notifier.flowErrorReported(node, rid, errorMsg);
+ notifier.flowErrorReported(node, rid, Utils.getOFErrorString(errorMsg));
}
}
@Override
public void nodeConnectorUpdated(String containerName, NodeConnector p,
UpdateType type) {
- Set<NodeConnector> target = null;
-
switch (type) {
case ADDED:
if (!containerToNc.containsKey(containerName)) {
case CHANGED:
break;
case REMOVED:
- target = containerToNc.get(containerName);
+ Set<NodeConnector> target = containerToNc.get(containerName);
if (target != null) {
target.remove(p);
}
ci.println("Max num of async messages sent prior to the Barrier message is "
+ barrierMessagePriorCount);
}
+
+ @Override
+ public void containerCreate(String containerName) {
+ // do nothing
+ }
+
+ @Override
+ public void containerDestroy(String containerName) {
+ containerToNc.remove(containerName);
+ }
}