X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fsal%2Fimplementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fimplementation%2Finternal%2FFlowProgrammerService.java;h=6bea30666925ddaf4991f819597fde625766026f;hb=refs%2Fchanges%2F49%2F449%2F1;hp=cb0a5c77a6979a0872fe63f0896c65d2a6a0d4e8;hpb=42210c03b0a4c54706320ba9f55794c0abd4d201;p=controller.git diff --git a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java index cb0a5c77a6..6bea306669 100644 --- a/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java +++ b/opendaylight/sal/implementation/src/main/java/org/opendaylight/controller/sal/implementation/internal/FlowProgrammerService.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -11,10 +10,13 @@ package org.opendaylight.controller.sal.implementation.internal; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.osgi.framework.console.CommandInterpreter; import org.eclipse.osgi.framework.console.CommandProvider; @@ -26,53 +28,64 @@ import org.opendaylight.controller.sal.action.PopVlan; import org.opendaylight.controller.sal.action.SetNwDst; import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.Node; -import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Node.NodeIDType; +import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.flowprogrammer.Flow; +import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerListener; import org.opendaylight.controller.sal.flowprogrammer.IFlowProgrammerService; import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService; +import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; -import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.IPProtocols; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.Status; +import org.opendaylight.controller.sal.utils.StatusCode; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * The SAL Flow Programmer Service. It dispatches the flow programming - * requests to the proper SDN protocol plugin - * - * - * + * The SAL Flow Programmer Service. It dispatches the flow programming requests + * to the proper SDN protocol plugin and it notifies about asynchronous messages + * received from the network node related to flow programming. */ public class FlowProgrammerService implements IFlowProgrammerService, - CommandProvider { + IPluginOutFlowProgrammerService, CommandProvider { protected static final Logger logger = LoggerFactory .getLogger(FlowProgrammerService.class); - private ConcurrentHashMap - pluginFlowProgrammer = - new ConcurrentHashMap(); + private ConcurrentHashMap pluginFlowProgrammer; + private Set listener; + private AtomicLong seq; + + public FlowProgrammerService() { + pluginFlowProgrammer = new ConcurrentHashMap(); + listener = new HashSet(); + seq = new AtomicLong(); + /* + * This Request ID generator starts with 1. Each aysnc message is + * associated with an unique Request ID (!= 0). + */ + seq.lazySet(1); + } /** * Function called by the dependency manager when all the required * dependencies are satisfied - * + * */ void init() { logger.debug("INIT called!"); } /** - * Function called by the dependency manager when at least one - * dependency become unsatisfied or when the component is shutting - * down because for example bundle is being stopped. - * + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * */ void destroy() { // Clear previous registration to avoid they are left hanging @@ -81,10 +94,9 @@ public class FlowProgrammerService implements IFlowProgrammerService, } /** - * Function called by dependency manager after "init ()" is called - * and after the services provided by the class are registered in - * the service registry - * + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * */ void start() { logger.debug("START called!"); @@ -93,10 +105,10 @@ public class FlowProgrammerService implements IFlowProgrammerService, } /** - * Function called by the dependency manager before the services - * exported by the component are unregistered, this will be - * followed by a "destroy ()" calls - * + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * */ void stop() { logger.debug("STOP called!"); @@ -113,8 +125,8 @@ public class FlowProgrammerService implements IFlowProgrammerService, String type = null; for (Object e : props.entrySet()) { Map.Entry entry = (Map.Entry) e; - logger.trace("Prop key:(" + entry.getKey() + ") value:(" - + entry.getValue() + ")"); + logger.trace("Prop key:({}) value:({})", entry.getKey(), + entry.getValue()); } Object value = props.get("protocolPluginType"); @@ -126,12 +138,11 @@ public class FlowProgrammerService implements IFlowProgrammerService, + "protocolPluginType provided"); } else { this.pluginFlowProgrammer.put(type, s); - logger.debug("Stored the pluginFlowProgrammer for type:" + type); + logger.debug("Stored the pluginFlowProgrammer for type: {}", type); } } - public void unsetService(Map props, - IPluginInFlowProgrammerService s) { + public void unsetService(Map props, IPluginInFlowProgrammerService s) { if (this.pluginFlowProgrammer == null) { logger.error("pluginFlowProgrammer store null"); return; @@ -141,8 +152,8 @@ public class FlowProgrammerService implements IFlowProgrammerService, logger.debug("Received unsetpluginFlowProgrammer request"); for (Object e : props.entrySet()) { Map.Entry entry = (Map.Entry) e; - logger.trace("Prop key:(" + entry.getKey() + ") value:(" - + entry.getValue() + ")"); + logger.trace("Prop key:({}) value:({})", entry.getKey(), + entry.getValue()); } Object value = props.get("protocoloPluginType"); @@ -154,16 +165,24 @@ public class FlowProgrammerService implements IFlowProgrammerService, + "protocolPluginType provided"); } else if (this.pluginFlowProgrammer.get(type).equals(s)) { this.pluginFlowProgrammer.remove(type); - logger.debug("Removed the pluginFlowProgrammer for type:" + type); + logger.debug("Removed the pluginFlowProgrammer for type: {}", type); } } + public void setListener(IFlowProgrammerListener s) { + this.listener.add(s); + } + + public void unsetListener(IFlowProgrammerListener s) { + this.listener.remove(s); + } + @Override public Status addFlow(Node node, Flow flow) { if (pluginFlowProgrammer != null) { if (this.pluginFlowProgrammer.get(node.getType()) != null) { - return this.pluginFlowProgrammer.get(node.getType()) - .addFlow(node, flow); + return this.pluginFlowProgrammer.get(node.getType()).addFlow( + node, flow); } } return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); @@ -174,7 +193,7 @@ public class FlowProgrammerService implements IFlowProgrammerService, if (pluginFlowProgrammer != null) { if (this.pluginFlowProgrammer.get(node.getType()) != null) { return this.pluginFlowProgrammer.get(node.getType()) - .removeFlow(node, flow); + .removeFlow(node, flow); } } return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); @@ -185,7 +204,7 @@ public class FlowProgrammerService implements IFlowProgrammerService, if (pluginFlowProgrammer != null) { if (this.pluginFlowProgrammer.get(node.getType()) != null) { return this.pluginFlowProgrammer.get(node.getType()) - .removeAllFlows(node); + .removeAllFlows(node); } } return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); @@ -196,12 +215,62 @@ public class FlowProgrammerService implements IFlowProgrammerService, if (pluginFlowProgrammer != null) { if (this.pluginFlowProgrammer.get(node.getType()) != null) { return this.pluginFlowProgrammer.get(node.getType()) - .modifyFlow(node, oldFlow, newFlow); + .modifyFlow(node, oldFlow, newFlow); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status addFlowAsync(Node node, Flow flow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()).addFlowAsync( + node, flow, getNextRid()); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status removeFlowAsync(Node node, Flow flow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .removeFlowAsync(node, flow, getNextRid()); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow) { + if (pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .modifyFlowAsync(node, oldFlow, newFlow, getNextRid()); } } return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); } + @Override + public void flowRemoved(Node node, Flow flow) { + for (IFlowProgrammerListener l : listener) { + l.flowRemoved(node, flow); + } + } + + @Override + public void flowErrorReported(Node node, long rid, Object err) { + logger.error("Got error {} for message rid {} from node {}", + new Object[] { err, rid, node }); + + for (IFlowProgrammerListener l : listener) { + l.flowErrorReported(node, rid, err); + } + } + // ---------------- OSGI TEST CODE ------------------------------// private void registerWithOSGIConsole() { @@ -215,10 +284,8 @@ public class FlowProgrammerService implements IFlowProgrammerService, public String getHelp() { StringBuffer help = new StringBuffer(); help.append("---SAL Flow Programmer testing commands---\n"); - help - .append("\t addflow - Add a sample flow to the openflow switch \n"); - help - .append("\t removeflow - Remove the sample flow from the openflow switch \n"); + help.append("\t addflow - Add a sample flow to the openflow switch \n"); + help.append("\t removeflow - Remove the sample flow from the openflow switch \n"); return help.toString(); } @@ -232,13 +299,13 @@ public class FlowProgrammerService implements IFlowProgrammerService, try { node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); } catch (NumberFormatException e) { - e.printStackTrace(); + logger.error("",e); } catch (ConstructionException e) { - e.printStackTrace(); + logger.error("",e); } ci.println(this.addFlow(node, getSampleFlow(node))); } - + public void _modifyflow(CommandInterpreter ci) throws UnknownHostException { Node node = null; String nodeId = ci.nextArgument(); @@ -249,15 +316,15 @@ public class FlowProgrammerService implements IFlowProgrammerService, try { node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); } catch (NumberFormatException e) { - e.printStackTrace(); + logger.error("",e); } catch (ConstructionException e) { - e.printStackTrace(); + logger.error("",e); } Flow flowA = getSampleFlow(node); Flow flowB = getSampleFlow(node); Match matchB = flowB.getMatch(); - matchB.setField(MatchType.NW_DST, InetAddress - .getByName("190.190.190.190")); + matchB.setField(MatchType.NW_DST, + InetAddress.getByName("190.190.190.190")); flowB.setMatch(matchB); ci.println(this.modifyFlow(node, flowA, flowB)); } @@ -272,9 +339,9 @@ public class FlowProgrammerService implements IFlowProgrammerService, try { node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); } catch (NumberFormatException e) { - e.printStackTrace(); + logger.error("",e); } catch (ConstructionException e) { - e.printStackTrace(); + logger.error("",e); } ci.println(this.removeFlow(node, getSampleFlow(node))); } @@ -289,9 +356,9 @@ public class FlowProgrammerService implements IFlowProgrammerService, try { node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); } catch (NumberFormatException e) { - e.printStackTrace(); + logger.error("",e); } catch (ConstructionException e) { - e.printStackTrace(); + logger.error("",e); } ci.println(this.addFlow(node, getSampleFlowV6(node))); } @@ -307,9 +374,9 @@ public class FlowProgrammerService implements IFlowProgrammerService, try { node = new Node(NodeIDType.OPENFLOW, Long.valueOf(nodeId)); } catch (NumberFormatException e) { - e.printStackTrace(); + logger.error("",e); } catch (ConstructionException e) { - e.printStackTrace(); + logger.error("",e); } ci.println(this.removeFlow(node, getSampleFlowV6(node))); } @@ -380,15 +447,17 @@ public class FlowProgrammerService implements IFlowProgrammerService, .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); InetAddress dstIP = InetAddress .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress ipMask = null; //InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); V6Match implementation assumes no mask is specified - InetAddress ipMask2 = null; //InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + InetAddress ipMask = null; // InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + // V6Match implementation assumes no mask is + // specified + InetAddress ipMask2 = null; // InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); short ethertype = EtherTypes.IPv6.shortValue(); short vlan = (short) 27; byte vlanPr = (byte) 3; Byte tos = 4; byte proto = IPProtocols.UDP.byteValue(); short src = (short) 5500; - //short dst = 80; + // short dst = 80; /* * Create a SAL Flow aFlow @@ -399,13 +468,16 @@ public class FlowProgrammerService implements IFlowProgrammerService, match.setField(MatchType.DL_DST, dstMac); match.setField(MatchType.DL_TYPE, ethertype); match.setField(MatchType.DL_VLAN, vlan); - match.setField(MatchType.DL_VLAN_PR, vlanPr); //V6Match does not handle this properly... + match.setField(MatchType.DL_VLAN_PR, vlanPr); // V6Match does not handle + // this properly... match.setField(MatchType.NW_SRC, srcIP, ipMask); match.setField(MatchType.NW_DST, dstIP, ipMask2); match.setField(MatchType.NW_TOS, tos); match.setField(MatchType.NW_PROTO, proto); - match.setField(MatchType.TP_SRC, src); //V6Match does not handle this properly... - //match.setField(MatchType.TP_DST, dst); V6Match does not handle this properly... + match.setField(MatchType.TP_SRC, src); // V6Match does not handle this + // properly... + // match.setField(MatchType.TP_DST, dst); V6Match does not handle this + // properly... List actions = new ArrayList(); actions.add(new Output(oport)); @@ -418,4 +490,36 @@ public class FlowProgrammerService implements IFlowProgrammerService, return flow; } + + /** + * This Request ID generator starts with 1. Each aysnc message is + * associated with an unique Request ID (!= 0). + * + * @return Request ID + */ + private long getNextRid() { + return seq.getAndIncrement(); + } + + @Override + public Status syncSendBarrierMessage(Node node) { + if (this.pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .syncSendBarrierMessage(node); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } + + @Override + public Status asyncSendBarrierMessage(Node node) { + if (this.pluginFlowProgrammer != null) { + if (this.pluginFlowProgrammer.get(node.getType()) != null) { + return this.pluginFlowProgrammer.get(node.getType()) + .asyncSendBarrierMessage(node); + } + } + return new Status(StatusCode.NOSERVICE, "Plugin unuvailable"); + } }