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