X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fprotocol_plugins%2Fopenflow%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fprotocol_plugin%2Fopenflow%2Finternal%2FReadServiceFilter.java;h=7f9a13e92ac3be846342a7615e37ec658d8b9fa0;hp=1b71c3bec34f70b382af55c094e7acb7f86f0fdf;hb=1f46115777f3dfe4ed653ea2c06cd3fe637fb122;hpb=cffdfafd2b23b24025f5ba4b32f16bca501bfeb5 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 1b71c3bec3..7f9a13e92a 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 @@ -10,22 +10,20 @@ 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; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsListener; import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsManager; -import org.opendaylight.controller.protocol_plugin.openflow.IPluginReadServiceFilter; +import org.opendaylight.controller.protocol_plugin.openflow.IReadFilterInternalListener; +import org.opendaylight.controller.protocol_plugin.openflow.IReadServiceFilter; import org.opendaylight.controller.protocol_plugin.openflow.core.IController; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.statistics.OFPortStatisticsReply; -import org.openflow.protocol.statistics.OFStatistics; -import org.openflow.protocol.statistics.OFStatisticsType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.action.Output; @@ -33,6 +31,7 @@ import org.opendaylight.controller.sal.core.ContainerFlow; import org.opendaylight.controller.sal.core.IContainerListener; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; +import org.opendaylight.controller.sal.core.NodeTable; import org.opendaylight.controller.sal.core.UpdateType; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.Match; @@ -40,10 +39,19 @@ import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.reader.FlowOnNode; import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; import org.opendaylight.controller.sal.reader.NodeDescription; +import org.opendaylight.controller.sal.reader.NodeTableStatistics; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.NodeCreator; - +import org.opendaylight.controller.sal.utils.NodeTableCreator; +import org.openflow.protocol.OFMatch; +import org.openflow.protocol.statistics.OFFlowStatisticsReply; +import org.openflow.protocol.statistics.OFPortStatisticsReply; +import org.openflow.protocol.statistics.OFStatistics; +import org.openflow.protocol.statistics.OFStatisticsType; +import org.openflow.protocol.statistics.OFTableStatistics; +import org.slf4j.Logger; +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. @@ -51,13 +59,15 @@ import org.opendaylight.controller.sal.utils.NodeCreator; * * */ -public class ReadServiceFilter implements IPluginReadServiceFilter, - IContainerListener { +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 readFilterInternalListeners; public void setController(IController core) { this.controller = core; @@ -69,6 +79,39 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, } } + public void setReadFilterInternalListener(Map props, IReadFilterInternalListener s) { + if (props == null) { + logger.error("Failed setting Read Filter Listener, property map is null."); + return; + } + String containerName = (String) props.get("containerName"); + if (containerName == null) { + logger.error("Failed setting Read Filter Listener, container name not supplied."); + return; + } + if ((this.readFilterInternalListeners != null) && !this.readFilterInternalListeners.containsValue(s)) { + this.readFilterInternalListeners.put(containerName, s); + logger.trace("Added Read Filter Listener for container {}", containerName); + } + } + + public void unsetReadFilterInternalListener(Map props, IReadFilterInternalListener s) { + if (props == null) { + logger.error("Failed unsetting Read Filter Listener, property map is null."); + return; + } + String containerName = (String) props.get("containerName"); + if (containerName == null) { + logger.error("Failed unsetting Read Filter Listener, containerName not supplied"); + return; + } + if ((this.readFilterInternalListeners != null) && this.readFilterInternalListeners.get(containerName) != null + && this.readFilterInternalListeners.get(containerName).equals(s)) { + this.readFilterInternalListeners.remove(containerName); + logger.trace("Removed Read Filter Listener for container {}", containerName); + } + } + /** * Function called by the dependency manager when all the required * dependencies are satisfied @@ -76,6 +119,9 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, */ void init() { containerToNc = new HashMap>(); + containerToNt = new HashMap>(); + containerToNode = new HashMap>(); + readFilterInternalListeners = new ConcurrentHashMap(); } /** @@ -126,9 +172,20 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, long sid = (Long) node.getID(); OFMatch ofMatch = new FlowConverter(flow).getOFMatch(); - List ofList = (cached == true) ? statsMgr - .getOFFlowStatistics(sid, ofMatch) : statsMgr.queryStatistics( - sid, OFStatisticsType.FLOW, ofMatch); + List ofList; + if (cached == true){ + ofList = statsMgr.getOFFlowStatistics(sid, ofMatch, flow.getPriority()); + } else { + ofList = statsMgr.queryStatistics(sid, OFStatisticsType.FLOW, ofMatch); + for (OFStatistics ofStat : ofList) { + if (((OFFlowStatisticsReply)ofStat).getPriority() == flow.getPriority()){ + ofList = new ArrayList(1); + ofList.add(ofStat); + break; + } + } + } + /* * Convert and filter the statistics per container @@ -174,9 +231,9 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, long sid = (Long) node.getID(); List ofList = (cached == true) ? statsMgr .getOFDescStatistics(sid) : statsMgr.queryStatistics(sid, - OFStatisticsType.DESC, null); + OFStatisticsType.DESC, null); - return new DescStatisticsConverter(ofList).getHwDescription(); + return new DescStatisticsConverter(ofList).getHwDescription(); } /** @@ -207,7 +264,7 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, } /** - * Filters a list of FlowOnNode elements based on the container + * Filters a list of OFStatistics elements based on the container * * @param container * @param nodeId @@ -235,6 +292,28 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, return newList; } + + public List filterTableListPerContainer( + String container, long switchId, List list) { + if (list == null) { + return null; + } + + // Create new filtered list of node tables + List newList = new ArrayList(); + + for (OFStatistics stat : list) { + OFTableStatistics target = (OFTableStatistics) stat; + NodeTable nt = NodeTableCreator.createOFNodeTable( + target.getTableId(), NodeCreator.createOFNode(switchId)); + if (containerOwnsNodeTable(container, nt)) { + newList.add(target); + } + } + + return newList; + } + /** * Returns whether the specified flow (flow match + actions) * belongs to the container @@ -251,15 +330,15 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, } return (flowPortsBelongToContainer(container, node, flow) && flowVlanBelongsToContainer(container, node, flow) && flowSpecAllowsFlow( - container, flow.getMatch())); + container, flow.getMatch())); } /** * Returns whether the passed NodeConnector belongs to the container * - * @param container container name - * @param p node connector to test - * @return true if belongs false otherwise + * @param container container name + * @param p node connector to test + * @return true if belongs false otherwise */ public boolean containerOwnsNodeConnector(String container, NodeConnector p) { // All node connectors belong to the default container @@ -270,6 +349,22 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, return (portSet == null) ? false : portSet.contains(p); } + /** + * Returns whether the passed NodeConnector belongs to the container + * + * @param container container name + * @param table node table to test + * @return true if belongs false otherwise + */ + public boolean containerOwnsNodeTable(String container, NodeTable table) { + // All node table belong to the default container + if (container.equals(GlobalConstants.DEFAULT.toString())) { + return true; + } + Set tableSet = containerToNt.get(container); + return (tableSet == null) ? false : tableSet.contains(table); + } + /** * Returns whether the container flowspec allows the passed flow * @@ -290,8 +385,7 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, * @param flow * @return */ - private boolean flowVlanBelongsToContainer(String container, Node node, - Flow flow) { + private boolean flowVlanBelongsToContainer(String container, Node node, Flow flow) { return true; // Always true for now } @@ -320,7 +414,7 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, // If an outgoing port is specified, it must belong to this container for (Action action : flow.getActions()) { if (action.getType() == ActionType.OUTPUT) { - NodeConnector outPort = (NodeConnector) ((Output) action) + NodeConnector outPort = ((Output) action) .getPort(); if (!containerOwnsNodeConnector(container, outPort)) { return false; @@ -331,49 +425,69 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, } @Override - public void containerFlowUpdated(String containerName, - ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) { - + public void containerFlowUpdated(String containerName, ContainerFlow previousFlow, + ContainerFlow currentFlow, UpdateType t) { + // TODO } @Override public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType type) { - Set target = null; switch (type) { case ADDED: if (!containerToNc.containsKey(containerName)) { - containerToNc.put(containerName, new HashSet()); + containerToNc.put(containerName, + Collections.newSetFromMap(new ConcurrentHashMap())); } containerToNc.get(containerName).add(p); - break; - case CHANGED: + if (!containerToNode.containsKey(containerName)) { + containerToNode.put(containerName, new HashSet()); + } + containerToNode.get(containerName).add(p.getNode()); break; case REMOVED: - target = containerToNc.get(containerName); - if (target != null) { - target.remove(p); + Set ncSet = containerToNc.get(containerName); + if (ncSet != null) { + //remove this nc from container map + ncSet.remove(p); + + //check if there are still ports of this node in this container + //and if not, remove its mapping + boolean nodeInContainer = false; + Node node = p.getNode(); + for (NodeConnector nodeConnector : ncSet) { + if (nodeConnector.getNode().equals(node)){ + nodeInContainer = true; + break; + } + } + if (! nodeInContainer) { + Set nodeSet = containerToNode.get(containerName); + if (nodeSet != null) { + nodeSet.remove(node); + } + } } break; + case CHANGED: default: } } @Override - public void tagUpdated(String containerName, Node n, short oldTag, - short newTag, UpdateType t) { + public void tagUpdated(String containerName, Node n, short oldTag, short newTag, UpdateType t) { // Not interested in this event } @Override public void containerModeUpdated(UpdateType t) { - // do nothing + // Not interested in this event } @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; } @@ -382,11 +496,11 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, short portId = (Short) connector.getID(); List ofList = (cached == true) ? statsMgr .getOFPortStatistics(sid, portId) : statsMgr.queryStatistics( - sid, OFStatisticsType.PORT, portId); + sid, OFStatisticsType.PORT, portId); - List ncStatistics = new PortStatisticsConverter( - sid, ofList).getNodeConnectorStatsList(); - return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics() + List ncStatistics = new PortStatisticsConverter( + sid, ofList).getNodeConnectorStatsList(); + return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics() : ncStatistics.get(0); } @@ -397,12 +511,12 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, long sid = (Long) node.getID(); List ofList = (cached == true) ? statsMgr .getOFPortStatistics(sid) : statsMgr.queryStatistics(sid, - OFStatisticsType.FLOW, null); + OFStatisticsType.FLOW, null); - List filteredList = filterPortListPerContainer( - containerName, sid, ofList); + List filteredList = filterPortListPerContainer( + containerName, sid, ofList); - return new PortStatisticsConverter(sid, filteredList) + return new PortStatisticsConverter(sid, filteredList) .getNodeConnectorStatsList(); } @@ -418,4 +532,97 @@ public class ReadServiceFilter implements IPluginReadServiceFilter, return statsMgr.getTransmitRate(switchId, port); } + @Override + public NodeTableStatistics readNodeTable(String containerName, + NodeTable table, boolean cached) { + if (!containerOwnsNodeTable(containerName, table)) { + return null; + } + Node node = table.getNode(); + long sid = (Long) node.getID(); + Byte tableId = (Byte) table.getID(); + List ofList = (cached == true) ? statsMgr.getOFTableStatistics(sid, tableId) : + statsMgr.queryStatistics(sid, OFStatisticsType.TABLE, tableId); + + List ntStatistics = + new TableStatisticsConverter(sid, ofList).getNodeTableStatsList(); + + return (ntStatistics.isEmpty()) ? new NodeTableStatistics() : ntStatistics.get(0); + } + + @Override + public List readAllNodeTable(String containerName, Node node, boolean cached) { + long sid = (Long) node.getID(); + List ofList = (cached == true) ? + statsMgr.getOFTableStatistics(sid) : statsMgr.queryStatistics(sid, OFStatisticsType.FLOW, null); + + List filteredList = filterTableListPerContainer(containerName, sid, ofList); + + return new TableStatisticsConverter(sid, filteredList).getNodeTableStatsList(); + } + + @Override + public void descriptionStatisticsRefreshed(Long switchId, List description) { + String container; + Node node = NodeCreator.createOFNode(switchId); + NodeDescription nodeDescription = new DescStatisticsConverter(description).getHwDescription(); + for (Map.Entry l : readFilterInternalListeners.entrySet()) { + container = l.getKey(); + if (container == GlobalConstants.DEFAULT.toString() + || (containerToNode.containsKey(container) && containerToNode.get(container).contains(node))) { + l.getValue().nodeDescriptionStatisticsUpdated(node, nodeDescription); + } + } + } + + @Override + public void flowStatisticsRefreshed(Long switchId, List flows) { + String container; + Node node = NodeCreator.createOFNode(switchId); + for (Map.Entry l : readFilterInternalListeners.entrySet()) { + container = l.getKey(); + + // 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); + } + } + + @Override + public void portStatisticsRefreshed(Long switchId, List ports) { + String container; + Node node = NodeCreator.createOFNode(switchId); + for (Map.Entry l : readFilterInternalListeners.entrySet()) { + container = l.getKey(); + + // Convert and filter the statistics per container + List filteredPorts = filterPortListPerContainer(container, switchId, ports); + List ncStatsList = new PortStatisticsConverter(switchId, filteredPorts) + .getNodeConnectorStatsList(); + + // notify listeners + l.getValue().nodeConnectorStatisticsUpdated(node, ncStatsList); + + } + } + + @Override + public void tableStatisticsRefreshed(Long switchId, List tables) { + String container; + Node node = NodeCreator.createOFNode(switchId); + for (Map.Entry l : readFilterInternalListeners.entrySet()) { + container = l.getKey(); + + // Convert and filter the statistics per container + List filteredList = filterTableListPerContainer(container, switchId, tables); + List tableStatsList = new TableStatisticsConverter(switchId, filteredList) + .getNodeTableStatsList(); + + // notify listeners + l.getValue().nodeTableStatisticsUpdated(node, tableStatsList); + } + } }