3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.controller.protocol_plugin.openflow.internal;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
19 import org.opendaylight.controller.protocol_plugin.openflow.IOFStatisticsManager;
20 import org.opendaylight.controller.protocol_plugin.openflow.IPluginReadServiceFilter;
21 import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
22 import org.openflow.protocol.OFMatch;
23 import org.openflow.protocol.statistics.OFPortStatisticsReply;
24 import org.openflow.protocol.statistics.OFStatistics;
25 import org.openflow.protocol.statistics.OFStatisticsType;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 import org.opendaylight.controller.sal.action.Action;
30 import org.opendaylight.controller.sal.action.ActionType;
31 import org.opendaylight.controller.sal.action.Output;
32 import org.opendaylight.controller.sal.core.ContainerFlow;
33 import org.opendaylight.controller.sal.core.IContainerListener;
34 import org.opendaylight.controller.sal.core.Node;
35 import org.opendaylight.controller.sal.core.NodeConnector;
36 import org.opendaylight.controller.sal.core.UpdateType;
37 import org.opendaylight.controller.sal.flowprogrammer.Flow;
38 import org.opendaylight.controller.sal.match.Match;
39 import org.opendaylight.controller.sal.match.MatchType;
40 import org.opendaylight.controller.sal.reader.FlowOnNode;
41 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
42 import org.opendaylight.controller.sal.reader.NodeDescription;
43 import org.opendaylight.controller.sal.utils.GlobalConstants;
44 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
45 import org.opendaylight.controller.sal.utils.NodeCreator;
48 * Read Service shim layer which is in charge of filtering the flow statistics
49 * based on container. It is a Global instance.
54 public class ReadServiceFilter implements IPluginReadServiceFilter,
56 private static final Logger logger = LoggerFactory
57 .getLogger(ReadServiceFilter.class);
58 private IController controller = null;
59 private IOFStatisticsManager statsMgr = null;
60 private Map<String, Set<NodeConnector>> containerToNc;
62 public void setController(IController core) {
63 this.controller = core;
66 public void unsetController(IController core) {
67 if (this.controller == core) {
68 this.controller = null;
73 * Function called by the dependency manager when all the required
74 * dependencies are satisfied
78 containerToNc = new HashMap<String, Set<NodeConnector>>();
82 * Function called by the dependency manager when at least one
83 * dependency become unsatisfied or when the component is shutting
84 * down because for example bundle is being stopped.
91 * Function called by dependency manager after "init ()" is called
92 * and after the services provided by the class are registered in
93 * the service registry
100 * Function called by the dependency manager before the services
101 * exported by the component are unregistered, this will be
102 * followed by a "destroy ()" calls
108 public void setService(IOFStatisticsManager service) {
109 this.statsMgr = service;
112 public void unsetService(IOFStatisticsManager service) {
113 this.statsMgr = null;
117 public FlowOnNode readFlow(String container, Node node, Flow flow,
120 if (controller == null) {
121 // Avoid to provide cached statistics if controller went down.
122 // They are not valid anymore anyway
123 logger.error("Internal plugin error");
127 long sid = (Long) node.getID();
128 OFMatch ofMatch = new FlowConverter(flow).getOFMatch();
129 List<OFStatistics> ofList = (cached == true) ? statsMgr
130 .getOFFlowStatistics(sid, ofMatch) : statsMgr.queryStatistics(
131 sid, OFStatisticsType.FLOW, ofMatch);
134 * Convert and filter the statistics per container
136 List<FlowOnNode> flowOnNodeList = new FlowStatisticsConverter(ofList)
137 .getFlowOnNodeList(node);
138 List<FlowOnNode> filteredList = filterFlowListPerContainer(container,
139 node, flowOnNodeList);
141 return (filteredList == null || filteredList.isEmpty()) ? null
142 : filteredList.get(0);
146 public List<FlowOnNode> readAllFlow(String container, Node node,
149 long sid = (Long) node.getID();
150 List<OFStatistics> ofList = (cached == true) ? statsMgr
151 .getOFFlowStatistics(sid) : statsMgr.queryStatistics(sid,
152 OFStatisticsType.FLOW, null);
155 * Convert and filter the statistics per container
157 List<FlowOnNode> flowOnNodeList = new FlowStatisticsConverter(ofList)
158 .getFlowOnNodeList(node);
159 List<FlowOnNode> filteredList = filterFlowListPerContainer(container,
160 node, flowOnNodeList);
162 return (filteredList == null) ? null : filteredList;
167 public NodeDescription readDescription(Node node, boolean cached) {
169 if (controller == null) {
170 logger.error("Internal plugin error");
174 long sid = (Long) node.getID();
175 List<OFStatistics> ofList = (cached == true) ? statsMgr
176 .getOFDescStatistics(sid) : statsMgr.queryStatistics(sid,
177 OFStatisticsType.DESC, null);
179 return new DescStatisticsConverter(ofList).getHwDescription();
183 * Filters a list of FlowOnNode elements based on the container
190 public List<FlowOnNode> filterFlowListPerContainer(String container,
191 Node nodeId, List<FlowOnNode> list) {
196 // Create new filtered list of flows
197 List<FlowOnNode> newList = new ArrayList<FlowOnNode>();
199 for (FlowOnNode target : list) {
200 // Check whether the described flow (match + actions) belongs to this container
201 if (flowBelongToContainer(container, nodeId, target.getFlow())) {
210 * Filters a list of FlowOnNode elements based on the container
217 public List<OFStatistics> filterPortListPerContainer(String container,
218 long switchId, List<OFStatistics> list) {
223 // Create new filtered list of flows
224 List<OFStatistics> newList = new ArrayList<OFStatistics>();
226 for (OFStatistics stat : list) {
227 OFPortStatisticsReply target = (OFPortStatisticsReply) stat;
228 NodeConnector nc = NodeConnectorCreator.createOFNodeConnector(
229 target.getPortNumber(), NodeCreator.createOFNode(switchId));
230 if (containerOwnsNodeConnector(container, nc)) {
239 * Returns whether the specified flow (flow match + actions)
240 * belongs to the container
245 * @return true if it belongs
247 public boolean flowBelongToContainer(String container, Node node, Flow flow) {
248 // All flows belong to the default container
249 if (container.equals(GlobalConstants.DEFAULT.toString())) {
252 return (flowPortsBelongToContainer(container, node, flow)
253 && flowVlanBelongsToContainer(container, node, flow) && flowSpecAllowsFlow(
254 container, flow.getMatch()));
258 * Returns whether the passed NodeConnector belongs to the container
260 * @param container container name
261 * @param p node connector to test
262 * @return true if belongs false otherwise
264 public boolean containerOwnsNodeConnector(String container, NodeConnector p) {
265 // All node connectors belong to the default container
266 if (container.equals(GlobalConstants.DEFAULT.toString())) {
269 Set<NodeConnector> portSet = containerToNc.get(container);
270 return (portSet == null) ? false : portSet.contains(p);
274 * Returns whether the container flowspec allows the passed flow
280 private boolean flowSpecAllowsFlow(String container, Match match) {
281 return true; // Always true for now
285 * Check whether the vlan field in the flow match is the same
286 * of the static vlan configured for the container
293 private boolean flowVlanBelongsToContainer(String container, Node node,
295 return true; // Always true for now
299 * Check whether the ports in the flow match and flow actions for
300 * the specified node belong to the container
307 private boolean flowPortsBelongToContainer(String container, Node node,
309 Match m = flow.getMatch();
310 if (m.isPresent(MatchType.IN_PORT)) {
311 NodeConnector inPort = (NodeConnector) m
312 .getField(MatchType.IN_PORT).getValue();
314 // If the incoming port is specified, check if it belongs to
315 if (!containerOwnsNodeConnector(container, inPort)) {
320 // If an outgoing port is specified, it must belong to this container
321 for (Action action : flow.getActions()) {
322 if (action.getType() == ActionType.OUTPUT) {
323 NodeConnector outPort = (NodeConnector) ((Output) action)
325 if (!containerOwnsNodeConnector(container, outPort)) {
334 public void containerFlowUpdated(String containerName,
335 ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) {
340 public void nodeConnectorUpdated(String containerName, NodeConnector p,
342 Set<NodeConnector> target = null;
346 if (!containerToNc.containsKey(containerName)) {
347 containerToNc.put(containerName, new HashSet<NodeConnector>());
349 containerToNc.get(containerName).add(p);
354 target = containerToNc.get(containerName);
355 if (target != null) {
364 public void tagUpdated(String containerName, Node n, short oldTag,
365 short newTag, UpdateType t) {
366 // Not interested in this event
370 public void containerModeUpdated(UpdateType t) {
375 public NodeConnectorStatistics readNodeConnector(String containerName,
376 NodeConnector connector, boolean cached) {
377 if (!containerOwnsNodeConnector(containerName, connector)) {
380 Node node = connector.getNode();
381 long sid = (Long) node.getID();
382 short portId = (Short) connector.getID();
383 List<OFStatistics> ofList = (cached == true) ? statsMgr
384 .getOFPortStatistics(sid, portId) : statsMgr.queryStatistics(
385 sid, OFStatisticsType.PORT, portId);
387 List<NodeConnectorStatistics> ncStatistics = new PortStatisticsConverter(
388 sid, ofList).getNodeConnectorStatsList();
389 return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics()
390 : ncStatistics.get(0);
394 public List<NodeConnectorStatistics> readAllNodeConnector(
395 String containerName, Node node, boolean cached) {
397 long sid = (Long) node.getID();
398 List<OFStatistics> ofList = (cached == true) ? statsMgr
399 .getOFPortStatistics(sid) : statsMgr.queryStatistics(sid,
400 OFStatisticsType.FLOW, null);
402 List<OFStatistics> filteredList = filterPortListPerContainer(
403 containerName, sid, ofList);
405 return new PortStatisticsConverter(sid, filteredList)
406 .getNodeConnectorStatsList();
410 public long getTransmitRate(String containerName, NodeConnector connector) {
411 if (!containerOwnsNodeConnector(containerName, connector)) {
415 long switchId = (Long) connector.getNode().getID();
416 short port = (Short) connector.getID();
418 return statsMgr.getTransmitRate(switchId, port);