Cannot delete static flow through northbound
[controller.git] / opendaylight / forwardingrulesmanager / implementation / src / main / java / org / opendaylight / controller / forwardingrulesmanager / internal / ForwardingRulesManager.java
index fe1ee60e6b46285a348e560774f095f6aa96a91e..520825762a40e8bfec9b89c5c0541c41edeedfc1 100644 (file)
@@ -11,7 +11,6 @@ package org.opendaylight.controller.forwardingrulesmanager.internal;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -52,10 +51,7 @@ import org.opendaylight.controller.forwardingrulesmanager.PortGroupProvider;
 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.Controller;
-import org.opendaylight.controller.sal.action.Flood;
 import org.opendaylight.controller.sal.action.Output;
-import org.opendaylight.controller.sal.action.PopVlan;
 import org.opendaylight.controller.sal.connection.ConnectionLocality;
 import org.opendaylight.controller.sal.core.Config;
 import org.opendaylight.controller.sal.core.ContainerFlow;
@@ -72,10 +68,7 @@ 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.IObjectReader;
-import org.opendaylight.controller.sal.utils.IPProtocols;
-import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
 import org.opendaylight.controller.sal.utils.NodeCreator;
 import org.opendaylight.controller.sal.utils.ObjectReader;
 import org.opendaylight.controller.sal.utils.ObjectWriter;
@@ -106,11 +99,12 @@ public class ForwardingRulesManager implements
         ICacheUpdateAware<Object,Object>,
         CommandProvider,
         IFlowProgrammerListener {
-    private static final String NODEDOWN = "Node is Down";
-    private static final String SUCCESS = StatusCode.SUCCESS.toString();
+
     private static final Logger log = LoggerFactory.getLogger(ForwardingRulesManager.class);
-    private static final String PORTREMOVED = "Port removed";
     private static final Logger logsync = LoggerFactory.getLogger("FRMsync");
+    private static final String PORTREMOVED = "Port removed";
+    private static final String NODEDOWN = "Node is Down";
+    private static final String INVALID_FLOW_ENTRY = "Invalid FlowEntry";
     private String frmFileName;
     private String portGroupFileName;
     private ConcurrentMap<Integer, FlowConfig> staticFlows;
@@ -164,8 +158,8 @@ public class ForwardingRulesManager implements
      * necessity non-transactional as long as need to be able to synchronize
      * states also while a transaction is in progress
      */
-    static final String WORKORDERCACHE = "frm.workOrder";
-    static final String WORKSTATUSCACHE = "frm.workStatus";
+    static final String WORK_ORDER_CACHE = "frm.workOrder";
+    static final String WORK_STATUS_CACHE = "frm.workStatus";
 
     /*
      * Data structure responsible for distributing the FlowEntryInstall requests
@@ -268,11 +262,34 @@ public class ForwardingRulesManager implements
     private Status addEntry(FlowEntry flowEntry, boolean async) {
 
         // Sanity Check
-        if (flowEntry == null || flowEntry.getNode() == null) {
-            String msg = "Invalid FlowEntry";
-            String logMsg = msg + ": {}";
+        if (flowEntry == null || flowEntry.getNode() == null || flowEntry.getFlow() == null) {
+            String logMsg = INVALID_FLOW_ENTRY + ": {}";
             log.warn(logMsg, flowEntry);
-            return new Status(StatusCode.NOTACCEPTABLE, msg);
+            return new Status(StatusCode.NOTACCEPTABLE, INVALID_FLOW_ENTRY);
+        }
+
+        /*
+         * Redundant Check: Check if the request is a redundant one from the
+         * same application the flowEntry is equal to an existing one. Given we
+         * do not have an application signature in the requested FlowEntry yet,
+         * we are here detecting the above condition by comparing the flow
+         * names, if set. If they are equal to the installed flow, most likely
+         * this is a redundant installation request from the same application
+         * and we can silently return success
+         *
+         * TODO: in future a sort of application reference list mechanism will
+         * be added to the FlowEntry so that exact flow can be used by different
+         * applications.
+         */
+        FlowEntry present = this.originalSwView.get(flowEntry);
+        if (present != null) {
+            boolean sameFlow = present.getFlow().equals(flowEntry.getFlow());
+            boolean sameApp = present.getFlowName() != null && present.getFlowName().equals(flowEntry.getFlowName());
+            if (sameFlow && sameApp) {
+                log.trace("Skipping redundant request for flow {} on node {}", flowEntry.getFlowName(),
+                        flowEntry.getNode());
+                return new Status(StatusCode.SUCCESS, "Entry is already present");
+            }
         }
 
         /*
@@ -387,8 +404,8 @@ public class ForwardingRulesManager implements
 
         // Sanity checks
         if (currentFlowEntry == null || currentFlowEntry.getNode() == null || newFlowEntry == null
-                || newFlowEntry.getNode() == null) {
-            String msg = "Modify: Invalid FlowEntry";
+                || newFlowEntry.getNode() == null || newFlowEntry.getFlow() == null) {
+            String msg = "Modify: " + INVALID_FLOW_ENTRY;
             String logMsg = msg + ": {} or {}";
             log.warn(logMsg, currentFlowEntry, newFlowEntry);
             return new Status(StatusCode.NOTACCEPTABLE, msg);
@@ -608,11 +625,10 @@ public class ForwardingRulesManager implements
         Status error = new Status(null, null);
 
         // Sanity Check
-        if (flowEntry == null || flowEntry.getNode() == null) {
-            String msg = "Invalid FlowEntry";
-            String logMsg = msg + ": {}";
+        if (flowEntry == null || flowEntry.getNode() == null || flowEntry.getFlow() == null) {
+            String logMsg = INVALID_FLOW_ENTRY + ": {}";
             log.warn(logMsg, flowEntry);
-            return new Status(StatusCode.NOTACCEPTABLE, msg);
+            return new Status(StatusCode.NOTACCEPTABLE, INVALID_FLOW_ENTRY);
         }
 
         // Derive the container flows merged installed entries
@@ -1385,10 +1401,10 @@ public class ForwardingRulesManager implements
             clusterContainerService.createCache("frm.TSPolicies",
                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
 
-            clusterContainerService.createCache(WORKSTATUSCACHE,
+            clusterContainerService.createCache(WORK_STATUS_CACHE,
                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
 
-            clusterContainerService.createCache(WORKORDERCACHE,
+            clusterContainerService.createCache(WORK_ORDER_CACHE,
                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
 
         } catch (CacheConfigException cce) {
@@ -1480,18 +1496,18 @@ public class ForwardingRulesManager implements
             log.error("Retrieval of frm.TSPolicies cache failed for Container {}", container.getName());
         }
 
-        map = clusterContainerService.getCache(WORKORDERCACHE);
+        map = clusterContainerService.getCache(WORK_ORDER_CACHE);
         if (map != null) {
             workOrder = (ConcurrentMap<FlowEntryDistributionOrder, FlowEntryInstall>) map;
         } else {
-            log.error("Retrieval of " + WORKORDERCACHE + " cache failed for Container {}", container.getName());
+            log.error("Retrieval of " + WORK_ORDER_CACHE + " cache failed for Container {}", container.getName());
         }
 
-        map = clusterContainerService.getCache(WORKSTATUSCACHE);
+        map = clusterContainerService.getCache(WORK_STATUS_CACHE);
         if (map != null) {
             workStatus = (ConcurrentMap<FlowEntryDistributionOrder, Status>) map;
         } else {
-            log.error("Retrieval of " + WORKSTATUSCACHE + " cache failed for Container {}", container.getName());
+            log.error("Retrieval of " + WORK_STATUS_CACHE + " cache failed for Container {}", container.getName());
         }
     }
 
@@ -1537,7 +1553,7 @@ public class ForwardingRulesManager implements
         boolean multipleFlowPush = false;
         String error;
         Status status;
-        config.setStatus(SUCCESS);
+        config.setStatus(StatusCode.SUCCESS.toString());
 
         // Presence check
         if (flowConfigExists(config)) {
@@ -1615,7 +1631,7 @@ public class ForwardingRulesManager implements
                 continue;
             }
             if (config.getNode().equals(node)) {
-                if (config.installInHw() && !config.getStatus().equals(SUCCESS)) {
+                if (config.installInHw() && !config.getStatus().equals(StatusCode.SUCCESS.toString())) {
                     Status status = this.installFlowEntryAsync(config.getFlowEntry());
                     config.setStatus(status.getDescription());
                 }
@@ -1669,7 +1685,7 @@ public class ForwardingRulesManager implements
                     config.setStatus("Removed from node because in container mode");
                     break;
                 case REMOVED:
-                    config.setStatus(SUCCESS);
+                    config.setStatus(StatusCode.SUCCESS.toString());
                     break;
                 default:
                 }
@@ -1856,7 +1872,7 @@ public class ForwardingRulesManager implements
                                     .installFlowEntry(target.getFlowEntry());
             if (status.isSuccess()) {
                 // Update Configuration database
-                target.setStatus(SUCCESS);
+                target.setStatus(StatusCode.SUCCESS.toString());
                 target.toggleInstallation();
                 staticFlows.put(key, target);
             }
@@ -2067,26 +2083,6 @@ public class ForwardingRulesManager implements
     public void subnetNotify(Subnet sub, boolean add) {
     }
 
-    private void installImplicitARPReplyPunt(Node node) {
-
-        if (node == null) {
-            return;
-        }
-
-        List<String> puntAction = new ArrayList<String>();
-        puntAction.add(ActionType.CONTROLLER.toString());
-
-        FlowConfig allowARP = new FlowConfig();
-        allowARP.setInstallInHw(true);
-        allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP Reply" + FlowConfig.INTERNALSTATICFLOWEND);
-        allowARP.setPriority("500");
-        allowARP.setNode(node);
-        allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase());
-        allowARP.setDstMac(HexEncode.bytesToHexString(switchManager.getControllerMAC()));
-        allowARP.setActions(puntAction);
-        addStaticFlowInternal(allowARP, true); // skip validation on internal static flow name
-    }
-
     /**
      * (non-Javadoc)
      *
@@ -2259,12 +2255,12 @@ public class ForwardingRulesManager implements
         List<FlowConfig> flowConfigForNode = getStaticFlows(nodeConnector.getNode());
         for (FlowConfig flowConfig : flowConfigForNode) {
             if (doesFlowContainNodeConnector(flowConfig.getFlow(), nodeConnector)) {
-                if (flowConfig.installInHw() && !flowConfig.getStatus().equals(SUCCESS)) {
+                if (flowConfig.installInHw() && !flowConfig.getStatus().equals(StatusCode.SUCCESS.toString())) {
                     Status status = this.installFlowEntry(flowConfig.getFlowEntry());
                     if (!status.isSuccess()) {
                         flowConfig.setStatus(status.getDescription());
                     } else {
-                        flowConfig.setStatus(SUCCESS);
+                        flowConfig.setStatus(StatusCode.SUCCESS.toString());
                     }
                     updated = true;
                 }
@@ -2411,17 +2407,6 @@ public class ForwardingRulesManager implements
         return true;
     }
 
-    private void usePortGroupConfig(String name) {
-        PortGroupConfig config = portGroupConfigs.get(name);
-        if (config == null) {
-            return;
-        }
-        if (portGroupProvider != null) {
-            Map<Node, PortGroup> data = portGroupProvider.getPortGroupData(config);
-            portGroupData.put(config, data);
-        }
-    }
-
     @Override
     public Map<String, PortGroupConfig> getPortGroupConfigs() {
         return portGroupConfigs;
@@ -2899,121 +2884,9 @@ public class ForwardingRulesManager implements
     @Override
     public String getHelp() {
         StringBuffer help = new StringBuffer();
-        help.append("---FRM Matrix Application---\n");
-        help.append("\t printMatrixData        - Prints the Matrix Configs\n");
-        help.append("\t addMatrixConfig <name> <regex>\n");
-        help.append("\t delMatrixConfig <name>\n");
-        help.append("\t useMatrixConfig <name>\n");
         return help.toString();
     }
 
-    public void _printMatrixData(CommandInterpreter ci) {
-        ci.println("Configs : ");
-        ci.println("---------");
-        ci.println(portGroupConfigs);
-
-        ci.println("Data : ");
-        ci.println("------");
-        ci.println(portGroupData);
-    }
-
-    public void _addMatrixConfig(CommandInterpreter ci) {
-        String name = ci.nextArgument();
-        String regex = ci.nextArgument();
-        addPortGroupConfig(name, regex, false);
-    }
-
-    public void _delMatrixConfig(CommandInterpreter ci) {
-        String name = ci.nextArgument();
-        delPortGroupConfig(name);
-    }
-
-    public void _useMatrixConfig(CommandInterpreter ci) {
-        String name = ci.nextArgument();
-        usePortGroupConfig(name);
-    }
-
-    public void _arpPunt(CommandInterpreter ci) {
-        String switchId = ci.nextArgument();
-        long swid = HexEncode.stringToLong(switchId);
-        Node node = NodeCreator.createOFNode(swid);
-        installImplicitARPReplyPunt(node);
-    }
-
-    public void _frmaddflow(CommandInterpreter ci) throws UnknownHostException {
-        Node node = null;
-        String nodeId = ci.nextArgument();
-        if (nodeId == null) {
-            ci.print("Node id not specified");
-            return;
-        }
-        try {
-            node = NodeCreator.createOFNode(Long.valueOf(nodeId));
-        } catch (NumberFormatException e) {
-            ci.print("Node id not a number");
-            return;
-        }
-        ci.println(this.programmer.addFlow(node, getSampleFlow(node)));
-    }
-
-    public void _frmremoveflow(CommandInterpreter ci) throws UnknownHostException {
-        Node node = null;
-        String nodeId = ci.nextArgument();
-        if (nodeId == null) {
-            ci.print("Node id not specified");
-            return;
-        }
-        try {
-            node = NodeCreator.createOFNode(Long.valueOf(nodeId));
-        } catch (NumberFormatException e) {
-            ci.print("Node id not a number");
-            return;
-        }
-        ci.println(this.programmer.removeFlow(node, getSampleFlow(node)));
-    }
-
-    private Flow getSampleFlow(Node node) throws UnknownHostException {
-        NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 24, node);
-        NodeConnector oport = NodeConnectorCreator.createOFNodeConnector((short) 30, node);
-        byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc };
-        byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f };
-        InetAddress srcIP = InetAddress.getByName("172.28.30.50");
-        InetAddress dstIP = InetAddress.getByName("171.71.9.52");
-        InetAddress ipMask = InetAddress.getByName("255.255.255.0");
-        InetAddress ipMask2 = InetAddress.getByName("255.0.0.0");
-        short ethertype = EtherTypes.IPv4.shortValue();
-        short vlan = (short) 27;
-        byte vlanPr = 3;
-        Byte tos = 4;
-        byte proto = IPProtocols.TCP.byteValue();
-        short src = (short) 55000;
-        short dst = 80;
-
-        /*
-         * Create a SAL Flow aFlow
-         */
-        Match match = new Match();
-        match.setField(MatchType.IN_PORT, port);
-        match.setField(MatchType.DL_SRC, srcMac);
-        match.setField(MatchType.DL_DST, dstMac);
-        match.setField(MatchType.DL_TYPE, ethertype);
-        match.setField(MatchType.DL_VLAN, vlan);
-        match.setField(MatchType.DL_VLAN_PR, vlanPr);
-        match.setField(MatchType.NW_SRC, srcIP, ipMask);
-        match.setField(MatchType.NW_DST, dstIP, ipMask2);
-        match.setField(MatchType.NW_TOS, tos);
-        match.setField(MatchType.NW_PROTO, proto);
-        match.setField(MatchType.TP_SRC, src);
-        match.setField(MatchType.TP_DST, dst);
-
-        List<Action> actions = new ArrayList<Action>();
-        actions.add(new Output(oport));
-        actions.add(new PopVlan());
-        actions.add(new Flood());
-        actions.add(new Controller());
-        return new Flow(match, actions);
-    }
-
     @Override
     public Status saveConfiguration() {
         return saveConfig();
@@ -3127,7 +3000,7 @@ public class ForwardingRulesManager implements
         if (target != null) {
             // Update Configuration database
             target.toggleInstallation();
-            target.setStatus(SUCCESS);
+            target.setStatus(StatusCode.SUCCESS.toString());
             staticFlows.put(key, target);
         }
 
@@ -3245,7 +3118,7 @@ public class ForwardingRulesManager implements
              */
             return;
         }
-        if (cacheName.equals(WORKORDERCACHE)) {
+        if (cacheName.equals(WORK_ORDER_CACHE)) {
             logsync.trace("Got a WorkOrderCacheUpdate for {}", key);
             /*
              * This is the case of one workOrder becoming available, so we need
@@ -3263,7 +3136,7 @@ public class ForwardingRulesManager implements
                 // processing
                 pendingEvents.offer(new WorkOrderEvent(fe, (FlowEntryInstall) new_value));
             }
-        } else if (cacheName.equals(WORKSTATUSCACHE)) {
+        } else if (cacheName.equals(WORK_STATUS_CACHE)) {
             logsync.trace("Got a WorkStatusCacheUpdate for {}", key);
             /*
              * This is the case of one workOrder being completed and a status
@@ -3293,4 +3166,37 @@ public class ForwardingRulesManager implements
          * Do nothing
          */
     }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<FlowEntry> getFlowEntriesForNode(Node node) {
+        List<FlowEntry> list = new ArrayList<FlowEntry>();
+        if (node != null) {
+            for (Map.Entry<FlowEntry, FlowEntry> entry : this.originalSwView.entrySet()) {
+                if (node.equals(entry.getKey().getNode())) {
+                    list.add(entry.getKey().clone());
+                }
+            }
+        }
+        return list;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<FlowEntry> getInstalledFlowEntriesForNode(Node node) {
+        List<FlowEntry> list = new ArrayList<FlowEntry>();
+        if (node != null) {
+            List<FlowEntryInstall> flowEntryInstallList = this.nodeFlows.get(node);
+            if(flowEntryInstallList != null) {
+                for(FlowEntryInstall fi: flowEntryInstallList) {
+                    list.add(fi.getInstall().clone());
+                }
+            }
+        }
+        return list;
+    }
 }