2 * Copyright (c) 2013-2014 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.sal.implementation.internal;
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;
18 import java.util.concurrent.ConcurrentHashMap;
19 import java.util.concurrent.CopyOnWriteArraySet;
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;
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
58 public class ReadService implements IReadService, CommandProvider, IPluginOutReadService {
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>();
67 * Function called by the dependency manager when all the required
68 * dependencies are satisfied
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.
81 // In case of plugin disactivating make sure we clear the
83 this.pluginReader.clear();
84 this.readerListeners.clear();
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
94 registerWithOSGIConsole();
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
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);
111 public void unsetService(Map<?, ?> props, IPluginInReadService s) {
112 ProtocolService.unset(this.pluginReader, props, s, logger);
115 public void setReaderListener(IReadServiceListener service) {
116 logger.trace("Got a listener set request {}", service);
117 this.readerListeners.add(service);
120 public void unsetReaderListener(IReadServiceListener service) {
121 logger.trace("Got a listener Unset request");
122 this.readerListeners.remove(service);
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);
134 logger.warn("Plugin {} unavailable", node.getType());
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);
147 logger.warn("Plugin {} unavailable", node.getType());
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);
160 logger.warn("Plugin {} unavailable", node.getType());
161 return Collections.emptyList();
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);
173 logger.warn("Plugin {} unavailable", node.getType());
174 return Collections.emptyList();
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);
186 logger.warn("Plugin {} unavailable", node.getType());
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);
199 logger.warn("Plugin {} unavailable", node.getType());
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);
213 logger.warn("Plugin {} unavailable", node.getType());
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);
228 logger.warn("Plugin {} unavailable", node.getType());
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);
241 logger.warn("Plugin {} unavailable", node.getType());
242 return Collections.emptyList();
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);
254 logger.warn("Plugin {} unavailable", node.getType());
255 return Collections.emptyList();
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);
269 logger.warn("Plugin {} unavailable", node.getType());
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);
283 logger.warn("Plugin {} unavailable", node.getType());
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);
296 logger.warn("Plugin {} unavailable", node.getType());
297 return Collections.emptyList();
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);
310 logger.warn("Plugin {} unavailable", node.getType());
315 public void nodeFlowStatisticsUpdated(Node node, List<FlowOnNode> flowStatsList) {
316 for (IReadServiceListener l : readerListeners){
317 l.nodeFlowStatisticsUpdated(node, flowStatsList);
322 public void nodeConnectorStatisticsUpdated(Node node, List<NodeConnectorStatistics> ncStatsList) {
323 for (IReadServiceListener l : readerListeners){
324 l.nodeConnectorStatisticsUpdated(node, ncStatsList);
329 public void nodeTableStatisticsUpdated(Node node, List<NodeTableStatistics> tableStatsList) {
330 for (IReadServiceListener l : readerListeners){
331 l.nodeTableStatisticsUpdated(node, tableStatsList);
336 public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
337 for (IReadServiceListener l : readerListeners){
338 l.descriptionStatisticsUpdated(node, nodeDescription);
342 // ---------------- OSGI TEST CODE ------------------------------//
344 private void registerWithOSGIConsole() {
345 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
347 bundleContext.registerService(CommandProvider.class.getName(), this,
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");
364 return help.toString();
367 public void _readflows(CommandInterpreter ci) {
368 String nodeId = ci.nextArgument();
369 String cacheReq = ci.nextArgument();
371 if (nodeId == null) {
372 ci.print("Node id not specified");
375 cached = (cacheReq == null) ? true : cacheReq.equals("true");
378 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
379 } catch (NumberFormatException e) {
381 } catch (ConstructionException e) {
384 List<FlowOnNode> list = (cached) ? this.readAllFlows(node) : this
385 .nonCachedReadAllFlows(node);
387 ci.println(list.toString());
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();
398 if (nodeId == null) {
399 ci.print("Node id not specified");
402 cached = (cacheReq == null) ? true : cacheReq.equals("true");
405 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
406 } catch (NumberFormatException e) {
408 } catch (ConstructionException e) {
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());
421 public void _readports(CommandInterpreter ci) {
422 String nodeId = ci.nextArgument();
423 String cacheReq = ci.nextArgument();
425 if (nodeId == null) {
426 ci.print("Node id not specified");
429 cached = (cacheReq == null) ? true : cacheReq.equals("true");
432 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
433 } catch (NumberFormatException e) {
435 } catch (ConstructionException e) {
438 List<NodeConnectorStatistics> list = (cached) ? this
439 .readNodeConnectors(node) : this
440 .nonCachedReadNodeConnectors(node);
442 ci.println(list.toString());
448 public void _readport(CommandInterpreter ci) {
449 String nodeId = ci.nextArgument();
450 String portId = ci.nextArgument();
451 String cacheReq = ci.nextArgument();
453 if (nodeId == null) {
454 ci.print("Node id not specified");
457 if (portId == null) {
458 ci.print("Port id not specified");
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);
470 ci.println(stats.toString());
476 public void _readtable(CommandInterpreter ci) {
477 String nodeId = ci.nextArgument();
478 String tableId = ci.nextArgument();
479 String cacheReq = ci.nextArgument();
481 if (nodeId == null) {
482 ci.print("Node id not specified");
485 if (tableId == null) {
486 ci.print("Table id not specified");
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);
498 ci.println(stats.toString());
504 public void _readdescr(CommandInterpreter ci) {
505 String nodeId = ci.nextArgument();
506 String cacheReq = ci.nextArgument();
508 if (nodeId == null) {
509 ci.print("Node id not specified");
512 cached = (cacheReq == null) ? true : cacheReq.equals("true");
516 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
517 } catch (NumberFormatException e) {
519 } catch (ConstructionException e) {
522 NodeDescription desc = (cached) ? this.readDescription(node) : this
523 .nonCachedReadDescription(node);
525 ci.println(desc.toString());
531 private Flow getSampleFlow(Node node) throws UnknownHostException {
532 NodeConnector port = NodeConnectorCreator.createOFNodeConnector(
534 NodeConnector oport = NodeConnectorCreator.createOFNodeConnector(
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;
548 byte proto = IPProtocols.TCP.byteValue();
549 short src = (short) 55000;
553 * Create a SAL Flow aFlow
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);
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);