Merge "Partial fix for bug 8. Fixing many generics-related warnings and some typos."
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / ReadServiceFilter.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
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
8  */
9
10 package org.opendaylight.controller.protocol_plugin.openflow.internal;
11
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
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;
28
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;
46
47 /**
48  * Read Service shim layer which is in charge of filtering the flow statistics
49  * based on container. It is a Global instance.
50  *
51  *
52  *
53  */
54 public class ReadServiceFilter implements IPluginReadServiceFilter,
55         IContainerListener {
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;
61
62     public void setController(IController core) {
63         this.controller = core;
64     }
65
66     public void unsetController(IController core) {
67         if (this.controller == core) {
68             this.controller = null;
69         }
70     }
71
72     /**
73      * Function called by the dependency manager when all the required
74      * dependencies are satisfied
75      *
76      */
77     void init() {
78         containerToNc = new HashMap<String, Set<NodeConnector>>();
79     }
80
81     /**
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.
85      *
86      */
87     void destroy() {
88     }
89
90     /**
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
94      *
95      */
96     void start() {
97     }
98
99     /**
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
103      *
104      */
105     void stop() {
106     }
107
108     public void setService(IOFStatisticsManager service) {
109         this.statsMgr = service;
110     }
111
112     public void unsetService(IOFStatisticsManager service) {
113         this.statsMgr = null;
114     }
115
116     @Override
117     public FlowOnNode readFlow(String container, Node node, Flow flow,
118             boolean cached) {
119
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");
124             return null;
125         }
126
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);
132
133         /*
134          * Convert and filter the statistics per container
135          */
136         List<FlowOnNode> flowOnNodeList = new FlowStatisticsConverter(ofList)
137                 .getFlowOnNodeList(node);
138         List<FlowOnNode> filteredList = filterFlowListPerContainer(container,
139                 node, flowOnNodeList);
140
141         return (filteredList == null || filteredList.isEmpty()) ? null
142                 : filteredList.get(0);
143     }
144
145     @Override
146     public List<FlowOnNode> readAllFlow(String container, Node node,
147             boolean cached) {
148
149         long sid = (Long) node.getID();
150         List<OFStatistics> ofList = (cached == true) ? statsMgr
151                 .getOFFlowStatistics(sid) : statsMgr.queryStatistics(sid,
152                 OFStatisticsType.FLOW, null);
153
154         /*
155          * Convert and filter the statistics per container
156          */
157         List<FlowOnNode> flowOnNodeList = new FlowStatisticsConverter(ofList)
158                 .getFlowOnNodeList(node);
159         List<FlowOnNode> filteredList = filterFlowListPerContainer(container,
160                 node, flowOnNodeList);
161
162         return (filteredList == null) ? null : filteredList;
163
164     }
165
166     @Override
167     public NodeDescription readDescription(Node node, boolean cached) {
168
169         if (controller == null) {
170             logger.error("Internal plugin error");
171             return null;
172         }
173
174         long sid = (Long) node.getID();
175         List<OFStatistics> ofList = (cached == true) ? statsMgr
176                 .getOFDescStatistics(sid) : statsMgr.queryStatistics(sid,
177                 OFStatisticsType.DESC, null);
178
179         return new DescStatisticsConverter(ofList).getHwDescription();
180     }
181
182     /**
183      * Filters a list of FlowOnNode elements based on the container
184      *
185      * @param container
186      * @param nodeId
187      * @param list
188      * @return
189      */
190     public List<FlowOnNode> filterFlowListPerContainer(String container,
191             Node nodeId, List<FlowOnNode> list) {
192         if (list == null) {
193             return null;
194         }
195
196         // Create new filtered list of flows
197         List<FlowOnNode> newList = new ArrayList<FlowOnNode>();
198
199         for (FlowOnNode target : list) {
200             // Check whether the described flow (match + actions) belongs to this container
201             if (flowBelongToContainer(container, nodeId, target.getFlow())) {
202                 newList.add(target);
203             }
204         }
205
206         return newList;
207     }
208
209     /**
210      * Filters a list of FlowOnNode elements based on the container
211      *
212      * @param container
213      * @param nodeId
214      * @param list
215      * @return
216      */
217     public List<OFStatistics> filterPortListPerContainer(String container,
218             long switchId, List<OFStatistics> list) {
219         if (list == null) {
220             return null;
221         }
222
223         // Create new filtered list of flows
224         List<OFStatistics> newList = new ArrayList<OFStatistics>();
225
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)) {
231                 newList.add(target);
232             }
233         }
234
235         return newList;
236     }
237
238     /**
239      * Returns whether the specified flow (flow match + actions)
240      * belongs to the container
241      *
242      * @param container
243      * @param node
244      * @param flow
245      * @return true if it belongs
246      */
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())) {
250             return true;
251         }
252         return (flowPortsBelongToContainer(container, node, flow)
253                 && flowVlanBelongsToContainer(container, node, flow) && flowSpecAllowsFlow(
254                 container, flow.getMatch()));
255     }
256
257     /**
258      * Returns whether the passed NodeConnector belongs to the container
259      *
260      * @param container container name
261      * @param p         node connector to test
262      * @return          true if belongs false otherwise
263      */
264     public boolean containerOwnsNodeConnector(String container, NodeConnector p) {
265         // All node connectors belong to the default container
266         if (container.equals(GlobalConstants.DEFAULT.toString())) {
267             return true;
268         }
269         Set<NodeConnector> portSet = containerToNc.get(container);
270         return (portSet == null) ? false : portSet.contains(p);
271     }
272
273     /**
274      * Returns whether the container flowspec allows the passed flow
275      *
276      * @param container
277      * @param match
278      * @return
279      */
280     private boolean flowSpecAllowsFlow(String container, Match match) {
281         return true; // Always true for now
282     }
283
284     /**
285      * Check whether the vlan field in the flow match is the same
286      * of the static vlan configured for the container
287      *
288      * @param container
289      * @param node
290      * @param flow
291      * @return
292      */
293     private boolean flowVlanBelongsToContainer(String container, Node node,
294             Flow flow) {
295         return true; // Always true for now
296     }
297
298     /**
299      * Check whether the ports in the flow match and flow actions for
300      * the specified node belong to the container
301      *
302      * @param container
303      * @param node
304      * @param flow
305      * @return
306      */
307     private boolean flowPortsBelongToContainer(String container, Node node,
308             Flow flow) {
309         Match m = flow.getMatch();
310         if (m.isPresent(MatchType.IN_PORT)) {
311             NodeConnector inPort = (NodeConnector) m
312                     .getField(MatchType.IN_PORT).getValue();
313
314             // If the incoming port is specified, check if it belongs to
315             if (!containerOwnsNodeConnector(container, inPort)) {
316                 return false;
317             }
318         }
319
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)
324                         .getPort();
325                 if (!containerOwnsNodeConnector(container, outPort)) {
326                     return false;
327                 }
328             }
329         }
330         return true;
331     }
332
333     @Override
334     public void containerFlowUpdated(String containerName,
335             ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) {
336
337     }
338
339     @Override
340     public void nodeConnectorUpdated(String containerName, NodeConnector p,
341             UpdateType type) {
342         Set<NodeConnector> target = null;
343
344         switch (type) {
345         case ADDED:
346             if (!containerToNc.containsKey(containerName)) {
347                 containerToNc.put(containerName, new HashSet<NodeConnector>());
348             }
349             containerToNc.get(containerName).add(p);
350             break;
351         case CHANGED:
352             break;
353         case REMOVED:
354             target = containerToNc.get(containerName);
355             if (target != null) {
356                 target.remove(p);
357             }
358             break;
359         default:
360         }
361     }
362
363     @Override
364     public void tagUpdated(String containerName, Node n, short oldTag,
365             short newTag, UpdateType t) {
366         // Not interested in this event
367     }
368
369     @Override
370     public void containerModeUpdated(UpdateType t) {
371         // do nothing
372     }
373
374     @Override
375     public NodeConnectorStatistics readNodeConnector(String containerName,
376             NodeConnector connector, boolean cached) {
377         if (!containerOwnsNodeConnector(containerName, connector)) {
378             return null;
379         }
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);
386
387         List<NodeConnectorStatistics> ncStatistics = new PortStatisticsConverter(
388                 sid, ofList).getNodeConnectorStatsList();
389         return (ncStatistics.isEmpty()) ? new NodeConnectorStatistics()
390                 : ncStatistics.get(0);
391     }
392
393     @Override
394     public List<NodeConnectorStatistics> readAllNodeConnector(
395             String containerName, Node node, boolean cached) {
396
397         long sid = (Long) node.getID();
398         List<OFStatistics> ofList = (cached == true) ? statsMgr
399                 .getOFPortStatistics(sid) : statsMgr.queryStatistics(sid,
400                 OFStatisticsType.FLOW, null);
401
402         List<OFStatistics> filteredList = filterPortListPerContainer(
403                 containerName, sid, ofList);
404
405         return new PortStatisticsConverter(sid, filteredList)
406                 .getNodeConnectorStatsList();
407     }
408
409     @Override
410     public long getTransmitRate(String containerName, NodeConnector connector) {
411         if (!containerOwnsNodeConnector(containerName, connector)) {
412             return 0;
413         }
414
415         long switchId = (Long) connector.getNode().getID();
416         short port = (Short) connector.getID();
417
418         return statsMgr.getTransmitRate(switchId, port);
419     }
420
421 }