X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fsal%2Fimplementation%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fimplementation%2Finternal%2FFlowProgrammerService.java;h=854125b3567a196b940556363ed56c82e99d50c0;hp=d2a49b9208fac68118ca27e70086ef9b0f59738a;hb=f1f19db0b23d8d470c270cddcd2a6c4eace5f837;hpb=dcd741d1fd2e408f49f2f8e484d6761a39d6eb3f 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 d2a49b9208..854125b356 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,38 +28,50 @@ 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.GlobalConstants; 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 @@ -69,9 +83,9 @@ public class FlowProgrammerService implements IFlowProgrammerService, } /** - * 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() { @@ -81,9 +95,8 @@ 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() { @@ -93,9 +106,9 @@ 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() { @@ -103,21 +116,21 @@ public class FlowProgrammerService implements IFlowProgrammerService, } // Set the reference to the plugin flow programmer - public void setService(Map props, IPluginInFlowProgrammerService s) { + public void setService(Map props, IPluginInFlowProgrammerService s) { if (this.pluginFlowProgrammer == null) { logger.error("pluginFlowProgrammer store null"); return; } - logger.trace("Got a service set request {}", s); - String type = null; - for (Object e : props.entrySet()) { - Map.Entry entry = (Map.Entry) e; - logger.trace("Prop key:({}) value:({})",entry.getKey(), - entry.getValue()); + if (logger.isTraceEnabled()) { + logger.trace("Got a service set request {}", s); + for (Map.Entry entry : props.entrySet()) { + logger.trace("Prop key:({}) value:({})", entry.getKey(), entry.getValue()); + } } - Object value = props.get("protocolPluginType"); + String type = null; + Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString()); if (value instanceof String) { type = (String) value; } @@ -126,26 +139,26 @@ 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; } - String type = null; logger.debug("Received unsetpluginFlowProgrammer request"); - for (Object e : props.entrySet()) { - Map.Entry entry = (Map.Entry) e; - logger.trace("Prop key:({}) value:({})",entry.getKey(), - entry.getValue()); + if (logger.isTraceEnabled()) { + logger.trace("Got a service set request {}", s); + for (Map.Entry entry : props.entrySet()) { + logger.trace("Prop key:({}) value:({})", entry.getKey(), entry.getValue()); + } } - Object value = props.get("protocoloPluginType"); + String type = null; + Object value = props.get(GlobalConstants.PROTOCOLPLUGINTYPE.toString()); if (value instanceof String) { type = (String) value; } @@ -158,12 +171,20 @@ public class FlowProgrammerService implements IFlowProgrammerService, } } + 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 +195,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 +206,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 +217,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 +286,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,9 +301,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, getSampleFlow(node))); } @@ -249,15 +318,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 +341,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 +358,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 +376,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))); } @@ -363,6 +432,7 @@ public class FlowProgrammerService implements IFlowProgrammerService, Flow flow = new Flow(match, actions); flow.setPriority((short) 100); flow.setHardTimeout((short) 360); + flow.setId(1234L); return flow; } @@ -380,15 +450,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 +471,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)); @@ -415,7 +490,40 @@ public class FlowProgrammerService implements IFlowProgrammerService, Flow flow = new Flow(match, actions); flow.setPriority((short) 300); flow.setHardTimeout((short) 240); + flow.setId(65536L); 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"); + } }