From 1f9b410fe9b4b27fe88995b059513a1b5c6ce9ac Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Tue, 30 Jul 2013 15:45:31 -0700 Subject: [PATCH] Per container flow statistics filtering to account cFlows ISSUE: ReadServiceFilter in openflow protocol plugin while trying to derive to which container a flow statistics object belongs, it does not take into account the container flows (cFlows). CHANGES: - Have ReadServiceFilter maintain a map of container to container flows - Have flowBelongToContainer() account the cFlows while filtering the Flow objects - Changed the other container maps to concurrent maps - Other minor style changes Change-Id: I2d41fa2111334d57ef3179e907fea0bf268943e7 Signed-off-by: Alessandro Boch --- .../openflow/internal/ReadServiceFilter.java | 138 +++++++++--------- 1 file changed, 72 insertions(+), 66 deletions(-) diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java index 7f9a13e92a..2c8708f20e 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java @@ -11,7 +11,6 @@ package org.opendaylight.controller.protocol_plugin.openflow.internal; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -55,18 +54,16 @@ import org.slf4j.LoggerFactory; /** * Read Service shim layer which is in charge of filtering the flow statistics * based on container. It is a Global instance. - * - * - * */ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener, IOFStatisticsListener { private static final Logger logger = LoggerFactory .getLogger(ReadServiceFilter.class); private IController controller = null; private IOFStatisticsManager statsMgr = null; - private Map> containerToNc; - private Map> containerToNode; - private Map> containerToNt; + private ConcurrentMap> containerToNc; + private ConcurrentMap> containerToNode; + private ConcurrentMap> containerToNt; + private ConcurrentMap> containerFlows; private ConcurrentMap readFilterInternalListeners; public void setController(IController core) { @@ -118,9 +115,10 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener * */ void init() { - containerToNc = new HashMap>(); - containerToNt = new HashMap>(); - containerToNode = new HashMap>(); + containerToNc = new ConcurrentHashMap>(); + containerToNt = new ConcurrentHashMap>(); + containerToNode = new ConcurrentHashMap>(); + containerFlows = new ConcurrentHashMap>(); readFilterInternalListeners = new ConcurrentHashMap(); } @@ -160,8 +158,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener } @Override - public FlowOnNode readFlow(String container, Node node, Flow flow, - boolean cached) { + public FlowOnNode readFlow(String container, Node node, Flow flow, boolean cached) { if (controller == null) { // Avoid to provide cached statistics if controller went down. @@ -186,17 +183,11 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener } } + // Convert and filter the statistics per container + List flowOnNodeList = new FlowStatisticsConverter(ofList).getFlowOnNodeList(node); + List filteredList = filterFlowListPerContainer(container, node, flowOnNodeList); - /* - * Convert and filter the statistics per container - */ - List flowOnNodeList = new FlowStatisticsConverter(ofList) - .getFlowOnNodeList(node); - List filteredList = filterFlowListPerContainer(container, - node, flowOnNodeList); - - return (filteredList == null || filteredList.isEmpty()) ? null - : filteredList.get(0); + return (filteredList == null || filteredList.isEmpty()) ? null : filteredList.get(0); } @Override @@ -208,13 +199,9 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener .getOFFlowStatistics(sid) : statsMgr.queryStatistics(sid, OFStatisticsType.FLOW, null); - /* - * Convert and filter the statistics per container - */ - List flowOnNodeList = new FlowStatisticsConverter(ofList) - .getFlowOnNodeList(node); - List filteredList = filterFlowListPerContainer(container, - node, flowOnNodeList); + // Convert and filter the statistics per container + List flowOnNodeList = new FlowStatisticsConverter(ofList).getFlowOnNodeList(node); + List filteredList = filterFlowListPerContainer(container, node, flowOnNodeList); return (filteredList == null) ? null : filteredList; @@ -233,7 +220,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener .getOFDescStatistics(sid) : statsMgr.queryStatistics(sid, OFStatisticsType.DESC, null); - return new DescStatisticsConverter(ofList).getHwDescription(); + return new DescStatisticsConverter(ofList).getHwDescription(); } /** @@ -271,8 +258,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener * @param list * @return */ - public List filterPortListPerContainer(String container, - long switchId, List list) { + public List filterPortListPerContainer(String container, long switchId, List list) { if (list == null) { return null; } @@ -304,8 +290,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener for (OFStatistics stat : list) { OFTableStatistics target = (OFTableStatistics) stat; - NodeTable nt = NodeTableCreator.createOFNodeTable( - target.getTableId(), NodeCreator.createOFNode(switchId)); + NodeTable nt = NodeTableCreator.createOFNodeTable(target.getTableId(), NodeCreator.createOFNode(switchId)); if (containerOwnsNodeTable(container, nt)) { newList.add(target); } @@ -328,9 +313,9 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener if (container.equals(GlobalConstants.DEFAULT.toString())) { return true; } - return (flowPortsBelongToContainer(container, node, flow) - && flowVlanBelongsToContainer(container, node, flow) && flowSpecAllowsFlow( - container, flow.getMatch())); + return (flowPortsBelongToContainer(container, node, flow) && + flowVlanBelongsToContainer(container, node, flow) && + isFlowAllowedByContainer(container, flow)); } /** @@ -366,14 +351,23 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener } /** - * Returns whether the container flowspec allows the passed flow + * Returns whether the container flows allow the passed flow * * @param container * @param match * @return */ - private boolean flowSpecAllowsFlow(String container, Match match) { - return true; // Always true for now + private boolean isFlowAllowedByContainer(String container, Flow flow) { + Set cFlowSet = this.containerFlows.get(container); + if (cFlowSet == null || cFlowSet.isEmpty()) { + return true; + } + for (ContainerFlow cFlow : cFlowSet) { + if (cFlow.allowsFlow(flow)) { + return true; + } + } + return false; } /** @@ -402,9 +396,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener Flow flow) { Match m = flow.getMatch(); if (m.isPresent(MatchType.IN_PORT)) { - NodeConnector inPort = (NodeConnector) m - .getField(MatchType.IN_PORT).getValue(); - + NodeConnector inPort = (NodeConnector) m.getField(MatchType.IN_PORT).getValue(); // If the incoming port is specified, check if it belongs to if (!containerOwnsNodeConnector(container, inPort)) { return false; @@ -414,8 +406,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener // If an outgoing port is specified, it must belong to this container for (Action action : flow.getActions()) { if (action.getType() == ActionType.OUTPUT) { - NodeConnector outPort = ((Output) action) - .getPort(); + NodeConnector outPort = ((Output) action).getPort(); if (!containerOwnsNodeConnector(container, outPort)) { return false; } @@ -427,12 +418,28 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener @Override public void containerFlowUpdated(String containerName, ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) { - // TODO + Set cFlowSet = containerFlows.get(containerName); + switch (t) { + case ADDED: + if (cFlowSet == null) { + cFlowSet = new HashSet(); + containerFlows.put(containerName, cFlowSet); + } + cFlowSet.add(currentFlow); + case CHANGED: + break; + case REMOVED: + if (cFlowSet != null) { + cFlowSet.remove(currentFlow); + } + break; + default: + break; + } } @Override - public void nodeConnectorUpdated(String containerName, NodeConnector p, - UpdateType type) { + public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType type) { switch (type) { case ADDED: @@ -486,8 +493,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener } @Override - public NodeConnectorStatistics readNodeConnector( - String containerName, NodeConnector connector, boolean cached) { + public NodeConnectorStatistics readNodeConnector(String containerName, NodeConnector connector, boolean cached) { if (!containerOwnsNodeConnector(containerName, connector)) { return null; } @@ -498,26 +504,22 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener .getOFPortStatistics(sid, portId) : statsMgr.queryStatistics( sid, OFStatisticsType.PORT, portId); - List ncStatistics = new PortStatisticsConverter( - sid, ofList).getNodeConnectorStatsList(); - return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics() - : ncStatistics.get(0); + List ncStatistics = new PortStatisticsConverter(sid, ofList) + .getNodeConnectorStatsList(); + return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics() : ncStatistics.get(0); } @Override - public List readAllNodeConnector( - String containerName, Node node, boolean cached) { + public List readAllNodeConnector(String containerName, Node node, boolean cached) { long sid = (Long) node.getID(); List ofList = (cached == true) ? statsMgr .getOFPortStatistics(sid) : statsMgr.queryStatistics(sid, OFStatisticsType.FLOW, null); - List filteredList = filterPortListPerContainer( - containerName, sid, ofList); + List filteredList = filterPortListPerContainer(containerName, sid, ofList); - return new PortStatisticsConverter(sid, filteredList) - .getNodeConnectorStatsList(); + return new PortStatisticsConverter(sid, filteredList).getNodeConnectorStatsList(); } @Override @@ -544,8 +546,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener List ofList = (cached == true) ? statsMgr.getOFTableStatistics(sid, tableId) : statsMgr.queryStatistics(sid, OFStatisticsType.TABLE, tableId); - List ntStatistics = - new TableStatisticsConverter(sid, ofList).getNodeTableStatsList(); + List ntStatistics = new TableStatisticsConverter(sid, ofList).getNodeTableStatsList(); return (ntStatistics.isEmpty()) ? new NodeTableStatistics() : ntStatistics.get(0); } @@ -564,13 +565,15 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener @Override public void descriptionStatisticsRefreshed(Long switchId, List description) { String container; + IReadFilterInternalListener listener; Node node = NodeCreator.createOFNode(switchId); NodeDescription nodeDescription = new DescStatisticsConverter(description).getHwDescription(); for (Map.Entry l : readFilterInternalListeners.entrySet()) { container = l.getKey(); + listener = l.getValue(); if (container == GlobalConstants.DEFAULT.toString() || (containerToNode.containsKey(container) && containerToNode.get(container).contains(node))) { - l.getValue().nodeDescriptionStatisticsUpdated(node, nodeDescription); + listener.nodeDescriptionStatisticsUpdated(node, nodeDescription); } } } @@ -578,25 +581,29 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener @Override public void flowStatisticsRefreshed(Long switchId, List flows) { String container; + IReadFilterInternalListener listener; Node node = NodeCreator.createOFNode(switchId); for (Map.Entry l : readFilterInternalListeners.entrySet()) { container = l.getKey(); + listener = l.getValue(); // Convert and filter the statistics per container List flowOnNodeList = new FlowStatisticsConverter(flows).getFlowOnNodeList(node); flowOnNodeList = filterFlowListPerContainer(container, node, flowOnNodeList); // notify listeners - l.getValue().nodeFlowStatisticsUpdated(node, flowOnNodeList); + listener.nodeFlowStatisticsUpdated(node, flowOnNodeList); } } @Override public void portStatisticsRefreshed(Long switchId, List ports) { String container; + IReadFilterInternalListener listener; Node node = NodeCreator.createOFNode(switchId); for (Map.Entry l : readFilterInternalListeners.entrySet()) { container = l.getKey(); + listener = l.getValue(); // Convert and filter the statistics per container List filteredPorts = filterPortListPerContainer(container, switchId, ports); @@ -604,8 +611,7 @@ public class ReadServiceFilter implements IReadServiceFilter, IContainerListener .getNodeConnectorStatsList(); // notify listeners - l.getValue().nodeConnectorStatisticsUpdated(node, ncStatsList); - + listener.nodeConnectorStatisticsUpdated(node, ncStatsList); } } -- 2.36.6