From c0dc1379d4450a895ff58d8b6f4feb639ff73230 Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Fri, 20 Sep 2013 09:45:22 -0700 Subject: [PATCH] FRM to remove flows on switchport admin down - When a swithport is shutdown FRM should uninstall the flows which have that port as input/output - Similarly when a port is moved to admin up state, FRM should install the interested flows from the config Change-Id: I890a4fb6541c9a01b0adacba7af9c0b8c2d69878 Signed-off-by: Alessandro Boch --- .../internal/ContainerManager.java | 4 +- .../internal/ForwardingRulesManager.java | 151 ++++++++++++------ 2 files changed, 106 insertions(+), 49 deletions(-) diff --git a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java index 5058e2a0ac..d67ee94b62 100644 --- a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java +++ b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java @@ -291,10 +291,10 @@ public class ContainerManager extends Authorization implements IContaine for (Match match : conf.getMatches()) { ContainerFlow cFlow = new ContainerFlow(match); if (delete) { - logger.trace("Removing Flow Spec %s from Container {}", conf.getName(), containerName); + logger.trace("Removing Flow Spec {} from Container {}", conf.getName(), containerName); container.deleteFlowSpec(cFlow); } else { - logger.trace("Adding Flow Spec %s to Container {}", conf.getName(), containerName); + logger.trace("Adding Flow Spec {} to Container {}", conf.getName(), containerName); container.addFlowSpec(cFlow); } diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java index fc18079b0a..e9a56d6113 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java @@ -57,6 +57,7 @@ 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.core.Config; import org.opendaylight.controller.sal.core.ContainerFlow; import org.opendaylight.controller.sal.core.IContainer; import org.opendaylight.controller.sal.core.IContainerListener; @@ -102,7 +103,7 @@ public class ForwardingRulesManager implements IConfigurationContainerAware, IInventoryListener, IObjectReader, - ICacheUpdateAware, + ICacheUpdateAware, CommandProvider, IFlowProgrammerListener { private static final String NODEDOWN = "Node is Down"; @@ -1312,7 +1313,6 @@ public class ForwardingRulesManager implements retrieveCaches(); } - @SuppressWarnings("deprecation") private void allocateCaches() { if (this.clusterContainerService == null) { log.warn("Un-initialized clusterContainerService, can't create cache"); @@ -1368,7 +1368,7 @@ public class ForwardingRulesManager implements } } - @SuppressWarnings({ "unchecked", "deprecation" }) + @SuppressWarnings({ "unchecked" }) private void retrieveCaches() { ConcurrentMap map; @@ -2174,7 +2174,99 @@ public class ForwardingRulesManager implements @Override public void notifyNodeConnector(NodeConnector nodeConnector, UpdateType type, Map propMap) { + boolean updateStaticFlowCluster = false; + + switch (type) { + case ADDED: + break; + case CHANGED: + Config config = (propMap == null) ? null : (Config) propMap.get(Config.ConfigPropName); + if (config != null) { + switch (config.getValue()) { + case Config.ADMIN_DOWN: + log.trace("Port {} is administratively down: uninstalling interested flows", nodeConnector); + updateStaticFlowCluster = removeFlowsOnNodeConnectorDown(nodeConnector); + break; + case Config.ADMIN_UP: + log.trace("Port {} is administratively up: installing interested flows", nodeConnector); + updateStaticFlowCluster = installFlowsOnNodeConnectorUp(nodeConnector); + break; + case Config.ADMIN_UNDEF: + break; + default: + } + } + break; + case REMOVED: + // This is the case where a switch port is removed from the SDN agent space + log.trace("Port {} was removed from our control: uninstalling interested flows", nodeConnector); + updateStaticFlowCluster = removeFlowsOnNodeConnectorDown(nodeConnector); + break; + default: + + } + + if (updateStaticFlowCluster) { + refreshClusterStaticFlowsStatus(nodeConnector.getNode()); + } + } + + /* + * It goes through the static flows configuration, it identifies the ones + * which have the specified node connector as input or output port and + * install them on the network node if they are marked to be installed in + * hardware and their status shows they were not installed yet + */ + private boolean installFlowsOnNodeConnectorUp(NodeConnector nodeConnector) { + boolean updated = false; + List flowConfigForNode = getStaticFlows(nodeConnector.getNode()); + for (FlowConfig flowConfig : flowConfigForNode) { + if (doesFlowContainNodeConnector(flowConfig.getFlow(), nodeConnector)) { + if (flowConfig.installInHw() && !flowConfig.getStatus().equals(SUCCESS)) { + Status status = this.installFlowEntry(flowConfig.getFlowEntry()); + if (!status.isSuccess()) { + flowConfig.setStatus(status.getDescription()); + } else { + flowConfig.setStatus(SUCCESS); + } + updated = true; + } + } + } + return updated; + } + /* + * Remove from the network node all the flows which have the specified node + * connector as input or output port. If any of the flow entry is a static + * flow, it updates the correspondent configuration. + */ + private boolean removeFlowsOnNodeConnectorDown(NodeConnector nodeConnector) { + boolean updated = false; + List nodeFlowEntries = nodeFlows.get(nodeConnector.getNode()); + if (nodeFlowEntries == null) { + return updated; + } + for (FlowEntryInstall fei : new ArrayList(nodeFlowEntries)) { + if (doesFlowContainNodeConnector(fei.getInstall().getFlow(), nodeConnector)) { + Status status = this.removeEntryInternal(fei, true); + if (!status.isSuccess()) { + continue; + } + /* + * If the flow entry is a static flow, then update its + * configuration + */ + if (fei.getGroupName().equals(FlowConfig.STATICFLOWGROUP)) { + FlowConfig flowConfig = getStaticFlow(fei.getFlowName(), fei.getNode()); + if (flowConfig != null) { + flowConfig.setStatus(PORTREMOVED); + updated = true; + } + } + } + } + return updated; } private FlowConfig getDerivedFlowConfig(FlowConfig original, String configName, Short port) { @@ -2582,57 +2674,22 @@ public class ForwardingRulesManager implements switch (t) { case REMOVED: - - List nodeFlowEntries = nodeFlows.get(nc.getNode()); - if (nodeFlowEntries == null) { - return; - } - for (FlowEntryInstall fei : new ArrayList(nodeFlowEntries)) { - if (doesFlowContainNodeConnector(fei.getInstall().getFlow(), nc)) { - Status status = this.removeEntryInternal(fei, true); - if (!status.isSuccess()) { - continue; - } - /* - * If the flow entry is a static flow, then update its - * configuration - */ - if (fei.getGroupName().equals(FlowConfig.STATICFLOWGROUP)) { - FlowConfig flowConfig = getStaticFlow(fei.getFlowName(), fei.getNode()); - if (flowConfig != null) { - flowConfig.setStatus(PORTREMOVED); - updateStaticFlowCluster = true; - } - } - } - } - if (updateStaticFlowCluster) { - refreshClusterStaticFlowsStatus(nc.getNode()); - } + log.trace("Port {} was removed from container: uninstalling interested flows", nc); + updateStaticFlowCluster = removeFlowsOnNodeConnectorDown(nc); break; case ADDED: - List flowConfigForNode = getStaticFlows(nc.getNode()); - for (FlowConfig flowConfig : flowConfigForNode) { - if (doesFlowContainNodeConnector(flowConfig.getFlow(), nc)) { - if (flowConfig.installInHw()) { - Status status = this.installFlowEntry(flowConfig.getFlowEntry()); - if (!status.isSuccess()) { - flowConfig.setStatus(status.getDescription()); - } else { - flowConfig.setStatus(SUCCESS); - } - updateStaticFlowCluster = true; - } - } - } - if (updateStaticFlowCluster) { - refreshClusterStaticFlowsStatus(nc.getNode()); - } + log.trace("Port {} was added to container: reinstall interested flows", nc); + updateStaticFlowCluster = installFlowsOnNodeConnectorUp(nc); + break; case CHANGED: break; default: } + + if (updateStaticFlowCluster) { + refreshClusterStaticFlowsStatus(nc.getNode()); + } } @Override -- 2.36.6