Move adsal into its own subdirectory.
[controller.git] / opendaylight / adsal / sal / implementation / src / main / java / org / opendaylight / controller / sal / implementation / internal / ReadService.java
1 /*
2  * Copyright (c) 2013-2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.sal.implementation.internal;
10
11 import java.net.InetAddress;
12 import java.net.UnknownHostException;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.CopyOnWriteArraySet;
20
21 import org.eclipse.osgi.framework.console.CommandInterpreter;
22 import org.eclipse.osgi.framework.console.CommandProvider;
23 import org.opendaylight.controller.sal.action.Action;
24 import org.opendaylight.controller.sal.action.Controller;
25 import org.opendaylight.controller.sal.action.Flood;
26 import org.opendaylight.controller.sal.action.Output;
27 import org.opendaylight.controller.sal.action.PopVlan;
28 import org.opendaylight.controller.sal.core.ConstructionException;
29 import org.opendaylight.controller.sal.core.Node;
30 import org.opendaylight.controller.sal.core.Node.NodeIDType;
31 import org.opendaylight.controller.sal.core.NodeConnector;
32 import org.opendaylight.controller.sal.core.NodeTable;
33 import org.opendaylight.controller.sal.flowprogrammer.Flow;
34 import org.opendaylight.controller.sal.match.Match;
35 import org.opendaylight.controller.sal.match.MatchType;
36 import org.opendaylight.controller.sal.reader.FlowOnNode;
37 import org.opendaylight.controller.sal.reader.IPluginInReadService;
38 import org.opendaylight.controller.sal.reader.IPluginOutReadService;
39 import org.opendaylight.controller.sal.reader.IReadService;
40 import org.opendaylight.controller.sal.reader.IReadServiceListener;
41 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
42 import org.opendaylight.controller.sal.reader.NodeDescription;
43 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
44 import org.opendaylight.controller.sal.utils.EtherTypes;
45 import org.opendaylight.controller.sal.utils.IPProtocols;
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.osgi.framework.BundleContext;
50 import org.osgi.framework.FrameworkUtil;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 /**
55  * The SAL Read Service. Dispatches read requests to the proper SDN protocol
56  * plugin, and notifies any listeners on updates from any plugin readers
57  */
58 public class ReadService implements IReadService, CommandProvider, IPluginOutReadService {
59
60     protected static final Logger logger = LoggerFactory.getLogger(ReadService.class);
61     private ConcurrentHashMap<String, ProtocolService<IPluginInReadService>> pluginReader =
62         new ConcurrentHashMap<String, ProtocolService<IPluginInReadService>>();
63     private Set<IReadServiceListener> readerListeners =
64         new CopyOnWriteArraySet<IReadServiceListener>();
65
66     /**
67      * Function called by the dependency manager when all the required
68      * dependencies are satisfied
69      *
70      */
71     void init() {
72     }
73
74     /**
75      * Function called by the dependency manager when at least one
76      * dependency become unsatisfied or when the component is shutting
77      * down because for example bundle is being stopped.
78      *
79      */
80     void destroy() {
81         // In case of plugin disactivating make sure we clear the
82         // dependencies
83         this.pluginReader.clear();
84         this.readerListeners.clear();
85     }
86
87     /**
88      * Function called by dependency manager after "init ()" is called
89      * and after the services provided by the class are registered in
90      * the service registry
91      *
92      */
93     void start() {
94         registerWithOSGIConsole();
95     }
96
97     /**
98      * Function called by the dependency manager before the services
99      * exported by the component are unregistered, this will be
100      * followed by a "destroy ()" calls
101      *
102      */
103     void stop() {
104     }
105
106     // Set the reference to the plugin flow Reader service
107     public void setService(Map<?, ?> props, IPluginInReadService s) {
108         ProtocolService.set(this.pluginReader, props, s, logger);
109     }
110
111     public void unsetService(Map<?, ?> props, IPluginInReadService s) {
112         ProtocolService.unset(this.pluginReader, props, s, logger);
113     }
114
115     public void setReaderListener(IReadServiceListener service) {
116         logger.trace("Got a listener set request {}", service);
117         this.readerListeners.add(service);
118     }
119
120     public void unsetReaderListener(IReadServiceListener service) {
121         logger.trace("Got a listener Unset request");
122         this.readerListeners.remove(service);
123     }
124
125     @Override
126     public FlowOnNode readFlow(Node node, Flow flow) {
127         if (pluginReader != null) {
128             ProtocolService<IPluginInReadService> service =
129                 this.pluginReader.get(node.getType());
130             if (service != null) {
131                 return service.getService().readFlow(node, flow, true);
132             }
133         }
134         logger.warn("Plugin {} unavailable", node.getType());
135         return null;
136     }
137
138     @Override
139     public FlowOnNode nonCachedReadFlow(Node node, Flow flow) {
140         if (pluginReader != null) {
141             ProtocolService<IPluginInReadService> service =
142                 this.pluginReader.get(node.getType());
143             if (service != null) {
144                 return service.getService().readFlow(node, flow, false);
145             }
146         }
147         logger.warn("Plugin {} unavailable", node.getType());
148         return null;
149     }
150
151     @Override
152     public List<FlowOnNode> readAllFlows(Node node) {
153         if (pluginReader != null) {
154             ProtocolService<IPluginInReadService> service =
155                 this.pluginReader.get(node.getType());
156             if (service != null) {
157                 return service.getService().readAllFlow(node, true);
158             }
159         }
160         logger.warn("Plugin {} unavailable", node.getType());
161         return Collections.emptyList();
162     }
163
164     @Override
165     public List<FlowOnNode> nonCachedReadAllFlows(Node node) {
166         if (pluginReader != null) {
167             ProtocolService<IPluginInReadService> service =
168                 this.pluginReader.get(node.getType());
169             if (service != null) {
170                 return service.getService().readAllFlow(node, false);
171             }
172         }
173         logger.warn("Plugin {} unavailable", node.getType());
174         return Collections.emptyList();
175     }
176
177     @Override
178     public NodeDescription readDescription(Node node) {
179         if (pluginReader != null) {
180             ProtocolService<IPluginInReadService> service =
181                 this.pluginReader.get(node.getType());
182             if (service != null) {
183                 return service.getService().readDescription(node, true);
184             }
185         }
186         logger.warn("Plugin {} unavailable", node.getType());
187         return null;
188     }
189
190     @Override
191     public NodeDescription nonCachedReadDescription(Node node) {
192         if (pluginReader != null) {
193             ProtocolService<IPluginInReadService> service =
194                 this.pluginReader.get(node.getType());
195             if (service != null) {
196                 return service.getService().readDescription(node, false);
197             }
198         }
199         logger.warn("Plugin {} unavailable", node.getType());
200         return null;
201     }
202
203     @Override
204     public NodeConnectorStatistics readNodeConnector(NodeConnector connector) {
205         Node node = connector.getNode();
206         if (pluginReader != null && node != null) {
207             ProtocolService<IPluginInReadService> service =
208                 this.pluginReader.get(node.getType());
209             if (service != null) {
210                 return service.getService().readNodeConnector(connector, true);
211             }
212         }
213         logger.warn("Plugin {} unavailable", node.getType());
214         return null;
215     }
216
217     @Override
218     public NodeConnectorStatistics nonCachedReadNodeConnector(
219             NodeConnector connector) {
220         Node node = connector.getNode();
221         if (pluginReader != null && node != null) {
222             ProtocolService<IPluginInReadService> service =
223                 this.pluginReader.get(node.getType());
224             if (service != null) {
225                 return service.getService().readNodeConnector(connector, false);
226             }
227         }
228         logger.warn("Plugin {} unavailable", node.getType());
229         return null;
230     }
231
232     @Override
233     public List<NodeConnectorStatistics> readNodeConnectors(Node node) {
234         if (pluginReader != null) {
235             ProtocolService<IPluginInReadService> service =
236                 this.pluginReader.get(node.getType());
237             if (service != null) {
238                 return service.getService().readAllNodeConnector(node, true);
239             }
240         }
241         logger.warn("Plugin {} unavailable", node.getType());
242         return Collections.emptyList();
243     }
244
245     @Override
246     public List<NodeTableStatistics> readNodeTable(Node node) {
247         if (pluginReader != null) {
248             ProtocolService<IPluginInReadService> service =
249                 this.pluginReader.get(node.getType());
250             if (service != null) {
251                 return service.getService().readAllNodeTable(node, true);
252             }
253         }
254         logger.warn("Plugin {} unavailable", node.getType());
255         return Collections.emptyList();
256     }
257
258
259     @Override
260     public NodeTableStatistics nonCachedReadNodeTable(NodeTable table) {
261         Node node = table.getNode();
262         if (pluginReader != null && node != null) {
263             ProtocolService<IPluginInReadService> service =
264                 this.pluginReader.get(node.getType());
265             if (service != null) {
266                 return service.getService().readNodeTable(table, false);
267             }
268         }
269         logger.warn("Plugin {} unavailable", node.getType());
270         return null;
271     }
272
273     @Override
274     public NodeTableStatistics readNodeTable(NodeTable table) {
275         Node node = table.getNode();
276         if (pluginReader != null && node != null) {
277             ProtocolService<IPluginInReadService> service =
278                 this.pluginReader.get(node.getType());
279             if (service != null) {
280                 return service.getService().readNodeTable(table, true);
281             }
282         }
283         logger.warn("Plugin {} unavailable", node.getType());
284         return null;
285     }
286
287     @Override
288     public List<NodeConnectorStatistics> nonCachedReadNodeConnectors(Node node) {
289         if (pluginReader != null) {
290             ProtocolService<IPluginInReadService> service =
291                 this.pluginReader.get(node.getType());
292             if (service != null) {
293                 return service.getService().readAllNodeConnector(node, false);
294             }
295         }
296         logger.warn("Plugin {} unavailable", node.getType());
297         return Collections.emptyList();
298     }
299
300     @Override
301     public long getTransmitRate(NodeConnector connector) {
302         Node node = connector.getNode();
303         if (pluginReader != null && node != null) {
304             ProtocolService<IPluginInReadService> service =
305                 this.pluginReader.get(node.getType());
306             if (service != null) {
307                 return service.getService().getTransmitRate(connector);
308             }
309         }
310         logger.warn("Plugin {} unavailable", node.getType());
311         return 0;
312     }
313
314     @Override
315     public void nodeFlowStatisticsUpdated(Node node, List<FlowOnNode> flowStatsList) {
316         for (IReadServiceListener l : readerListeners){
317             l.nodeFlowStatisticsUpdated(node, flowStatsList);
318         }
319     }
320
321     @Override
322     public void nodeConnectorStatisticsUpdated(Node node, List<NodeConnectorStatistics> ncStatsList) {
323         for (IReadServiceListener l : readerListeners){
324             l.nodeConnectorStatisticsUpdated(node, ncStatsList);
325         }
326     }
327
328     @Override
329     public void nodeTableStatisticsUpdated(Node node, List<NodeTableStatistics> tableStatsList) {
330         for (IReadServiceListener l : readerListeners){
331             l.nodeTableStatisticsUpdated(node, tableStatsList);
332         }
333     }
334
335     @Override
336     public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
337         for (IReadServiceListener l : readerListeners){
338             l.descriptionStatisticsUpdated(node, nodeDescription);
339         }
340     }
341
342     // ---------------- OSGI TEST CODE ------------------------------//
343
344     private void registerWithOSGIConsole() {
345         BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
346                 .getBundleContext();
347         bundleContext.registerService(CommandProvider.class.getName(), this,
348                 null);
349     }
350
351     @Override
352     public String getHelp() {
353         StringBuffer help = new StringBuffer();
354         help.append("---SAL Reader testing commands---\n");
355         help.append("\t readflows <sid> <cached> - Read all the (cached) flows from the openflow switch <sid>\n");
356         help.append("\t readflow  <sid> <cached> - Read the (cached) sample flow from the openflow switch <sid>\n");
357         help.append("\t readdescr <sid> <cached> - Read the (cached) description from openflow switch <sid>\n");
358         help.append("\t\t cached = (true|false). If false or not specified, the plugin cached info\n");
359         help.append("\t\t is returned. If true, the info is directly retrieved from the switch\n");
360         help.append("\t readport <sid> <port>    - Read port statistics for the specified port\n");
361         help.append("\t readports <sid>          - Read port statistics for all ports of specified switch\n");
362         help.append("\t readtable <sid> <tableid>- Read specified table statistics\n");
363
364         return help.toString();
365     }
366
367     public void _readflows(CommandInterpreter ci) {
368         String nodeId = ci.nextArgument();
369         String cacheReq = ci.nextArgument();
370         boolean cached;
371         if (nodeId == null) {
372             ci.print("Node id not specified");
373             return;
374         }
375         cached = (cacheReq == null) ? true : cacheReq.equals("true");
376         Node node = null;
377         try {
378             node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
379         } catch (NumberFormatException e) {
380             logger.error("",e);
381         } catch (ConstructionException e) {
382             logger.error("",e);
383         }
384         List<FlowOnNode> list = (cached) ? this.readAllFlows(node) : this
385                 .nonCachedReadAllFlows(node);
386         if (list != null) {
387             ci.println(list.toString());
388         } else {
389             ci.println("null");
390         }
391     }
392
393     // Requests the hw view for the specific sample flow
394     public void _readflow(CommandInterpreter ci) throws UnknownHostException {
395         String nodeId = ci.nextArgument();
396         String cacheReq = ci.nextArgument();
397         boolean cached;
398         if (nodeId == null) {
399             ci.print("Node id not specified");
400             return;
401         }
402         cached = (cacheReq == null) ? true : cacheReq.equals("true");
403         Node node = null;
404         try {
405             node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
406         } catch (NumberFormatException e) {
407             logger.error("",e);
408         } catch (ConstructionException e) {
409             logger.error("",e);
410         }
411         Flow flow = getSampleFlow(node);
412         FlowOnNode flowOnNode = (cached) ? this.readFlow(node, flow) : this
413                 .nonCachedReadFlow(node, flow);
414         if (flowOnNode != null) {
415             ci.println(flowOnNode.toString());
416         } else {
417             ci.println("null");
418         }
419     }
420
421     public void _readports(CommandInterpreter ci) {
422         String nodeId = ci.nextArgument();
423         String cacheReq = ci.nextArgument();
424         boolean cached;
425         if (nodeId == null) {
426             ci.print("Node id not specified");
427             return;
428         }
429         cached = (cacheReq == null) ? true : cacheReq.equals("true");
430         Node node = null;
431         try {
432             node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
433         } catch (NumberFormatException e) {
434             logger.error("",e);
435         } catch (ConstructionException e) {
436             logger.error("",e);
437         }
438         List<NodeConnectorStatistics> list = (cached) ? this
439                 .readNodeConnectors(node) : this
440                 .nonCachedReadNodeConnectors(node);
441                 if (list != null) {
442                     ci.println(list.toString());
443                 } else {
444                     ci.println("null");
445                 }
446     }
447
448     public void _readport(CommandInterpreter ci) {
449         String nodeId = ci.nextArgument();
450         String portId = ci.nextArgument();
451         String cacheReq = ci.nextArgument();
452         boolean cached;
453         if (nodeId == null) {
454             ci.print("Node id not specified");
455             return;
456         }
457         if (portId == null) {
458             ci.print("Port id not specified");
459             return;
460         }
461         cached = (cacheReq == null) ? true : cacheReq.equals("true");
462         NodeConnector nodeConnector = null;
463         Node node = NodeCreator.createOFNode(Long.parseLong(nodeId));
464         nodeConnector = NodeConnectorCreator.createNodeConnector(Short
465                 .valueOf(portId), node);
466         NodeConnectorStatistics stats = (cached) ? this
467                 .readNodeConnector(nodeConnector) : this
468                 .nonCachedReadNodeConnector(nodeConnector);
469                 if (stats != null) {
470                     ci.println(stats.toString());
471                 } else {
472                     ci.println("null");
473                 }
474     }
475
476     public void _readtable(CommandInterpreter ci) {
477         String nodeId = ci.nextArgument();
478         String tableId = ci.nextArgument();
479         String cacheReq = ci.nextArgument();
480         boolean cached;
481         if (nodeId == null) {
482             ci.print("Node id not specified");
483             return;
484         }
485         if (tableId == null) {
486             ci.print("Table id not specified");
487             return;
488         }
489         cached = (cacheReq == null) ? true : cacheReq.equals("true");
490         NodeTable nodeTable = null;
491         Node node = NodeCreator.createOFNode(Long.parseLong(nodeId));
492         nodeTable = NodeTableCreator.createNodeTable(Byte
493                 .valueOf(tableId), node);
494         NodeTableStatistics stats = (cached) ? this
495                 .readNodeTable(nodeTable) : this
496                 .nonCachedReadNodeTable(nodeTable);
497                 if (stats != null) {
498                     ci.println(stats.toString());
499                 } else {
500                     ci.println("null");
501                 }
502     }
503
504     public void _readdescr(CommandInterpreter ci) {
505         String nodeId = ci.nextArgument();
506         String cacheReq = ci.nextArgument();
507         boolean cached;
508         if (nodeId == null) {
509             ci.print("Node id not specified");
510             return;
511         }
512         cached = (cacheReq == null) ? true : cacheReq.equals("true");
513
514         Node node = null;
515         try {
516             node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
517         } catch (NumberFormatException e) {
518             logger.error("",e);
519         } catch (ConstructionException e) {
520             logger.error("",e);
521         }
522         NodeDescription desc = (cached) ? this.readDescription(node) : this
523                 .nonCachedReadDescription(node);
524         if (desc != null) {
525             ci.println(desc.toString());
526         } else {
527             ci.println("null");
528         }
529     }
530
531     private Flow getSampleFlow(Node node) throws UnknownHostException {
532         NodeConnector port = NodeConnectorCreator.createOFNodeConnector(
533                 (short) 24, node);
534         NodeConnector oport = NodeConnectorCreator.createOFNodeConnector(
535                 (short) 30, node);
536         byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
537                 (byte) 0x9a, (byte) 0xbc };
538         byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d,
539                 (byte) 0x5e, (byte) 0x6f };
540         InetAddress srcIP = InetAddress.getByName("172.28.30.50");
541         InetAddress dstIP = InetAddress.getByName("171.71.9.52");
542         InetAddress ipMask = InetAddress.getByName("255.255.255.0");
543         InetAddress ipMask2 = InetAddress.getByName("255.0.0.0");
544         short ethertype = EtherTypes.IPv4.shortValue();
545         short vlan = (short) 27;
546         byte vlanPr = 3;
547         Byte tos = 4;
548         byte proto = IPProtocols.TCP.byteValue();
549         short src = (short) 55000;
550         short dst = 80;
551
552         /*
553          * Create a SAL Flow aFlow
554          */
555         Match match = new Match();
556         match.setField(MatchType.IN_PORT, port);
557         match.setField(MatchType.DL_SRC, srcMac);
558         match.setField(MatchType.DL_DST, dstMac);
559         match.setField(MatchType.DL_TYPE, ethertype);
560         match.setField(MatchType.DL_VLAN, vlan);
561         match.setField(MatchType.DL_VLAN_PR, vlanPr);
562         match.setField(MatchType.NW_SRC, srcIP, ipMask);
563         match.setField(MatchType.NW_DST, dstIP, ipMask2);
564         match.setField(MatchType.NW_TOS, tos);
565         match.setField(MatchType.NW_PROTO, proto);
566         match.setField(MatchType.TP_SRC, src);
567         match.setField(MatchType.TP_DST, dst);
568
569         List<Action> actions = new ArrayList<Action>();
570         actions.add(new Output(oport));
571         actions.add(new PopVlan());
572         actions.add(new Flood());
573         actions.add(new Controller());
574         return new Flow(match, actions);
575     }
576 }