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.GlobalConstants;
42 import org.opendaylight.controller.sal.utils.IPProtocols;
43 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
44 import org.opendaylight.controller.sal.utils.NodeCreator;
45 import org.opendaylight.controller.sal.utils.NodeTableCreator;
46 import org.osgi.framework.BundleContext;
47 import org.osgi.framework.FrameworkUtil;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
52 * The SAL Read Service. It dispatches the read request to
53 * the proper SDN protocol plugin
58 public class ReadService implements IReadService, CommandProvider {
60 protected static final Logger logger = LoggerFactory
61 .getLogger(ReadService.class);
62 private ConcurrentHashMap<String, IPluginInReadService>
64 new ConcurrentHashMap<String, IPluginInReadService>();
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();
87 * Function called by dependency manager after "init ()" is called
88 * and after the services provided by the class are registered in
89 * the service registry
93 registerWithOSGIConsole();
97 * Function called by the dependency manager before the services
98 * exported by the component are unregistered, this will be
99 * followed by a "destroy ()" calls
105 // Set the reference to the plugin flow Reader service
106 public void setService(Map props, IPluginInReadService s) {
107 if (this.pluginReader == null) {
108 logger.error("pluginReader store null");
112 logger.trace("Got a service set request {}", s);
114 for (Object e : props.entrySet()) {
115 Map.Entry entry = (Map.Entry) e;
116 logger.trace("Prop key:({}) value:({})", entry.getKey(),
120 Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
121 if (value instanceof String) {
122 type = (String) value;
125 logger.error("Received a pluginReader without any "
126 + "protocolPluginType provided");
128 this.pluginReader.put(type, s);
129 logger.debug("Stored the pluginReader for type: {}", type);
133 public void unsetService(Map props, IPluginInReadService s) {
134 if (this.pluginReader == null) {
135 logger.error("pluginReader store null");
140 logger.debug("Received unsetpluginReader request");
141 for (Object e : props.entrySet()) {
142 Map.Entry entry = (Map.Entry) e;
143 logger.trace("Prop key:({}) value:({})", entry.getKey(),
147 Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString());
148 if (value instanceof String) {
149 type = (String) value;
152 logger.error("Received a pluginReader without any "
153 + "protocolPluginType provided");
154 } else if (this.pluginReader.get(type).equals(s)) {
155 this.pluginReader.remove(type);
156 logger.debug("Removed the pluginReader for type: {}", type);
161 public FlowOnNode readFlow(Node node, Flow flow) {
162 if (pluginReader != null) {
163 if (this.pluginReader.get(node.getType()) != null) {
164 return this.pluginReader.get(node.getType())
165 .readFlow(node, flow, true);
168 logger.warn("Plugin unavailable");
173 public FlowOnNode nonCachedReadFlow(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, false);
180 logger.warn("Plugin unavailable");
185 public List<FlowOnNode> readAllFlows(Node node) {
186 if (pluginReader != null) {
187 if (this.pluginReader.get(node.getType()) != null) {
188 return this.pluginReader.get(node.getType())
189 .readAllFlow(node, true);
192 logger.warn("Plugin unavailable");
197 public List<FlowOnNode> nonCachedReadAllFlows(Node node) {
198 if (pluginReader != null) {
199 if (this.pluginReader.get(node.getType()) != null) {
200 return this.pluginReader.get(node.getType())
201 .readAllFlow(node, false);
204 logger.warn("Plugin unavailable");
209 public NodeDescription readDescription(Node node) {
210 if (pluginReader != null) {
211 if (this.pluginReader.get(node.getType()) != null) {
212 return this.pluginReader.get(node.getType())
213 .readDescription(node, true);
216 logger.warn("Plugin unavailable");
221 public NodeDescription nonCachedReadDescription(Node node) {
222 if (pluginReader != null) {
223 if (this.pluginReader.get(node.getType()) != null) {
224 return this.pluginReader.get(node.getType())
225 .readDescription(node, false);
228 logger.warn("Plugin unavailable");
233 public NodeConnectorStatistics readNodeConnector(NodeConnector connector) {
234 Node node = connector.getNode();
235 if (pluginReader != null && node != null) {
236 if (this.pluginReader.get(node.getType()) != null) {
237 return this.pluginReader.get(node.getType())
238 .readNodeConnector(connector, true);
241 logger.warn("Plugin unavailable");
246 public NodeConnectorStatistics nonCachedReadNodeConnector(
247 NodeConnector connector) {
248 Node node = connector.getNode();
249 if (pluginReader != null && node != null) {
250 if (this.pluginReader.get(node.getType()) != null) {
251 return this.pluginReader.get(node.getType())
252 .readNodeConnector(connector, false);
255 logger.warn("Plugin unavailable");
260 public List<NodeConnectorStatistics> readNodeConnectors(Node node) {
261 if (pluginReader != null) {
262 if (this.pluginReader.get(node.getType()) != null) {
263 return this.pluginReader.get(node.getType())
264 .readAllNodeConnector(node, true);
267 logger.warn("Plugin unavailable");
272 public List<NodeTableStatistics> readNodeTable(Node node) {
273 if (pluginReader != null) {
274 if (this.pluginReader.get(node.getType()) != null) {
275 return this.pluginReader.get(node.getType())
276 .readAllNodeTable(node, true);
279 logger.warn("Plugin unavailable");
285 public NodeTableStatistics nonCachedReadNodeTable(NodeTable table) {
286 Node node = table.getNode();
287 if (pluginReader != null && node != null) {
288 if (this.pluginReader.get(node.getType()) != null) {
289 return this.pluginReader.get(node.getType())
290 .readNodeTable(table, false);
293 logger.warn("Plugin unavailable");
298 public NodeTableStatistics readNodeTable(NodeTable table) {
299 Node node = table.getNode();
300 if (pluginReader != null && node != null) {
301 if (this.pluginReader.get(node.getType()) != null) {
302 return this.pluginReader.get(node.getType())
303 .readNodeTable(table, true);
306 logger.warn("Plugin unavailable");
311 public List<NodeConnectorStatistics> nonCachedReadNodeConnectors(Node node) {
312 if (pluginReader != null) {
313 if (this.pluginReader.get(node.getType()) != null) {
314 return this.pluginReader.get(node.getType())
315 .readAllNodeConnector(node, false);
318 logger.warn("Plugin unavailable");
323 public long getTransmitRate(NodeConnector connector) {
324 Node node = connector.getNode();
325 if (pluginReader != null && node != null) {
326 if (this.pluginReader.get(node.getType()) != null) {
327 return this.pluginReader.get(node.getType())
328 .getTransmitRate(connector);
331 logger.warn("Plugin unavailable");
335 // ---------------- OSGI TEST CODE ------------------------------//
337 private void registerWithOSGIConsole() {
338 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
340 bundleContext.registerService(CommandProvider.class.getName(), this,
345 public String getHelp() {
346 StringBuffer help = new StringBuffer();
347 help.append("---SAL Reader testing commands---\n");
349 .append("\t readflows <sid> <cached> - Read all the (cached) flows from the openflow switch <sid>\n");
351 .append("\t readflow <sid> <cached> - Read the (cached) sample flow from the openflow switch <sid>\n");
353 .append("\t readdesc <sid> <cached> - Read the (cached) description from openflow switch <sid>\n");
355 .append("\t cached=true/false. If false or not specified, the protocol plugin cached info\n");
357 .append("\t is returned. If true, the info is directly retrieved from the switch\n");
358 return help.toString();
361 public void _readflows(CommandInterpreter ci) {
362 String nodeId = ci.nextArgument();
363 String cacheReq = ci.nextArgument();
365 if (nodeId == null) {
366 ci.print("Node id not specified");
369 cached = (cacheReq == null) ? true : cacheReq.equals("true");
372 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
373 } catch (NumberFormatException e) {
375 } catch (ConstructionException e) {
378 List<FlowOnNode> list = (cached) ? this.readAllFlows(node) : this
379 .nonCachedReadAllFlows(node);
381 ci.println(list.toString());
387 // Requests the hw view for the specific sample flow
388 public void _readflow(CommandInterpreter ci) throws UnknownHostException {
389 String nodeId = ci.nextArgument();
390 String cacheReq = ci.nextArgument();
392 if (nodeId == null) {
393 ci.print("Node id not specified");
396 cached = (cacheReq == null) ? true : cacheReq.equals("true");
399 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
400 } catch (NumberFormatException e) {
402 } catch (ConstructionException e) {
405 Flow flow = getSampleFlow(node);
406 FlowOnNode flowOnNode = (cached) ? this.readFlow(node, flow) : this
407 .nonCachedReadFlow(node, flow);
408 if (flowOnNode != null) {
409 ci.println(flowOnNode.toString());
415 public void _readports(CommandInterpreter ci) {
416 String nodeId = ci.nextArgument();
417 String cacheReq = ci.nextArgument();
419 if (nodeId == null) {
420 ci.print("Node id not specified");
423 cached = (cacheReq == null) ? true : cacheReq.equals("true");
426 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
427 } catch (NumberFormatException e) {
429 } catch (ConstructionException e) {
432 List<NodeConnectorStatistics> list = (cached) ? this
433 .readNodeConnectors(node) : this
434 .nonCachedReadNodeConnectors(node);
436 ci.println(list.toString());
442 public void _readport(CommandInterpreter ci) {
443 String nodeId = ci.nextArgument();
444 String portId = ci.nextArgument();
445 String cacheReq = ci.nextArgument();
447 if (nodeId == null) {
448 ci.print("Node id not specified");
451 if (portId == null) {
452 ci.print("Port id not specified");
455 cached = (cacheReq == null) ? true : cacheReq.equals("true");
456 NodeConnector nodeConnector = null;
457 Node node = NodeCreator.createOFNode(Long.parseLong(nodeId));
458 nodeConnector = NodeConnectorCreator.createNodeConnector(Short
459 .valueOf(portId), node);
460 NodeConnectorStatistics stats = (cached) ? this
461 .readNodeConnector(nodeConnector) : this
462 .nonCachedReadNodeConnector(nodeConnector);
464 ci.println(stats.toString());
470 public void _readtable(CommandInterpreter ci) {
471 String nodeId = ci.nextArgument();
472 String tableId = ci.nextArgument();
473 String cacheReq = ci.nextArgument();
475 if (nodeId == null) {
476 ci.print("Node id not specified");
479 if (tableId == null) {
480 ci.print("Table id not specified");
483 cached = (cacheReq == null) ? true : cacheReq.equals("true");
484 NodeTable nodeTable = null;
485 Node node = NodeCreator.createOFNode(Long.parseLong(nodeId));
486 nodeTable = NodeTableCreator.createNodeTable(Byte
487 .valueOf(tableId), node);
488 NodeTableStatistics stats = (cached) ? this
489 .readNodeTable(nodeTable) : this
490 .nonCachedReadNodeTable(nodeTable);
492 ci.println(stats.toString());
498 public void _readdescr(CommandInterpreter ci) {
499 String nodeId = ci.nextArgument();
500 String cacheReq = ci.nextArgument();
502 if (nodeId == null) {
503 ci.print("Node id not specified");
506 cached = (cacheReq == null) ? true : cacheReq.equals("true");
510 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
511 } catch (NumberFormatException e) {
513 } catch (ConstructionException e) {
516 NodeDescription desc = (cached) ? this.readDescription(node) : this
517 .nonCachedReadDescription(node);
519 ci.println(desc.toString());
525 private Flow getSampleFlow(Node node) throws UnknownHostException {
526 NodeConnector port = NodeConnectorCreator.createOFNodeConnector(
528 NodeConnector oport = NodeConnectorCreator.createOFNodeConnector(
530 byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
531 (byte) 0x9a, (byte) 0xbc };
532 byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d,
533 (byte) 0x5e, (byte) 0x6f };
534 InetAddress srcIP = InetAddress.getByName("172.28.30.50");
535 InetAddress dstIP = InetAddress.getByName("171.71.9.52");
536 InetAddress ipMask = InetAddress.getByName("255.255.255.0");
537 InetAddress ipMask2 = InetAddress.getByName("255.0.0.0");
538 short ethertype = EtherTypes.IPv4.shortValue();
539 short vlan = (short) 27;
542 byte proto = IPProtocols.TCP.byteValue();
543 short src = (short) 55000;
547 * Create a SAL Flow aFlow
549 Match match = new Match();
550 match.setField(MatchType.IN_PORT, port);
551 match.setField(MatchType.DL_SRC, srcMac);
552 match.setField(MatchType.DL_DST, dstMac);
553 match.setField(MatchType.DL_TYPE, ethertype);
554 match.setField(MatchType.DL_VLAN, vlan);
555 match.setField(MatchType.DL_VLAN_PR, vlanPr);
556 match.setField(MatchType.NW_SRC, srcIP, ipMask);
557 match.setField(MatchType.NW_DST, dstIP, ipMask2);
558 match.setField(MatchType.NW_TOS, tos);
559 match.setField(MatchType.NW_PROTO, proto);
560 match.setField(MatchType.TP_SRC, src);
561 match.setField(MatchType.TP_DST, dst);
563 List<Action> actions = new ArrayList<Action>();
564 actions.add(new Output(oport));
565 actions.add(new PopVlan());
566 actions.add(new Flood());
567 actions.add(new Controller());
568 return new Flow(match, actions);