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