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.NodeTable;
37 import org.opendaylight.controller.sal.core.UpdateType;
38 import org.opendaylight.controller.sal.flowprogrammer.Flow;
39 import org.opendaylight.controller.sal.match.Match;
40 import org.opendaylight.controller.sal.match.MatchType;
41 import org.opendaylight.controller.sal.reader.FlowOnNode;
42 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
43 import org.opendaylight.controller.sal.reader.NodeDescription;
44 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
45 import org.opendaylight.controller.sal.utils.GlobalConstants;
46 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
47 import org.opendaylight.controller.sal.utils.NodeCreator;
48 import org.opendaylight.controller.sal.utils.NodeTableCreator;
49 import org.openflow.protocol.statistics.OFTableStatistics;
51 * Read Service shim layer which is in charge of filtering the flow statistics
52 * based on container. It is a Global instance.
57 public class ReadServiceFilter implements IPluginReadServiceFilter,
59 private static final Logger logger = LoggerFactory
60 .getLogger(ReadServiceFilter.class);
61 private IController controller = null;
62 private IOFStatisticsManager statsMgr = null;
63 private Map<String, Set<NodeConnector>> containerToNc;
64 private Map<String, Set<NodeTable>> containerToNt;
66 public void setController(IController core) {
67 this.controller = core;
70 public void unsetController(IController core) {
71 if (this.controller == core) {
72 this.controller = null;
77 * Function called by the dependency manager when all the required
78 * dependencies are satisfied
82 containerToNc = new HashMap<String, Set<NodeConnector>>();
83 containerToNt = new HashMap<String, Set<NodeTable>>();
87 * Function called by the dependency manager when at least one
88 * dependency become unsatisfied or when the component is shutting
89 * down because for example bundle is being stopped.
96 * Function called by dependency manager after "init ()" is called
97 * and after the services provided by the class are registered in
98 * the service registry
105 * Function called by the dependency manager before the services
106 * exported by the component are unregistered, this will be
107 * followed by a "destroy ()" calls
113 public void setService(IOFStatisticsManager service) {
114 this.statsMgr = service;
117 public void unsetService(IOFStatisticsManager service) {
118 this.statsMgr = null;
122 public FlowOnNode readFlow(String container, Node node, Flow flow,
125 if (controller == null) {
126 // Avoid to provide cached statistics if controller went down.
127 // They are not valid anymore anyway
128 logger.error("Internal plugin error");
132 long sid = (Long) node.getID();
133 OFMatch ofMatch = new FlowConverter(flow).getOFMatch();
134 List<OFStatistics> ofList = (cached == true) ? statsMgr
135 .getOFFlowStatistics(sid, ofMatch) : statsMgr.queryStatistics(
136 sid, OFStatisticsType.FLOW, ofMatch);
139 * Convert and filter the statistics per container
141 List<FlowOnNode> flowOnNodeList = new FlowStatisticsConverter(ofList)
142 .getFlowOnNodeList(node);
143 List<FlowOnNode> filteredList = filterFlowListPerContainer(container,
144 node, flowOnNodeList);
146 return (filteredList == null || filteredList.isEmpty()) ? null
147 : filteredList.get(0);
151 public List<FlowOnNode> readAllFlow(String container, Node node,
154 long sid = (Long) node.getID();
155 List<OFStatistics> ofList = (cached == true) ? statsMgr
156 .getOFFlowStatistics(sid) : statsMgr.queryStatistics(sid,
157 OFStatisticsType.FLOW, null);
160 * Convert and filter the statistics per container
162 List<FlowOnNode> flowOnNodeList = new FlowStatisticsConverter(ofList)
163 .getFlowOnNodeList(node);
164 List<FlowOnNode> filteredList = filterFlowListPerContainer(container,
165 node, flowOnNodeList);
167 return (filteredList == null) ? null : filteredList;
172 public NodeDescription readDescription(Node node, boolean cached) {
174 if (controller == null) {
175 logger.error("Internal plugin error");
179 long sid = (Long) node.getID();
180 List<OFStatistics> ofList = (cached == true) ? statsMgr
181 .getOFDescStatistics(sid) : statsMgr.queryStatistics(sid,
182 OFStatisticsType.DESC, null);
184 return new DescStatisticsConverter(ofList).getHwDescription();
188 * Filters a list of FlowOnNode elements based on the container
195 public List<FlowOnNode> filterFlowListPerContainer(String container,
196 Node nodeId, List<FlowOnNode> list) {
201 // Create new filtered list of flows
202 List<FlowOnNode> newList = new ArrayList<FlowOnNode>();
204 for (FlowOnNode target : list) {
205 // Check whether the described flow (match + actions) belongs to this container
206 if (flowBelongToContainer(container, nodeId, target.getFlow())) {
215 * Filters a list of FlowOnNode elements based on the container
222 public List<OFStatistics> filterPortListPerContainer(String container,
223 long switchId, List<OFStatistics> list) {
228 // Create new filtered list of flows
229 List<OFStatistics> newList = new ArrayList<OFStatistics>();
231 for (OFStatistics stat : list) {
232 OFPortStatisticsReply target = (OFPortStatisticsReply) stat;
233 NodeConnector nc = NodeConnectorCreator.createOFNodeConnector(
234 target.getPortNumber(), NodeCreator.createOFNode(switchId));
235 if (containerOwnsNodeConnector(container, nc)) {
244 public List<OFStatistics> filterTableListPerContainer(
245 String container, long switchId, List<OFStatistics> list) {
250 // Create new filtered list of node tables
251 List<OFStatistics> newList = new ArrayList<OFStatistics>();
253 for (OFStatistics stat : list) {
254 OFTableStatistics target = (OFTableStatistics) stat;
255 NodeTable nt = NodeTableCreator.createOFNodeTable(
256 target.getTableId(), NodeCreator.createOFNode(switchId));
257 if (containerOwnsNodeTable(container, nt)) {
266 * Returns whether the specified flow (flow match + actions)
267 * belongs to the container
272 * @return true if it belongs
274 public boolean flowBelongToContainer(String container, Node node, Flow flow) {
275 // All flows belong to the default container
276 if (container.equals(GlobalConstants.DEFAULT.toString())) {
279 return (flowPortsBelongToContainer(container, node, flow)
280 && flowVlanBelongsToContainer(container, node, flow) && flowSpecAllowsFlow(
281 container, flow.getMatch()));
285 * Returns whether the passed NodeConnector belongs to the container
287 * @param container container name
288 * @param p node connector to test
289 * @return true if belongs false otherwise
291 public boolean containerOwnsNodeConnector(String container, NodeConnector p) {
292 // All node connectors belong to the default container
293 if (container.equals(GlobalConstants.DEFAULT.toString())) {
296 Set<NodeConnector> portSet = containerToNc.get(container);
297 return (portSet == null) ? false : portSet.contains(p);
301 * Returns whether the passed NodeConnector belongs to the container
303 * @param container container name
304 * @param table node table to test
305 * @return true if belongs false otherwise
307 public boolean containerOwnsNodeTable(String container, NodeTable table) {
308 // All node table belong to the default container
309 if (container.equals(GlobalConstants.DEFAULT.toString())) {
312 Set<NodeTable> tableSet = containerToNt.get(container);
313 return (tableSet == null) ? false : tableSet.contains(table);
317 * Returns whether the container flowspec allows the passed flow
323 private boolean flowSpecAllowsFlow(String container, Match match) {
324 return true; // Always true for now
328 * Check whether the vlan field in the flow match is the same
329 * of the static vlan configured for the container
336 private boolean flowVlanBelongsToContainer(String container, Node node,
338 return true; // Always true for now
342 * Check whether the ports in the flow match and flow actions for
343 * the specified node belong to the container
350 private boolean flowPortsBelongToContainer(String container, Node node,
352 Match m = flow.getMatch();
353 if (m.isPresent(MatchType.IN_PORT)) {
354 NodeConnector inPort = (NodeConnector) m
355 .getField(MatchType.IN_PORT).getValue();
357 // If the incoming port is specified, check if it belongs to
358 if (!containerOwnsNodeConnector(container, inPort)) {
363 // If an outgoing port is specified, it must belong to this container
364 for (Action action : flow.getActions()) {
365 if (action.getType() == ActionType.OUTPUT) {
366 NodeConnector outPort = (NodeConnector) ((Output) action)
368 if (!containerOwnsNodeConnector(container, outPort)) {
377 public void containerFlowUpdated(String containerName,
378 ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) {
383 public void nodeConnectorUpdated(String containerName, NodeConnector p,
385 Set<NodeConnector> target = null;
389 if (!containerToNc.containsKey(containerName)) {
390 containerToNc.put(containerName, new HashSet<NodeConnector>());
392 containerToNc.get(containerName).add(p);
397 target = containerToNc.get(containerName);
398 if (target != null) {
407 public void tagUpdated(String containerName, Node n, short oldTag,
408 short newTag, UpdateType t) {
409 // Not interested in this event
413 public void containerModeUpdated(UpdateType t) {
418 public NodeConnectorStatistics readNodeConnector(String containerName,
419 NodeConnector connector, boolean cached) {
420 if (!containerOwnsNodeConnector(containerName, connector)) {
423 Node node = connector.getNode();
424 long sid = (Long) node.getID();
425 short portId = (Short) connector.getID();
426 List<OFStatistics> ofList = (cached == true) ? statsMgr
427 .getOFPortStatistics(sid, portId) : statsMgr.queryStatistics(
428 sid, OFStatisticsType.PORT, portId);
430 List<NodeConnectorStatistics> ncStatistics = new PortStatisticsConverter(
431 sid, ofList).getNodeConnectorStatsList();
432 return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics()
433 : ncStatistics.get(0);
437 public List<NodeConnectorStatistics> readAllNodeConnector(
438 String containerName, Node node, boolean cached) {
440 long sid = (Long) node.getID();
441 List<OFStatistics> ofList = (cached == true) ? statsMgr
442 .getOFPortStatistics(sid) : statsMgr.queryStatistics(sid,
443 OFStatisticsType.FLOW, null);
445 List<OFStatistics> filteredList = filterPortListPerContainer(
446 containerName, sid, ofList);
448 return new PortStatisticsConverter(sid, filteredList)
449 .getNodeConnectorStatsList();
453 public long getTransmitRate(String containerName, NodeConnector connector) {
454 if (!containerOwnsNodeConnector(containerName, connector)) {
458 long switchId = (Long) connector.getNode().getID();
459 short port = (Short) connector.getID();
461 return statsMgr.getTransmitRate(switchId, port);
465 public NodeTableStatistics readNodeTable(String containerName,
466 NodeTable table, boolean cached) {
467 if (!containerOwnsNodeTable(containerName, table)) {
470 Node node = table.getNode();
471 long sid = (Long) node.getID();
472 Byte tableId = (Byte) table.getID();
473 List<OFStatistics> ofList = (cached == true) ? statsMgr
474 .getOFTableStatistics(sid, tableId) : statsMgr.queryStatistics(
475 sid, OFStatisticsType.TABLE, tableId);
477 List<NodeTableStatistics> ntStatistics = new TableStatisticsConverter(
478 sid, ofList).getNodeTableStatsList();
480 return (ntStatistics.isEmpty()) ? new NodeTableStatistics()
481 : ntStatistics.get(0);
485 public List<NodeTableStatistics> readAllNodeTable(String containerName,
486 Node node, boolean cached) {
487 long sid = (Long) node.getID();
488 List<OFStatistics> ofList = (cached == true) ? statsMgr
489 .getOFTableStatistics(sid) : statsMgr.queryStatistics(sid,
490 OFStatisticsType.FLOW, null);
492 List<OFStatistics> filteredList = filterTableListPerContainer(
493 containerName, sid, ofList);
495 return new TableStatisticsConverter(sid, filteredList)
496 .getNodeTableStatsList();