Adding of specific flow validation in of plugin 93/3493/4
authorAlessandro Boch <aboch@cisco.com>
Thu, 5 Dec 2013 09:25:26 +0000 (01:25 -0800)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 9 Dec 2013 23:58:11 +0000 (23:58 +0000)
- An of 1.0 switch silently accepts a flowmod which
  match does not have proper hierarchy of fields set.
  It installs the flow discarding the incorrect fields.
  This would cause inconsistency between flows in hw
  and flows in sw. The application needs to be notified
  that the flow would not be accepted as is by the openflow
  switch.

Change-Id: If70a642f2835147856d3517ad82faef3e9bb1e2c
Signed-off-by: Alessandro Boch <aboch@cisco.com>
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java

index f26bcf7..1a67c4c 100644 (file)
@@ -38,6 +38,7 @@ 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.NodeCreator;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.sal.utils.StatusCode;
@@ -225,6 +226,11 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
                     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) {
@@ -256,12 +262,52 @@ public class FlowProgrammerService implements IPluginInFlowProgrammerService,
                 "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(IPProtocols.IPV4.byteValue()) || m
+                        .getField(MatchType.DL_TYPE).getValue().equals(IPProtocols.IPV6.byteValue()));
+
+        // 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) {