Merge "FlowConfig to only run syntactic validation"
authorJason Ye <yisye@cisco.com>
Thu, 27 Feb 2014 20:25:04 +0000 (20:25 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 27 Feb 2014 20:25:04 +0000 (20:25 +0000)
1  2 
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java

index bdbf7acd5f6781fe153fe35421bbfe3aec6dbbd8,be95bc98d54a272da3ab533d701e0f9f3c9c8a94..614c39e0608fe1a7d384b854588d143c0ad5761e
@@@ -50,6 -50,9 +50,9 @@@ import org.opendaylight.controller.forw
  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;
@@@ -243,6 -246,57 +246,57 @@@ public class ForwardingRulesManager imp
          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