3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
10 package org.opendaylight.controller.sal.implementation.internal;
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;
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;
51 * The SAL Read Service. It dispatches the read request to
52 * the proper SDN protocol plugin
57 public class ReadService implements IReadService, CommandProvider {
59 protected static final Logger logger = LoggerFactory
60 .getLogger(ReadService.class);
61 private ConcurrentHashMap<String, IPluginInReadService>
63 new ConcurrentHashMap<String, IPluginInReadService>();
66 * Function called by the dependency manager when all the required
67 * dependencies are satisfied
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.
80 // In case of plugin disactivating make sure we clear the
82 this.pluginReader.clear();
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
92 registerWithOSGIConsole();
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
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");
111 logger.trace("Got a service set request {}", s);
113 for (Object e : props.entrySet()) {
114 Map.Entry entry = (Map.Entry) e;
115 logger.trace("Prop key:({}) value:({})", entry.getKey(),
119 Object value = props.get("protocolPluginType");
120 if (value instanceof String) {
121 type = (String) value;
124 logger.error("Received a pluginReader without any "
125 + "protocolPluginType provided");
127 this.pluginReader.put(type, s);
128 logger.debug("Stored the pluginReader for type: {}", type);
132 public void unsetService(Map props, IPluginInReadService s) {
133 if (this.pluginReader == null) {
134 logger.error("pluginReader store 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(),
146 Object value = props.get("protocoloPluginType");
147 if (value instanceof String) {
148 type = (String) value;
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);
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);
167 logger.warn("Plugin unavailable");
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);
179 logger.warn("Plugin unavailable");
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);
191 logger.warn("Plugin unavailable");
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);
203 logger.warn("Plugin unavailable");
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);
215 logger.warn("Plugin unavailable");
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);
227 logger.warn("Plugin unavailable");
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);
240 logger.warn("Plugin unavailable");
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);
254 logger.warn("Plugin unavailable");
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);
266 logger.warn("Plugin unavailable");
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);
278 logger.warn("Plugin unavailable");
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);
292 logger.warn("Plugin unavailable");
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);
305 logger.warn("Plugin unavailable");
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);
317 logger.warn("Plugin unavailable");
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);
330 logger.warn("Plugin unavailable");
334 // ---------------- OSGI TEST CODE ------------------------------//
336 private void registerWithOSGIConsole() {
337 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
339 bundleContext.registerService(CommandProvider.class.getName(), this,
344 public String getHelp() {
345 StringBuffer help = new StringBuffer();
346 help.append("---SAL Reader testing commands---\n");
348 .append("\t readflows <sid> <cached> - Read all the (cached) flows from the openflow switch <sid>\n");
350 .append("\t readflow <sid> <cached> - Read the (cached) sample flow from the openflow switch <sid>\n");
352 .append("\t readdesc <sid> <cached> - Read the (cached) description from openflow switch <sid>\n");
354 .append("\t cached=true/false. If false or not specified, the protocol plugin cached info\n");
356 .append("\t is returned. If true, the info is directly retrieved from the switch\n");
357 return help.toString();
360 public void _readflows(CommandInterpreter ci) {
361 String nodeId = ci.nextArgument();
362 String cacheReq = ci.nextArgument();
364 if (nodeId == null) {
365 ci.print("Node id not specified");
368 cached = (cacheReq == null) ? true : cacheReq.equals("true");
371 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
372 } catch (NumberFormatException e) {
374 } catch (ConstructionException e) {
377 List<FlowOnNode> list = (cached) ? this.readAllFlows(node) : this
378 .nonCachedReadAllFlows(node);
380 ci.println(list.toString());
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();
391 if (nodeId == null) {
392 ci.print("Node id not specified");
395 cached = (cacheReq == null) ? true : cacheReq.equals("true");
398 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
399 } catch (NumberFormatException e) {
401 } catch (ConstructionException e) {
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());
414 public void _readports(CommandInterpreter ci) {
415 String nodeId = ci.nextArgument();
416 String cacheReq = ci.nextArgument();
418 if (nodeId == null) {
419 ci.print("Node id not specified");
422 cached = (cacheReq == null) ? true : cacheReq.equals("true");
425 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
426 } catch (NumberFormatException e) {
428 } catch (ConstructionException e) {
431 List<NodeConnectorStatistics> list = (cached) ? this
432 .readNodeConnectors(node) : this
433 .nonCachedReadNodeConnectors(node);
435 ci.println(list.toString());
441 public void _readport(CommandInterpreter ci) {
442 String nodeId = ci.nextArgument();
443 String portId = ci.nextArgument();
444 String cacheReq = ci.nextArgument();
446 if (nodeId == null) {
447 ci.print("Node id not specified");
450 if (portId == null) {
451 ci.print("Port id not specified");
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);
463 ci.println(stats.toString());
469 public void _readtable(CommandInterpreter ci) {
470 String nodeId = ci.nextArgument();
471 String tableId = ci.nextArgument();
472 String cacheReq = ci.nextArgument();
474 if (nodeId == null) {
475 ci.print("Node id not specified");
478 if (tableId == null) {
479 ci.print("Table id not specified");
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);
491 ci.println(stats.toString());
497 public void _readdescr(CommandInterpreter ci) {
498 String nodeId = ci.nextArgument();
499 String cacheReq = ci.nextArgument();
501 if (nodeId == null) {
502 ci.print("Node id not specified");
505 cached = (cacheReq == null) ? true : cacheReq.equals("true");
509 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
510 } catch (NumberFormatException e) {
512 } catch (ConstructionException e) {
515 NodeDescription desc = (cached) ? this.readDescription(node) : this
516 .nonCachedReadDescription(node);
518 ci.println(desc.toString());
524 private Flow getSampleFlow(Node node) throws UnknownHostException {
525 NodeConnector port = NodeConnectorCreator.createOFNodeConnector(
527 NodeConnector oport = NodeConnectorCreator.createOFNodeConnector(
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;
541 byte proto = IPProtocols.TCP.byteValue();
542 short src = (short) 55000;
546 * Create a SAL Flow aFlow
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);
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);