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