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