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.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;
48 * The SAL Read Service. It dispatches the read request to
49 * the proper SDN protocol plugin
54 public class ReadService implements IReadService, CommandProvider {
56 protected static final Logger logger = LoggerFactory
57 .getLogger(ReadService.class);
58 private ConcurrentHashMap<String, IPluginInReadService>
60 new ConcurrentHashMap<String, IPluginInReadService>();
63 * Function called by the dependency manager when all the required
64 * dependencies are satisfied
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.
77 // In case of plugin disactivating make sure we clear the
79 this.pluginReader.clear();
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
89 registerWithOSGIConsole();
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
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");
108 logger.trace("Got a service set request {}", s);
110 for (Object e : props.entrySet()) {
111 Map.Entry entry = (Map.Entry) e;
112 logger.trace("Prop key:({}) value:({})", entry.getKey(),
116 Object value = props.get("protocolPluginType");
117 if (value instanceof String) {
118 type = (String) value;
121 logger.error("Received a pluginReader without any "
122 + "protocolPluginType provided");
124 this.pluginReader.put(type, s);
125 logger.debug("Stored the pluginReader for type: {}", type);
129 public void unsetService(Map props, IPluginInReadService s) {
130 if (this.pluginReader == null) {
131 logger.error("pluginReader store 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(),
143 Object value = props.get("protocoloPluginType");
144 if (value instanceof String) {
145 type = (String) value;
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);
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);
164 logger.warn("Plugin unavailable");
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);
176 logger.warn("Plugin unavailable");
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);
188 logger.warn("Plugin unavailable");
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);
200 logger.warn("Plugin unavailable");
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);
212 logger.warn("Plugin unavailable");
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);
224 logger.warn("Plugin unavailable");
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);
237 logger.warn("Plugin unavailable");
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);
251 logger.warn("Plugin unavailable");
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);
263 logger.warn("Plugin unavailable");
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);
275 logger.warn("Plugin unavailable");
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);
288 logger.warn("Plugin unavailable");
292 // ---------------- OSGI TEST CODE ------------------------------//
294 private void registerWithOSGIConsole() {
295 BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass())
297 bundleContext.registerService(CommandProvider.class.getName(), this,
302 public String getHelp() {
303 StringBuffer help = new StringBuffer();
304 help.append("---SAL Reader testing commands---\n");
306 .append("\t readflows <sid> <cached> - Read all the (cached) flows from the openflow switch <sid>\n");
308 .append("\t readflow <sid> <cached> - Read the (cached) sample flow from the openflow switch <sid>\n");
310 .append("\t readdesc <sid> <cached> - Read the (cached) description from openflow switch <sid>\n");
312 .append("\t cached=true/false. If false or not specified, the protocol plugin cached info\n");
314 .append("\t is returned. If true, the info is directly retrieved from the switch\n");
315 return help.toString();
318 public void _readflows(CommandInterpreter ci) {
319 String nodeId = ci.nextArgument();
320 String cacheReq = ci.nextArgument();
322 if (nodeId == null) {
323 ci.print("Node id not specified");
326 cached = (cacheReq == null) ? true : cacheReq.equals("true");
329 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
330 } catch (NumberFormatException e) {
332 } catch (ConstructionException e) {
335 List<FlowOnNode> list = (cached) ? this.readAllFlows(node) : this
336 .nonCachedReadAllFlows(node);
338 ci.println(list.toString());
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();
349 if (nodeId == null) {
350 ci.print("Node id not specified");
353 cached = (cacheReq == null) ? true : cacheReq.equals("true");
356 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
357 } catch (NumberFormatException e) {
359 } catch (ConstructionException e) {
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());
372 public void _readports(CommandInterpreter ci) {
373 String nodeId = ci.nextArgument();
374 String cacheReq = ci.nextArgument();
376 if (nodeId == null) {
377 ci.print("Node id not specified");
380 cached = (cacheReq == null) ? true : cacheReq.equals("true");
383 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
384 } catch (NumberFormatException e) {
386 } catch (ConstructionException e) {
389 List<NodeConnectorStatistics> list = (cached) ? this
390 .readNodeConnectors(node) : this
391 .nonCachedReadNodeConnectors(node);
393 ci.println(list.toString());
399 public void _readport(CommandInterpreter ci) {
400 String nodeId = ci.nextArgument();
401 String portId = ci.nextArgument();
402 String cacheReq = ci.nextArgument();
404 if (nodeId == null) {
405 ci.print("Node id not specified");
408 if (portId == null) {
409 ci.print("Port id not specified");
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);
421 ci.println(stats.toString());
427 public void _readdescr(CommandInterpreter ci) {
428 String nodeId = ci.nextArgument();
429 String cacheReq = ci.nextArgument();
431 if (nodeId == null) {
432 ci.print("Node id not specified");
435 cached = (cacheReq == null) ? true : cacheReq.equals("true");
439 node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId));
440 } catch (NumberFormatException e) {
442 } catch (ConstructionException e) {
445 NodeDescription desc = (cached) ? this.readDescription(node) : this
446 .nonCachedReadDescription(node);
448 ci.println(desc.toString());
454 private Flow getSampleFlow(Node node) throws UnknownHostException {
455 NodeConnector port = NodeConnectorCreator.createOFNodeConnector(
457 NodeConnector oport = NodeConnectorCreator.createOFNodeConnector(
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;
471 byte proto = IPProtocols.TCP.byteValue();
472 short src = (short) 55000;
476 * Create a SAL Flow aFlow
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);
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);