From: Alessandro Boch Date: Fri, 21 Jun 2013 17:09:11 +0000 (-0700) Subject: Refactor ForwardingRulesmanager X-Git-Tag: releasepom-0.1.0~330 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=432ddf481f3bb6c297b1353f76a797fc9ef0e454 Refactor ForwardingRulesmanager - Refactor flow entries database in order to remove synchronized methods which hit performance and to better accomodate cluster cache syncing: - Installed entries as a flat concurrent map of FlowInstallEntry key/elements - Modified FlowEntry hashCode function to take into account only the flow parameters which uniquely identify a flow entry: node, match and priority. Modified FlowEntryInstall hashCode function to only account install FlowEntry hash code. - Added a per node and per group index databases for efficiently access node or group flow entries in the flat map - Fixed bugs in MatchField hashcode (did not account MAC addresses), added Junit test for hashcode in Match, FlowEntry and FlowEntryInstall - Have flow entries parameter classes implement Serializable so that FRM flow DB is synced across cluster cntroller nodes - Added api to remove all flows part of a group, uninstallFlowEntryGroup() - Added a event handler thread in FRM so that FRM does not hog switch handler thread on southbound events processing - Changed the installation of startup configured static flows from synchronous to asynchronous flow install - Modified FlowConfig.isValid() to return a status object, changed test code accordingly - Fixed issue where internal generated static flows (the ones for proactive forwarding switches) were getting removed on container creation - Fixed Flows GUI which was not showing static flow state correctly - Minor coding style changes - Changes tested with 2K static flows on two software switches with a custer of two controllers Change-Id: Ic4c0167094988c0ebd44763e45541fe728d95ead Signed-off-by: Alessandro Boch --- diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java index 77c1c859c6..8a77825d79 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java @@ -55,6 +55,7 @@ import org.opendaylight.controller.sal.utils.IPProtocols; import org.opendaylight.controller.sal.utils.NetUtils; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.opendaylight.controller.sal.utils.ServiceHelper; +import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; import org.opendaylight.controller.switchmanager.ISwitchManager; import org.opendaylight.controller.switchmanager.Switch; @@ -65,13 +66,14 @@ import org.slf4j.LoggerFactory; * Configuration Java Object which represents a flow configuration information * for Forwarding Rules Manager. */ - @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class FlowConfig implements Serializable { private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(FlowConfig.class); - private static final String staticFlowsGroup = "**StaticFlows"; + public static final String staticFlowsGroup = "**StaticFlows"; + public static final String internalStaticFlowsGroup = "**InternalStaticFlows"; + public static final String internalStaticFlowBegin = "**"; private boolean dynamic; private String status; @@ -128,13 +130,10 @@ public class FlowConfig implements Serializable { public FlowConfig() { } - public FlowConfig(String installInHw, String name, Node node, - String priority, String cookie, String ingressPort, - String portGroup, String vlanId, String vlanPriority, - String etherType, String srcMac, String dstMac, String protocol, - String tosBits, String srcIP, String dstIP, String tpSrc, - String tpDst, String idleTimeout, String hardTimeout, - List actions) { + public FlowConfig(String installInHw, String name, Node node, String priority, String cookie, String ingressPort, + String portGroup, String vlanId, String vlanPriority, String etherType, String srcMac, String dstMac, + String protocol, String tosBits, String srcIP, String dstIP, String tpSrc, String tpDst, + String idleTimeout, String hardTimeout, List actions) { super(); this.installInHw = installInHw; this.name = name; @@ -202,7 +201,7 @@ public class FlowConfig implements Serializable { public boolean isInternalFlow() { // Controller generated static flows have name starting with "**" - return (this.name != null && this.name.startsWith("**")); + return (this.name != null && this.name.startsWith(FlowConfig.internalStaticFlowBegin)); } public String getName() { @@ -254,17 +253,13 @@ public class FlowConfig implements Serializable { @Override public String toString() { - return "FlowConfig [dynamic=" + dynamic + ", status=" + status - + ", installInHw=" + installInHw + ", name=" + name - + ", switchId=" + node + ", ingressPort=" + ingressPort - + ", portGroup=" + portGroup + ", etherType=" + etherType - + ", priority=" + priority + ", vlanId=" + vlanId - + ", vlanPriority=" + vlanPriority + ", dlSrc=" + dlSrc - + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst - + ", protocol=" + protocol + ", tosBits=" + tosBits - + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst + ", cookie=" - + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" - + hardTimeout + ", actions=" + actions + "]"; + return "FlowConfig [dynamic=" + dynamic + ", status=" + status + ", installInHw=" + installInHw + ", name=" + + name + ", switchId=" + node + ", ingressPort=" + ingressPort + ", portGroup=" + portGroup + + ", etherType=" + etherType + ", priority=" + priority + ", vlanId=" + vlanId + ", vlanPriority=" + + vlanPriority + ", dlSrc=" + dlSrc + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst + + ", protocol=" + protocol + ", tosBits=" + tosBits + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst + + ", cookie=" + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout=" + hardTimeout + ", actions=" + + actions + "]"; } public void setPortGroup(String portGroup) { @@ -376,11 +371,7 @@ public class FlowConfig implements Serializable { } public boolean isIPv6() { - if (NetUtils.isIPv6AddressValid(this.getSrcIp()) - || NetUtils.isIPv6AddressValid(this.getDstIp())) { - return true; - } - return false; + return NetUtils.isIPv6AddressValid(this.getSrcIp()) || NetUtils.isIPv6AddressValid(this.getDstIp()); } public List getActions() { @@ -424,30 +415,22 @@ public class FlowConfig implements Serializable { result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode()); result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode()); result = prime * result + (dynamic ? 1231 : 1237); - result = prime * result - + ((etherType == null) ? 0 : etherType.hashCode()); - result = prime * result - + ((ingressPort == null) ? 0 : ingressPort.hashCode()); + result = prime * result + ((etherType == null) ? 0 : etherType.hashCode()); + result = prime * result + ((ingressPort == null) ? 0 : ingressPort.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode()); result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode()); - result = prime * result - + ((portGroup == null) ? 0 : portGroup.hashCode()); - result = prime * result - + ((priority == null) ? 0 : priority.hashCode()); - result = prime * result - + ((protocol == null) ? 0 : protocol.hashCode()); + result = prime * result + ((portGroup == null) ? 0 : portGroup.hashCode()); + result = prime * result + ((priority == null) ? 0 : priority.hashCode()); + result = prime * result + ((protocol == null) ? 0 : protocol.hashCode()); result = prime * result + ((node == null) ? 0 : node.hashCode()); result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode()); result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode()); result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode()); result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode()); - result = prime * result - + ((vlanPriority == null) ? 0 : vlanPriority.hashCode()); - result = prime * result - + ((idleTimeout == null) ? 0 : idleTimeout.hashCode()); - result = prime * result - + ((hardTimeout == null) ? 0 : hardTimeout.hashCode()); + result = prime * result + ((vlanPriority == null) ? 0 : vlanPriority.hashCode()); + result = prime * result + ((idleTimeout == null) ? 0 : idleTimeout.hashCode()); + result = prime * result + ((hardTimeout == null) ? 0 : hardTimeout.hashCode()); return result; } @@ -614,13 +597,10 @@ public class FlowConfig implements Serializable { return false; } - Pattern macPattern = Pattern - .compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}"); + Pattern macPattern = Pattern.compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}"); Matcher mm = macPattern.matcher(mac); if (!mm.matches()) { - log.debug( - "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", - mac); + log.debug("Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f", mac); return false; } return true; @@ -672,17 +652,16 @@ public class FlowConfig implements Serializable { return ((to >= 0) && (to <= 0xffff)); } - private boolean conflictWithContainerFlow(IContainer container, - StringBuffer resultStr) { + private Status conflictWithContainerFlow(IContainer container) { // Return true if it's default container if (container.getName().equals(GlobalConstants.DEFAULT.toString())) { - return false; + return new Status(StatusCode.SUCCESS); } // No container flow = no conflict List cFlowList = container.getContainerFlows(); if (((cFlowList == null)) || cFlowList.isEmpty()) { - return false; + return new Status(StatusCode.SUCCESS); } // Check against each container's flow @@ -693,36 +672,34 @@ public class FlowConfig implements Serializable { for (ContainerFlow cFlow : cFlowList) { if (cFlow.allowsFlow(flow)) { log.trace("Config is congruent with at least one container flow"); - return false; + return new Status(StatusCode.SUCCESS); } } String msg = "Flow Config conflicts with all existing container flows"; - resultStr.append(msg); log.trace(msg); - return true; + return new Status(StatusCode.BADREQUEST, msg); } - public boolean isValid(IContainer container, StringBuffer resultStr) { + public Status validate(IContainer container) { EtherIPType etype = EtherIPType.ANY; EtherIPType ipsrctype = EtherIPType.ANY; EtherIPType ipdsttype = EtherIPType.ANY; - String containerName = (container == null) ? GlobalConstants.DEFAULT - .toString() : container.getName(); - ISwitchManager switchManager = (ISwitchManager) ServiceHelper - .getInstance(ISwitchManager.class, containerName, this); + String containerName = (container == null) ? GlobalConstants.DEFAULT.toString() : container.getName(); + ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, + this); Switch sw = null; try { - if (name == null) { - resultStr.append(String.format("Name is null")); - return false; + if (name == null || name.trim().isEmpty()) { + return new Status(StatusCode.BADREQUEST, "Invalid name"); } + if (node == null) { - resultStr.append(String.format("Node is null")); - return false; + return new Status(StatusCode.BADREQUEST, "Node is null"); } + if (switchManager != null) { for (Switch device : switchManager.getNetworkDevices()) { if (device.getNode().equals(node)) { @@ -731,20 +708,16 @@ public class FlowConfig implements Serializable { } } if (sw == null) { - resultStr.append(String.format("Node %s not found", node)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Node %s not found", node)); } } else { log.debug("switchmanager is not set yet"); } if (priority != null) { - if (Integer.decode(priority) < 0 - || (Integer.decode(priority) > 65535)) { - resultStr.append(String.format( - "priority %s is not in the range 0 - 65535", + if (Integer.decode(priority) < 0 || (Integer.decode(priority) > 65535)) { + return new Status(StatusCode.BADREQUEST, String.format("priority %s is not in the range 0 - 65535", priority)); - return false; } } @@ -756,39 +729,27 @@ public class FlowConfig implements Serializable { if (ingressPort != null) { Short port = Short.decode(ingressPort); if (isPortValid(sw, port) == false) { - resultStr - .append(String - .format("Ingress port %d is not valid for the Switch", - port)); - if ((container != null) - && !container.getName().equals( - GlobalConstants.DEFAULT.toString())) { - resultStr - .append(" in Container " + container.getName()); + String msg = String.format("Ingress port %d is not valid for the Switch", port); + if ((container != null) && !container.getName().equals(GlobalConstants.DEFAULT.toString())) { + msg += " in Container " + container.getName(); } - return false; + return new Status(StatusCode.BADREQUEST, msg); } } if ((vlanId != null) && !isVlanIdValid(vlanId)) { - resultStr.append(String.format( - "Vlan ID %s is not in the range 0 - 4095", vlanId)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Vlan ID %s is not in the range 0 - 4095", + vlanId)); } if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) { - resultStr.append(String.format( - "Vlan priority %s is not in the range 0 - 7", + return new Status(StatusCode.BADREQUEST, String.format("Vlan priority %s is not in the range 0 - 7", vlanPriority)); - return false; } - if (etherType != null) { int type = Integer.decode(etherType); if ((type < 0) || (type > 0xffff)) { - resultStr.append(String.format( - "Ethernet type %s is not valid", etherType)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Ethernet type %s is not valid", etherType)); } else { if (type == 0x800) { etype = EtherIPType.V4; @@ -799,36 +760,27 @@ public class FlowConfig implements Serializable { } if ((tosBits != null) && !isTOSBitsValid(tosBits)) { - resultStr.append(String.format( - "IP ToS bits %s is not in the range 0 - 63", tosBits)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("IP ToS bits %s is not in the range 0 - 63", + tosBits)); } if ((tpSrc != null) && !isTpPortValid(tpSrc)) { - resultStr.append(String.format( - "Transport source port %s is not valid", tpSrc)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Transport source port %s is not valid", tpSrc)); } + if ((tpDst != null) && !isTpPortValid(tpDst)) { - resultStr.append(String.format( - "Transport destination port %s is not valid", tpDst)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Transport destination port %s is not valid", + tpDst)); } if ((dlSrc != null) && !isL2AddressValid(dlSrc)) { - resultStr - .append(String - .format("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", - dlSrc)); - return false; + return new Status(StatusCode.BADREQUEST, String.format( + "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", dlSrc)); } if ((dlDst != null) && !isL2AddressValid(dlDst)) { - resultStr - .append(String - .format("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", - dlDst)); - return false; + return new Status(StatusCode.BADREQUEST, String.format( + "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", dlDst)); } if (nwSrc != null) { @@ -837,9 +789,7 @@ public class FlowConfig implements Serializable { } else if (NetUtils.isIPv6AddressValid(nwSrc)) { ipsrctype = EtherIPType.V6; } else { - resultStr.append(String.format( - "IP source address %s is not valid", nwSrc)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", nwSrc)); } } @@ -849,42 +799,33 @@ public class FlowConfig implements Serializable { } else if (NetUtils.isIPv6AddressValid(nwDst)) { ipdsttype = EtherIPType.V6; } else { - resultStr.append(String.format( - "IP destination address %s is not valid", nwDst)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("IP destination address %s is not valid", + nwDst)); } } if (etype != EtherIPType.ANY) { if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) { - resultStr.append(String - .format("Type mismatch between Ethernet & Src IP")); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Src IP")); } if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) { - resultStr.append(String - .format("Type mismatch between Ethernet & Dst IP")); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Type mismatch between Ethernet & Dst IP")); } } if (ipsrctype != ipdsttype) { if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) { - resultStr - .append(String.format("IP Src Dest Type mismatch")); - return false; + return new Status(StatusCode.BADREQUEST, String.format("IP Src Dest Type mismatch")); } } if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) { - resultStr.append(String.format( - "Idle Timeout value %s is not valid", idleTimeout)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Idle Timeout value %s is not valid", + idleTimeout)); } if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) { - resultStr.append(String.format( - "Hard Timeout value %s is not valid", hardTimeout)); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Hard Timeout value %s is not valid", + hardTimeout)); } Matcher sstr; @@ -894,24 +835,17 @@ public class FlowConfig implements Serializable { sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp); if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { - Matcher n = Pattern.compile("(?:(\\d+))") - .matcher(t); + Matcher n = Pattern.compile("(?:(\\d+))").matcher(t); if (n.matches()) { if (n.group(1) != null) { Short port = Short.parseShort(n.group(1)); if (isPortValid(sw, port) == false) { - resultStr - .append(String - .format("Output port %d is not valid for this switch", - port)); + String msg = String.format("Output port %d is not valid for this switch", port); if ((container != null) - && !container.getName().equals( - GlobalConstants.DEFAULT - .toString())) { - resultStr.append(" in Container " - + container.getName()); + && !container.getName().equals(GlobalConstants.DEFAULT.toString())) { + msg += " in Container " + container.getName(); } - return false; + return new Status(StatusCode.BADREQUEST, msg); } } } @@ -919,243 +853,181 @@ public class FlowConfig implements Serializable { continue; } // Check src IP - sstr = Pattern.compile(ActionType.FLOOD.toString()) - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp); if (sstr.matches()) { if (container != null) { - resultStr.append(String.format( - "flood is not allowed in container %s", - container.getName())); - return false; + return new Status(StatusCode.BADREQUEST, String.format( + "flood is not allowed in container %s", container.getName())); } continue; } // Check src IP - sstr = Pattern.compile( - ActionType.SET_NW_SRC.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { if (!NetUtils.isIPv4AddressValid(sstr.group(1))) { - resultStr.append(String.format( - "IP source address %s is not valid", + return new Status(StatusCode.BADREQUEST, String.format("IP source address %s is not valid", sstr.group(1))); - return false; } continue; } // Check dst IP - sstr = Pattern.compile( - ActionType.SET_NW_DST.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { if (!NetUtils.isIPv4AddressValid(sstr.group(1))) { - resultStr.append(String.format( - "IP destination address %s is not valid", - sstr.group(1))); - return false; + return new Status(StatusCode.BADREQUEST, String.format( + "IP destination address %s is not valid", sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_VLAN_ID.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isVlanIdValid(sstr.group(1))) { - resultStr.append(String.format( - "Vlan ID %s is not in the range 0 - 4095", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isVlanIdValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "Vlan ID %s is not in the range 0 - 4095", sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_VLAN_PCP.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isVlanPriorityValid(sstr.group(1))) { - resultStr - .append(String - .format("Vlan priority %s is not in the range 0 - 7", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isVlanPriorityValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "Vlan priority %s is not in the range 0 - 7", sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_DL_SRC.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isL2AddressValid(sstr.group(1))) { - resultStr - .append(String - .format("Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f", + sstr.group(1))); } continue; } - - sstr = Pattern.compile( - ActionType.SET_DL_DST.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isL2AddressValid(sstr.group(1))) { - resultStr - .append(String - .format("Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isL2AddressValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f", + sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_NW_TOS.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isTOSBitsValid(sstr.group(1))) { - resultStr - .append(String - .format("IP ToS bits %s is not in the range 0 - 63", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isTOSBitsValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "IP ToS bits %s is not in the range 0 - 63", sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_TP_SRC.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isTpPortValid(sstr.group(1))) { - resultStr.append(String.format( - "Transport source port %s is not valid", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "Transport source port %s is not valid", sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_TP_DST.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - if ((sstr.group(1) != null) - && !isTpPortValid(sstr.group(1))) { - resultStr - .append(String - .format("Transport destination port %s is not valid", - sstr.group(1))); - return false; + if ((sstr.group(1) != null) && !isTpPortValid(sstr.group(1))) { + return new Status(StatusCode.BADREQUEST, String.format( + "Transport destination port %s is not valid", sstr.group(1))); } continue; } - sstr = Pattern.compile( - ActionType.SET_NEXT_HOP.toString() + "=(.*)") - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { if (!NetUtils.isIPAddressValid(sstr.group(1))) { - resultStr.append(String.format( - "IP destination address %s is not valid", - sstr.group(1))); - return false; + return new Status(StatusCode.BADREQUEST, String.format( + "IP destination address %s is not valid", sstr.group(1))); } continue; } } } // Check against the container flow - if ((container != null) - && conflictWithContainerFlow(container, resultStr)) { - return false; + Status status; + if ((container != null) && !(status = conflictWithContainerFlow(container)).isSuccess()) { + return status; } } catch (NumberFormatException e) { - resultStr.append(String.format("Invalid number format %s", - e.getMessage())); - return false; + return new Status(StatusCode.BADREQUEST, String.format("Invalid number format %s", e.getMessage())); } - return true; + return new Status(StatusCode.SUCCESS); } public FlowEntry getFlowEntry() { - return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, - this.getFlow(), this.getNode()); + return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this.getFlow(), this.getNode()); } public Flow getFlow() { Match match = new Match(); if (this.ingressPort != null) { - match.setField( - MatchType.IN_PORT, - NodeConnectorCreator.createOFNodeConnector( - Short.parseShort(ingressPort), getNode())); + match.setField(MatchType.IN_PORT, + NodeConnectorCreator.createOFNodeConnector(Short.parseShort(ingressPort), getNode())); } if (this.dlSrc != null) { - match.setField(MatchType.DL_SRC, - HexEncode.bytesFromHexString(this.dlSrc)); + match.setField(MatchType.DL_SRC, HexEncode.bytesFromHexString(this.dlSrc)); } if (this.dlDst != null) { - match.setField(MatchType.DL_DST, - HexEncode.bytesFromHexString(this.dlDst)); + match.setField(MatchType.DL_DST, HexEncode.bytesFromHexString(this.dlDst)); } if (this.etherType != null) { - match.setField(MatchType.DL_TYPE, Integer.decode(etherType) - .shortValue()); + match.setField(MatchType.DL_TYPE, Integer.decode(etherType).shortValue()); } if (this.vlanId != null) { match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId)); } if (this.vlanPriority != null) { - match.setField(MatchType.DL_VLAN_PR, - Byte.parseByte(this.vlanPriority)); + match.setField(MatchType.DL_VLAN_PR, Byte.parseByte(this.vlanPriority)); } if (this.nwSrc != null) { String parts[] = this.nwSrc.split("/"); InetAddress ip = NetUtils.parseInetAddress(parts[0]); InetAddress mask = null; + int maskLen = 0; if (parts.length > 1) { - int maskLen = Integer.parseInt(parts[1]); - mask = NetUtils.getInetNetworkMask(maskLen, - ip instanceof Inet6Address); + maskLen = Integer.parseInt(parts[1]); + } else { + maskLen = (ip instanceof Inet6Address) ? 128 : 32; } + mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address); match.setField(MatchType.NW_SRC, ip, mask); } if (this.nwDst != null) { String parts[] = this.nwDst.split("/"); InetAddress ip = NetUtils.parseInetAddress(parts[0]); InetAddress mask = null; + int maskLen = 0; if (parts.length > 1) { - int maskLen = Integer.parseInt(parts[1]); - mask = NetUtils.getInetNetworkMask(maskLen, - ip instanceof Inet6Address); + maskLen = Integer.parseInt(parts[1]); + } else { + maskLen = (ip instanceof Inet6Address) ? 128 : 32; } + mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address); match.setField(MatchType.NW_DST, ip, mask); } if (this.protocol != null) { - match.setField(MatchType.NW_PROTO, - IPProtocols.getProtocolNumberByte(this.protocol)); + match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol)); } if (this.tosBits != null) { match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits)); } if (this.tpSrc != null) { - match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc) - .shortValue()); + match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc).shortValue()); } if (this.tpDst != null) { - match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst) - .shortValue()); + match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst).shortValue()); } Flow flow = new Flow(match, getActionList()); @@ -1186,9 +1058,8 @@ public class FlowConfig implements Serializable { return this.node.equals(node); } - public void toggleStatus() { - installInHw = (installInHw == null) ? "true" : (installInHw - .equals("true")) ? "false" : "true"; + public void toggleInstallation() { + installInHw = (installInHw == null) ? "true" : (installInHw.equals("true")) ? "false" : "true"; } /* @@ -1202,156 +1073,118 @@ public class FlowConfig implements Serializable { if (actions != null) { Matcher sstr; for (String actiongrp : actions) { - sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(actiongrp); if (sstr.matches()) { for (String t : sstr.group(1).split(",")) { Matcher n = Pattern.compile("(?:(\\d+))").matcher(t); if (n.matches()) { if (n.group(1) != null) { short ofPort = Short.parseShort(n.group(1)); - actionList.add(new Output(NodeConnectorCreator - .createOFNodeConnector(ofPort, - this.getNode()))); + actionList.add(new Output(NodeConnectorCreator.createOFNodeConnector(ofPort, + this.getNode()))); } } } continue; } - sstr = Pattern.compile(ActionType.DROP.toString()).matcher( - actiongrp); + sstr = Pattern.compile(ActionType.DROP.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new Drop()); continue; } - sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher( - actiongrp); + sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new Loopback()); continue; } - sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher( - actiongrp); + sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new Flood()); continue; } - sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new SwPath()); continue; } - sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher( - actiongrp); + sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new HwPath()); continue; } - sstr = Pattern.compile(ActionType.CONTROLLER.toString()) - .matcher(actiongrp); + sstr = Pattern.compile(ActionType.CONTROLLER.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new Controller()); continue; } - sstr = Pattern.compile( - ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList.add(new SetVlanId( - Short.parseShort(sstr.group(1)))); + actionList.add(new SetVlanId(Short.parseShort(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList - .add(new SetVlanPcp(Byte.parseByte(sstr.group(1)))); + actionList.add(new SetVlanPcp(Byte.parseByte(sstr.group(1)))); continue; } - sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher( - actiongrp); + sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(actiongrp); if (sstr.matches()) { actionList.add(new PopVlan()); continue; } - sstr = Pattern.compile( - ActionType.SET_DL_SRC.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList.add(new SetDlSrc(HexEncode - .bytesFromHexString(sstr.group(1)))); + actionList.add(new SetDlSrc(HexEncode.bytesFromHexString(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_DL_DST.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_DL_DST.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList.add(new SetDlDst(HexEncode - .bytesFromHexString(sstr.group(1)))); + actionList.add(new SetDlDst(HexEncode.bytesFromHexString(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_NW_SRC.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr - .group(1)))); + actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_NW_DST.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_NW_DST.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr - .group(1)))); + actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_NW_TOS.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_TP_SRC.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList - .add(new SetTpSrc(Integer.valueOf(sstr.group(1)))); + actionList.add(new SetTpSrc(Integer.valueOf(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_TP_DST.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_TP_DST.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList - .add(new SetTpDst(Integer.valueOf(sstr.group(1)))); + actionList.add(new SetTpDst(Integer.valueOf(sstr.group(1)))); continue; } - sstr = Pattern.compile( - ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher( - actiongrp); + sstr = Pattern.compile(ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(actiongrp); if (sstr.matches()) { - actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr - .group(1)))); + actionList.add(new SetNextHop(NetUtils.parseInetAddress(sstr.group(1)))); continue; } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java index 8a055329e1..e86e0186c6 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java @@ -25,8 +25,7 @@ import org.slf4j.LoggerFactory; * instance the flows constituting a policy all share the same group name. */ public class FlowEntry implements Cloneable, Serializable { - protected static final Logger logger = LoggerFactory - .getLogger(FlowEntry.class); + protected static final Logger logger = LoggerFactory.getLogger(FlowEntry.class); private static final long serialVersionUID = 1L; private static final Logger log = LoggerFactory.getLogger(FlowEntry.class); private String groupName; // group name @@ -86,55 +85,65 @@ public class FlowEntry implements Cloneable, Serializable { return cloned; } + /* + * Only accounts fields which uniquely identify a flow for collision + * purposes: node, match and priority + */ @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((flow == null) ? 0 : flow.hashCode()); - result = prime * result - + ((flowName == null) ? 0 : flowName.hashCode()); - result = prime * result - + ((groupName == null) ? 0 : groupName.hashCode()); result = prime * result + ((node == null) ? 0 : node.hashCode()); + result = prime * result + ((flow == null) ? 0 : (int) flow.getPriority()); + result = prime * result + ((flow == null || flow.getMatch() == null) ? 0 : flow.getMatch().hashCode()); + return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } FlowEntry other = (FlowEntry) obj; - if (flow == null) { - if (other.flow != null) + + if (node == null) { + if (other.node != null) { return false; - } else if (!flow.equals(other.flow)) + } + } else if (!node.equals(other.node)) { return false; - if (flowName == null) { - if (other.flowName != null) - return false; - } else if (!flowName.equals(other.flowName)) + } + + if (flow == null) { + return (other.flow == null) ? true : false; + } else if (other.flow == null) { return false; - if (groupName == null) { - if (other.groupName != null) - return false; - } else if (!groupName.equals(other.groupName)) + } + if (flow.getPriority() != other.flow.getPriority()) { return false; - if (node == null) { - if (other.node != null) + } + if (flow.getMatch() == null) { + if (other.flow.getMatch() != null) { return false; - } else if (!node.equals(other.node)) + } + } else if (!flow.getMatch().equals(other.flow.getMatch())) { return false; + } + return true; } @Override public String toString() { - return "FlowEntry[flowName = " + flowName + ", groupName = " - + groupName + ",node = " + node + ", flow = " + flow + "]"; + return "FlowEntry[flowName = " + flowName + ", groupName = " + groupName + ", node = " + node + ", flow = " + + flow + "]"; } private String constructFlowName() { @@ -170,4 +179,14 @@ public class FlowEntry implements Cloneable, Serializable { return this; } + + /** + * Returns whether this entry is the result of an internal generated static + * flow + * + * @return true if internal generated static flow, false otherwise + */ + public boolean isInternal() { + return flowName.startsWith(FlowConfig.internalStaticFlowBegin); + } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java index 311d2f96ac..ebb5a7bb24 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java @@ -8,6 +8,8 @@ package org.opendaylight.controller.forwardingrulesmanager; +import java.io.Serializable; + import org.opendaylight.controller.sal.core.ContainerFlow; import org.opendaylight.controller.sal.core.Node; @@ -20,59 +22,54 @@ import org.opendaylight.controller.sal.core.Node; * * Note: If the container flow is null, the install entry will be a clone of the * original entry - * */ -public class FlowEntryInstall { - private FlowEntry original; - private ContainerFlow cFlow; - private FlowEntry install; +public class FlowEntryInstall implements Serializable { + private static final long serialVersionUID = 1L; + private final FlowEntry original; + private final ContainerFlow cFlow; + private final FlowEntry install; transient private long requestId; // async request id transient private boolean deletePending; public FlowEntryInstall(FlowEntry original, ContainerFlow cFlow) { this.original = original; this.cFlow = cFlow; - this.install = (cFlow == null) ? original.clone() : original - .mergeWith(cFlow); + this.install = (cFlow == null) ? original.clone() : original.mergeWith(cFlow); deletePending = false; requestId = 0; } + /* + * Given FlowEntryInstall is used as key for FRM map which contains the + * software view of installed entries, having its hashcode tied to the one + * of the installed FlowEntry which takes into account the fields which + * uniquely identify a flow from switch point of view: node, match and + * priority. + */ @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((cFlow == null) ? 0 : cFlow.hashCode()); - result = prime * result + ((install == null) ? 0 : install.hashCode()); - result = prime * result - + ((original == null) ? 0 : original.hashCode()); - return result; + return install.hashCode(); } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } FlowEntryInstall other = (FlowEntryInstall) obj; - if (cFlow == null) { - if (other.cFlow != null) - return false; - } else if (!cFlow.equals(other.cFlow)) - return false; if (install == null) { - if (other.install != null) + if (other.install != null) { return false; - } else if (!install.equals(other.install)) - return false; - if (original == null) { - if (other.original != null) - return false; - } else if (!original.equals(other.original)) + } + } else if (!install.equals(other.install)) { return false; + } return true; } @@ -120,9 +117,18 @@ public class FlowEntryInstall { return requestId; } + /** + * Returns whether this entry is the result of an internal generated static + * flow + * + * @return true if internal generated static flow, false otherwise + */ + public boolean isInternal() { + return original.isInternal(); + } + @Override public String toString() { - return "[Install = " + install + " Original = " + original + " cFlow = " - + cFlow + " rid = " + requestId + "]"; + return "[Install = " + install + " Original = " + original + " cFlow = " + cFlow + " rid = " + requestId + "]"; } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java index b3d0c8acdf..bde6932a62 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java @@ -18,7 +18,6 @@ import org.opendaylight.controller.sal.utils.Status; /** * Interface that describes methods for installing or removing forwarding rules * and to access to the flows database. - * */ public interface IForwardingRulesManager { @@ -46,6 +45,19 @@ public interface IForwardingRulesManager { */ public Status uninstallFlowEntry(FlowEntry flow); + /** + * It requests FRM to remove all the Flow Entry that are part of the + * specified group. FRM will request the SDN protocol plugin to uninstall + * the flows from the network node one by one. Based on the result of this + * operation FRM will update its database accordingly and will return the + * proper {@code Status} code. + * + * @param groupName + * the group name + * @return the {@code Status} object indicating the result of this action + */ + public Status uninstallFlowEntryGroup(String groupName); + /** * It requests FRM to replace the currently installed Flow Entry with the * new one. It is up to the SDN protocol plugin to decide how to convey this @@ -73,7 +85,6 @@ public interface IForwardingRulesManager { * not valid an error code is returned. If the existing flow is equal to the * passed one it will be a no op and success code is returned. * - * * @param newone * the new flow entry to install * @return the {@code Status} object indicating the result of this action @@ -99,7 +110,7 @@ public interface IForwardingRulesManager { * call. A unique request id is returned to the caller. FRM will request the * SDN protocol plugin to uninstall the flow from the network node. As * immediate result of this asynchronous call, FRM will update its flow - * database as if the flow was successfully installed. + * database as if the flow was successfully removed. * * @param flow * the flow entry to uninstall @@ -108,6 +119,19 @@ public interface IForwardingRulesManager { */ public Status uninstallFlowEntryAsync(FlowEntry flow); + /** + * It requests FRM to remove all the Flow Entry that are part of the + * specified group through an asynchronous call. FRM will request the SDN + * protocol plugin to uninstall the flows from the network node one by one. + * As immediate result of this asynchronous call, FRM will update its flow + * database as if the flow was successfully removed. + * + * @param groupName + * the group name + * @return the {@code Status} object indicating the result of this action + */ + public Status uninstallFlowEntryGroupAsync(String groupName); + /** * It requests FRM to replace the currently installed Flow Entry with the * new one through an asynchronous call. A unique request id is returned to @@ -194,8 +218,7 @@ public interface IForwardingRulesManager { * @param dstPort * the list of ports to be added to the flow output actions */ - public void addOutputPort(Node node, String flowName, - List dstPort); + public void addOutputPort(Node node, String flowName, List dstPort); /** * Remove a list of output port from the flow with the specified name on the @@ -208,8 +231,7 @@ public interface IForwardingRulesManager { * @param dstPortthe * list of ports to be removed from the flow output actions */ - public void removeOutputPort(Node node, String flowName, - List dstPort); + public void removeOutputPort(Node node, String flowName, List dstPort); /** * Replace the current output port in the specified flow with the specified @@ -224,8 +246,7 @@ public interface IForwardingRulesManager { * @param dstPort * the new output action port */ - public void replaceOutputPort(Node node, String flowName, - NodeConnector outPort); + public void replaceOutputPort(Node node, String flowName, NodeConnector outPort); /** * Returns the output port configured on the specified flow diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java index 952b3cdff7..31e1ea199b 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java @@ -11,7 +11,6 @@ package org.opendaylight.controller.forwardingrulesmanager; /** * The interface which describes the methods forwarding rules manager will call * for notifying the listeners of policy installation updates. - * */ public interface IForwardingRulesManagerAware { diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java index 95e9b00d14..b05091a4d7 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java @@ -17,8 +17,6 @@ import java.util.Set; * * PortGroup is used by PortGroupProvider application to signal a set of ports * that represent a configured PortGroupConfig. - * - * */ public class PortGroup { private long matrixSwitchId; @@ -99,7 +97,6 @@ public class PortGroup { @Override public String toString() { - return "PortGroup [matrixSwitchId=" + matrixSwitchId + ", ports=" - + ports + "]"; + return "PortGroup [matrixSwitchId=" + matrixSwitchId + ", ports=" + ports + "]"; } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java index 77ff64014b..5f28608338 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java @@ -32,6 +32,5 @@ public interface PortGroupChangeListener { * true indicates that the PortGroup is added. False indicates * that the PortGroup is removed. */ - void portGroupChanged(PortGroupConfig config, - Map portGroupData, boolean add); + void portGroupChanged(PortGroupConfig config, Map portGroupData, boolean add); } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java index b45f4898bf..c634426d43 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java @@ -129,8 +129,7 @@ public class PortGroupConfig implements Serializable { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result - + ((matchString == null) ? 0 : matchString.hashCode()); + result = prime * result + ((matchString == null) ? 0 : matchString.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @@ -159,7 +158,6 @@ public class PortGroupConfig implements Serializable { @Override public String toString() { - return "PortGroupConfig [name=" + name + ", matchString=" + matchString - + "]"; + return "PortGroupConfig [name=" + name + ", matchString=" + matchString + "]"; } } diff --git a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java index 5a9281aea8..7b53eb0b8a 100644 --- a/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java +++ b/opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java @@ -70,8 +70,7 @@ public interface PortGroupProvider { * @return PortGroup data for a given Openflow switch. * @see PortGroup */ - public PortGroup getPortGroupData(PortGroupConfig config, - long matrixSwitchId); + public PortGroup getPortGroupData(PortGroupConfig config, long matrixSwitchId); /** * Registers a Listener for Port Group membership changes based on Custom diff --git a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java index 34337ba42b..f139f45377 100644 --- a/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java +++ b/opendaylight/forwardingrulesmanager/api/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java @@ -14,6 +14,8 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import org.junit.Assert; import org.junit.Test; @@ -28,6 +30,7 @@ import org.opendaylight.controller.sal.action.PopVlan; import org.opendaylight.controller.sal.action.SetDlDst; import org.opendaylight.controller.sal.action.SetNwDst; import org.opendaylight.controller.sal.action.SetVlanId; +import org.opendaylight.controller.sal.core.ContainerFlow; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.flowprogrammer.Flow; @@ -37,19 +40,18 @@ 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.NodeCreator; +import org.opendaylight.controller.sal.utils.Status; public class frmTest { @Test public void testFlowEntryInstall() throws UnknownHostException { Node node = NodeCreator.createOFNode(1L); - FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), - node); - FlowEntry pol2 = new FlowEntry("polTest2", null, getSampleFlowV6(node), - node); - FlowEntryInstall fei = new FlowEntryInstall(pol, null); - FlowEntryInstall fei2 = new FlowEntryInstall(pol, null); - FlowEntryInstall fei3 = new FlowEntryInstall(pol2, null); + FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), node); + FlowEntry pol2 = new FlowEntry("polTest2", null, getSampleFlowV6(node), node); + FlowEntryInstall fei = new FlowEntryInstall(pol.clone(), null); + FlowEntryInstall fei2 = new FlowEntryInstall(pol.clone(), null); + FlowEntryInstall fei3 = new FlowEntryInstall(pol2.clone(), null); Assert.assertTrue(fei.getOriginal().equals(pol)); Assert.assertTrue(fei.getInstall().equals(pol)); Assert.assertTrue(fei.getFlowName().equals(pol.getFlowName())); @@ -59,21 +61,18 @@ public class frmTest { fei.toBeDeleted(); Assert.assertTrue(fei.isDeletePending()); Assert.assertNull(fei.getContainerFlow()); - Assert.assertTrue(fei.equalsByNodeAndName(pol.getNode(), - pol.getFlowName())); + Assert.assertTrue(fei.equalsByNodeAndName(pol.getNode(), pol.getFlowName())); Assert.assertTrue(fei.equals(fei2)); - fei2.getOriginal().setFlowName("polTest2"); Assert.assertFalse(fei.equals(null)); - Assert.assertFalse(fei.equals(fei3)); + Assert.assertTrue(fei.equals(fei3)); } @Test public void testFlowEntryCreation() throws UnknownHostException { Node node = NodeCreator.createOFNode(1L); - FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), - node); + FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), node); Assert.assertTrue(pol.getFlow().equals(getSampleFlowV6(node))); } @@ -81,8 +80,7 @@ public class frmTest { public void testFlowEntrySetGet() throws UnknownHostException { Node node = NodeCreator.createOFNode(1L); Node node2 = NodeCreator.createOFNode(2L); - FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), - node); + FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), node); pol.setGroupName("polTest2"); pol.setFlowName("flowName"); Assert.assertTrue(pol.getFlowName().equals("flowName")); @@ -96,18 +94,127 @@ public class frmTest { public void testFlowEntryEquality() throws UnknownHostException { Node node = NodeCreator.createOFNode(1L); Node node2 = NodeCreator.createOFNode(1L); - FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), - node); - FlowEntry pol2 = new FlowEntry("polTest", null, getSampleFlowV6(node), - node2); + FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), node); + FlowEntry pol2 = new FlowEntry("polTest", null, getSampleFlowV6(node), node2); Assert.assertTrue(pol.equals(pol2)); } + @Test + public void testFlowEntryCollision() throws UnknownHostException { + // Create 2 equal FlowEntry objects + Node node1 = NodeCreator.createOFNode(1L); + Node node2 = NodeCreator.createOFNode(1L); + FlowEntry fe1 = new FlowEntry("Junit", "flow1", getSampleFlowV6(node1), node1); + FlowEntry fe2 = new FlowEntry("Junit", "flow2", getSampleFlowV6(node2), node1); + + // Check equality in FlowEntry and parameters + Assert.assertTrue(fe1.getFlow().getMatch().equals(fe2.getFlow().getMatch())); + Assert.assertTrue(fe1.getFlow().getMatch().getMatches() == fe2.getFlow().getMatch().getMatches()); + Assert.assertTrue(fe1.getFlow().getMatch().hashCode() == fe2.getFlow().getMatch().hashCode()); + Assert.assertTrue(fe1.getFlow().hashCode() == fe2.getFlow().hashCode()); + Assert.assertTrue(fe1.equals(fe2)); + Assert.assertTrue(fe1.hashCode() == fe2.hashCode()); + + // Change priority field for fe2, verify inequality + fe2.getFlow().setPriority((short)1000); + + // Verify FlowEntry works as key in collection + ConcurrentMap map = new ConcurrentHashMap(); + Assert.assertTrue(null == map.put(fe1, fe1)); + Assert.assertTrue(fe1.clone().equals(map.put(fe1.clone(), fe1.clone()))); + Assert.assertTrue(map.get(fe1.clone()).equals(fe1.clone())); + Assert.assertTrue(map.keySet().contains(fe1.clone())); + Assert.assertTrue(map.containsKey(fe1)); + + // Remove key + map.remove(fe1); + Assert.assertTrue(map.isEmpty()); + Assert.assertFalse(map.containsKey(fe1)); + + // Verify cloned object as key + map.put(fe1.clone(), fe1.clone()); + Assert.assertTrue(map.containsKey(fe1)); + + // Verify different key is not present + Assert.assertFalse(map.containsKey(fe2)); + + // Add different key + map.put(fe2.clone(), fe2.clone()); + Assert.assertTrue(map.size() == 2); + Assert.assertTrue(map.containsKey(fe1)); + Assert.assertTrue(map.containsKey(fe2)); + + // Make fe2 equal to fe1 again + fe2.getFlow().setPriority((short)300); + Assert.assertTrue(fe2.equals(fe1)); + Assert.assertTrue(map.containsKey(fe2)); + + // Clean up + map.clear(); + } + + @Test + public void testFlowEntryInstallCollision() throws UnknownHostException { + // Create 2 equal FlowEntryInstall objects + Node node1 = NodeCreator.createOFNode(1L); + Node node2 = NodeCreator.createOFNode(1L); + FlowEntry fe1 = new FlowEntry("Junit", "flow1", getSampleFlowV6(node1), node1); + FlowEntry fe2 = new FlowEntry("Junit", "flow2", getSampleFlowV6(node2), node1); + ContainerFlow cf1 = null; + ContainerFlow cf2 = null; + FlowEntryInstall fei1 = new FlowEntryInstall(fe1, cf1); + FlowEntryInstall fei2 = new FlowEntryInstall(fe2, cf2); + + // Check equality in FlowEntry and parameters + Assert.assertTrue(fei1.equals(fei2)); + Assert.assertTrue(fei1.hashCode() == fei2.hashCode()); + + // Verify FlowEntryInstall works as key in collection + ConcurrentMap map = + new ConcurrentHashMap(); + Assert.assertTrue(null == map.put(fei1, fei1)); + Assert.assertTrue(map.get(fei1).equals(fei2)); + Assert.assertTrue(map.keySet().contains(fei1)); + Assert.assertTrue(map.keySet().contains(fei2)); + Assert.assertTrue(map.containsKey(fei1)); + + // Remove key + map.remove(fei1); + Assert.assertTrue(map.isEmpty()); + Assert.assertFalse(map.containsKey(fei1)); + + // Verify cloned object as key + map.put(fei1, fei1); + Assert.assertTrue(map.containsKey(fei1)); + + // Change fei2, change relevant hashcode info + fei2.getInstall().getFlow().setPriority((short)301); + Assert.assertFalse(fei1.equals(fei2)); + Assert.assertFalse(fei1.hashCode() == fei2.hashCode()); + + + // Verify different key is not present + Assert.assertFalse(map.containsKey(fei2)); + + // Add different key + map.put(fei2, fei2); + Assert.assertTrue(map.size() == 2); + Assert.assertTrue(map.containsKey(fei1)); + Assert.assertTrue(map.containsKey(fei2)); + + // Make fei2 equal to fei1 again + fei2.getInstall().getFlow().setPriority((short)300); + Assert.assertTrue(fei2.equals(fei1)); + Assert.assertTrue(map.containsKey(fei2)); + + // Clean up + map.clear(); + } + @Test public void testFlowEntryCloning() throws UnknownHostException { Node node = NodeCreator.createOFNode(1L); - FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), - node); + FlowEntry pol = new FlowEntry("polTest", null, getSampleFlowV6(node), node); FlowEntry pol2 = pol.clone(); Assert.assertTrue(pol.equals(pol2)); } @@ -162,8 +269,7 @@ public class frmTest { FlowConfig frmC = new FlowConfig(); FlowConfig frmC3 = new FlowConfig(); Node node = NodeCreator.createOFNode(1L); - FlowEntry entry = new FlowEntry("polTest", null, getSampleFlowV6(node), - node); + FlowEntry entry = new FlowEntry("polTest", null, getSampleFlowV6(node), node); // testing equal function Assert.assertFalse(frmC.equals(null)); @@ -262,8 +368,7 @@ public class frmTest { Assert.assertFalse(frmC.equals(flowC)); frmC.setNode(Node.fromString(Node.NodeIDType.OPENFLOW, "1")); - Assert.assertTrue(frmC.getNode().equals( - Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); + Assert.assertTrue(frmC.getNode().equals(Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); Assert.assertFalse(frmC.equals(frmC3)); frmC3.setNode(Node.fromString(Node.NodeIDType.OPENFLOW, "1")); @@ -345,17 +450,12 @@ public class frmTest { FlowConfig fc2 = new FlowConfig(); fc.setName("flow1"); fc.setNode(Node.fromString(Node.NodeIDType.OPENFLOW, "1")); - Assert.assertFalse(fc.onNode(Node.fromString(Node.NodeIDType.OPENFLOW, - "0"))); - Assert.assertTrue(fc.onNode(Node.fromString(Node.NodeIDType.OPENFLOW, - "1"))); - - Assert.assertTrue(fc.isByNameAndNodeIdEqual("flow1", - Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); - Assert.assertFalse(fc.isByNameAndNodeIdEqual("flow1", - Node.fromString(Node.NodeIDType.OPENFLOW, "0"))); - Assert.assertFalse(fc.isByNameAndNodeIdEqual("flow2", - Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); + Assert.assertFalse(fc.onNode(Node.fromString(Node.NodeIDType.OPENFLOW, "0"))); + Assert.assertTrue(fc.onNode(Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); + + Assert.assertTrue(fc.isByNameAndNodeIdEqual("flow1", Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); + Assert.assertFalse(fc.isByNameAndNodeIdEqual("flow1", Node.fromString(Node.NodeIDType.OPENFLOW, "0"))); + Assert.assertFalse(fc.isByNameAndNodeIdEqual("flow2", Node.fromString(Node.NodeIDType.OPENFLOW, "1"))); Assert.assertFalse(fc.isByNameAndNodeIdEqual(fc2)); fc2.setName("flow1"); @@ -369,11 +469,11 @@ public class frmTest { @Test public void testStatusToggle() throws UnknownHostException { FlowConfig fc = new FlowConfig(); - fc.toggleStatus(); + fc.toggleInstallation(); Assert.assertTrue(fc.installInHw()); - fc.toggleStatus(); + fc.toggleInstallation(); Assert.assertFalse(fc.installInHw()); - fc.toggleStatus(); + fc.toggleInstallation(); Assert.assertTrue(fc.installInHw()); } @@ -406,181 +506,216 @@ public class frmTest { @Test public void testValid() throws UnknownHostException { - StringBuffer sb = new StringBuffer(); - sb.setLength(0); FlowConfig fc2 = createSampleFlowConfig(); - Assert.assertTrue(fc2.isValid(null, sb)); + Assert.assertTrue(fc2.validate(null).isSuccess()); FlowConfig fc = new FlowConfig(); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Name is null")); + Status status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Invalid name")); fc.setName("Config"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Node is null")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Node is null")); fc.setNode(Node.fromString(Node.NodeIDType.OPENFLOW, "1")); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setPriority("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains( - "is not in the range 0 - 65535")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 65535")); fc.setPriority("100000"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains( - "is not in the range 0 - 65535")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 65535")); + fc.setPriority("2000"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setCookie("100"); + Assert.assertTrue(fc.validate(null).isSuccess()); + fc.setIngressPort("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("is not valid for the Switch")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not valid for the Switch")); + fc.setIngressPort("100"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setVlanId(("-1")); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString() - .contains("is not in the range 0 - 4095")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 4095")); + fc.setVlanId("5000"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString() - .contains("is not in the range 0 - 4095")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 4095")); + fc.setVlanId("100"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); + fc.setVlanPriority("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("is not in the range 0 - 7")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 7")); + fc.setVlanPriority("9"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("is not in the range 0 - 7")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("is not in the range 0 - 7")); + fc.setVlanPriority("5"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setEtherType("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Ethernet type")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Ethernet type")); + fc.setEtherType("0xfffff"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Ethernet type")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Ethernet type")); + fc.setEtherType("0x800"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setTosBits("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("IP ToS bits")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("IP ToS bits")); + fc.setTosBits("65"); - sb.setLength(0); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("IP ToS bits")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("IP ToS bits")); + fc.setTosBits("60"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setSrcPort("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Transport source port")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Transport source port")); + fc.setSrcPort("0xfffff"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Transport source port")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Transport source port")); + fc.setSrcPort("0x00ff"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setDstPort("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Transport destination port")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Transport destination port")); + fc.setDstPort("0xfffff"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Transport destination port")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Transport destination port")); + fc.setDstPort("0x00ff"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setSrcMac("abc"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Ethernet source address")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Ethernet source address")); + fc.setSrcMac("00:A0:C9:14:C8:29"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setDstMac("abc"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString() - .contains("Ethernet destination address")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Ethernet destination address")); + fc.setDstMac("00:A0:C9:22:AB:11"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setSrcIp("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("IP source address")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("IP source address")); + fc.setSrcIp("2001:420:281:1004:407a:57f4:4d15:c355"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains( - "Type mismatch between Ethernet & Src IP")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Src IP")); fc.setEtherType("0x86dd"); - Assert.assertTrue(fc.isValid(null, sb)); - sb.setLength(0); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setSrcIp("1.1.1.1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains( - "Type mismatch between Ethernet & Src IP")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Src IP")); + fc.setEtherType("0x800"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setDstIp("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("IP destination address")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("IP destination address")); + fc.setDstIp("2001:420:281:1004:407a:57f4:4d15:c355"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains( - "Type mismatch between Ethernet & Dst IP")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Dst IP")); fc.setEtherType("0x86dd"); fc.setSrcIp("2001:420:281:1004:407a:57f4:4d15:c355"); - Assert.assertTrue(fc.isValid(null, sb)); - sb.setLength(0); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setDstIp("2.2.2.2"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains( - "Type mismatch between Ethernet & Dst IP")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Type mismatch between Ethernet & Dst IP")); + fc.setEtherType("0x800"); fc.setSrcIp("1.1.1.1"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setEtherType(null); fc.setSrcIp("2001:420:281:1004:407a:57f4:4d15:c355"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("IP Src Dest Type mismatch")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("IP Src Dest Type mismatch")); + fc.setSrcIp("1.1.1.1"); fc.setIdleTimeout("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Idle Timeout value")); - sb.setLength(0); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Idle Timeout value")); + fc.setIdleTimeout("0xfffff"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Idle Timeout value")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Idle Timeout value")); + fc.setIdleTimeout("10"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); fc.setHardTimeout("-1"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Hard Timeout value")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Hard Timeout value")); + fc.setHardTimeout("0xfffff"); - Assert.assertFalse(fc.isValid(null, sb)); - Assert.assertTrue(sb.toString().contains("Hard Timeout value")); + status = fc.validate(null); + Assert.assertFalse(status.isSuccess()); + Assert.assertTrue(status.getDescription().contains("Hard Timeout value")); + fc.setHardTimeout("10"); - Assert.assertTrue(fc.isValid(null, sb)); + Assert.assertTrue(fc.validate(null).isSuccess()); } @@ -588,11 +723,9 @@ public class frmTest { ArrayList actions; actions = createSampleActionList(); // actions.add(ActionType.CONTROLLER.toString()); - FlowConfig flowConfig = new FlowConfig("true", "Config1", - Node.fromString(Node.NodeIDType.OPENFLOW, "1"), "100", "0", - "60", "2", "100", "0", "0x0800", "00:A0:C9:14:C8:29", - "00:A0:C9:22:AB:11", IPProtocols.TCP.toString(), "0", - "1.2.3.4", "2.2.2.2", "8080", "100", "300", "1000", actions); + FlowConfig flowConfig = new FlowConfig("true", "Config1", Node.fromString(Node.NodeIDType.OPENFLOW, "1"), + "100", "0", "60", "2", "100", "0", "0x0800", "00:A0:C9:14:C8:29", "00:A0:C9:22:AB:11", + IPProtocols.TCP.toString(), "0", "1.2.3.4", "2.2.2.2", "8080", "100", "300", "1000", actions); return flowConfig; } @@ -621,24 +754,15 @@ public class frmTest { } private Flow getSampleFlowV6(Node node) throws UnknownHostException { - NodeConnector port = NodeConnectorCreator.createOFNodeConnector( - (short) 24, node); - NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( - (short) 30, node); - byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, - (byte) 0x9a, (byte) 0xbc }; - byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, - (byte) 0x5e, (byte) 0x6f }; - byte newMac[] = { (byte) 0x11, (byte) 0xaa, (byte) 0xbb, (byte) 0x34, - (byte) 0x9a, (byte) 0xee }; - InetAddress srcIP = InetAddress - .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); - InetAddress dstIP = InetAddress - .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress ipMask = InetAddress - .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); - InetAddress ipMask2 = InetAddress - .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector((short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + byte newMac[] = { (byte) 0x11, (byte) 0xaa, (byte) 0xbb, (byte) 0x34, (byte) 0x9a, (byte) 0xee }; + InetAddress srcIP = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress.getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask = InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMask2 = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); InetAddress newIP = InetAddress.getByName("2056:650::a1b0"); short ethertype = EtherTypes.IPv6.shortValue(); short vlan = (short) 27; @@ -674,8 +798,6 @@ public class frmTest { actions.add(new PopVlan()); actions.add(new Flood()); - actions.add(new Controller()); - Flow flow = new Flow(match, actions); flow.setPriority((short) 300); flow.setHardTimeout((short) 240); diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java index 969287719d..2b161e9be7 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java @@ -34,8 +34,7 @@ import org.opendaylight.controller.clustering.services.IClusterContainerServices import org.opendaylight.controller.hosttracker.IfIptoHost; public class Activator extends ComponentActivatorAbstractBase { - protected static final Logger logger = LoggerFactory - .getLogger(Activator.class); + protected static final Logger logger = LoggerFactory.getLogger(Activator.class); /** * Function called when the activator starts just after some initializations @@ -94,50 +93,32 @@ public class Activator extends ComponentActivatorAbstractBase { // export the service if (containerName.equals(GlobalConstants.DEFAULT.toString())) { - interfaces = new String[] { IContainerListener.class.getName(), - ISwitchManagerAware.class.getName(), - IForwardingRulesManager.class.getName(), - IInventoryListener.class.getName(), - ICacheUpdateAware.class.getName(), - IConfigurationContainerAware.class.getName(), + interfaces = new String[] { IContainerListener.class.getName(), ISwitchManagerAware.class.getName(), + IForwardingRulesManager.class.getName(), IInventoryListener.class.getName(), + ICacheUpdateAware.class.getName(), IConfigurationContainerAware.class.getName(), IFlowProgrammerListener.class.getName() }; } else { - interfaces = new String[] { - ISwitchManagerAware.class.getName(), - IForwardingRulesManager.class.getName(), - IInventoryListener.class.getName(), - ICacheUpdateAware.class.getName(), - IConfigurationContainerAware.class.getName(), + interfaces = new String[] { ISwitchManagerAware.class.getName(), + IForwardingRulesManager.class.getName(), IInventoryListener.class.getName(), + ICacheUpdateAware.class.getName(), IConfigurationContainerAware.class.getName(), IFlowProgrammerListener.class.getName() }; } c.setInterface(interfaces, props); - c.add(createContainerServiceDependency(containerName) - .setService(IFlowProgrammerService.class) - .setCallbacks("setFlowProgrammerService", - "unsetFlowProgrammerService").setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService(IFlowProgrammerService.class) + .setCallbacks("setFlowProgrammerService", "unsetFlowProgrammerService").setRequired(true)); - c.add(createContainerServiceDependency(containerName) - .setService(IClusterContainerServices.class) - .setCallbacks("setClusterContainerService", - "unsetClusterContainerService").setRequired(true)); - c.add(createContainerServiceDependency(containerName) - .setService(ISwitchManager.class) - .setCallbacks("setSwitchManager", "unsetSwitchManager") - .setRequired(true)); - c.add(createContainerServiceDependency(containerName) - .setService(IForwardingRulesManagerAware.class) - .setCallbacks("setFrmAware", "unsetFrmAware") - .setRequired(false)); - c.add(createContainerServiceDependency(containerName) - .setService(IfIptoHost.class) - .setCallbacks("setHostFinder", "unsetHostFinder") - .setRequired(true)); - c.add(createContainerServiceDependency(containerName) - .setService(IContainer.class) - .setCallbacks("setIContainer", "unsetIContainer") - .setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", "unsetClusterContainerService").setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService(ISwitchManager.class) + .setCallbacks("setSwitchManager", "unsetSwitchManager").setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService(IForwardingRulesManagerAware.class) + .setCallbacks("setFrmAware", "unsetFrmAware").setRequired(false)); + c.add(createContainerServiceDependency(containerName).setService(IfIptoHost.class) + .setCallbacks("setHostFinder", "unsetHostFinder").setRequired(true)); + c.add(createContainerServiceDependency(containerName).setService(IContainer.class) + .setCallbacks("setIContainer", "unsetIContainer").setRequired(true)); } } } diff --git a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java index db1186e6b7..e9c0edc3bd 100644 --- a/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java +++ b/opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java @@ -19,13 +19,14 @@ import java.util.Date; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.LinkedBlockingQueue; import org.eclipse.osgi.framework.console.CommandInterpreter; import org.eclipse.osgi.framework.console.CommandProvider; @@ -88,15 +89,13 @@ import org.slf4j.LoggerFactory; * the network. It also maintains the central repository of all the forwarding * rules installed on the network nodes. */ -public class ForwardingRulesManagerImpl implements IForwardingRulesManager, - PortGroupChangeListener, IContainerListener, ISwitchManagerAware, - IConfigurationContainerAware, IInventoryListener, IObjectReader, - ICacheUpdateAware, CommandProvider, - IFlowProgrammerListener { +public class ForwardingRulesManagerImpl implements IForwardingRulesManager, PortGroupChangeListener, + IContainerListener, ISwitchManagerAware, IConfigurationContainerAware, IInventoryListener, IObjectReader, + ICacheUpdateAware, CommandProvider, IFlowProgrammerListener { private static final String SAVE = "Save"; private static final String NODEDOWN = "Node is Down"; - private static final Logger log = LoggerFactory - .getLogger(ForwardingRulesManagerImpl.class); + private static final String SUCCESS = StatusCode.SUCCESS.toString(); + private static final Logger log = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class); private Map flowsSaveEvent; private String frmFileName; private String portGroupFileName; @@ -105,17 +104,26 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, private ConcurrentMap portGroupConfigs; private ConcurrentMap> portGroupData; private ConcurrentMap TSPolicies; - private boolean inContainerMode; // being used by default instance only + private boolean inContainerMode; // being used by global instance only + private boolean stopping; + /* - * Flow database. It's the software view of what was installed on the - * switch. It is indexed by node. For convenience a version indexed by group - * name is also maintained. The core element is a class which contains the - * flow entry pushed by the functional modules and the respective container - * flow merged version. In absence of container flows, the two flow entries - * are the same. + * Flow database. It's the software view of what was requested to install + * and what is installed on the switch. It is indexed by the entry itself. + * The entry's hashcode resumes the network node index, the flow's priority + * and the flow's match. The value element is a class which contains the + * flow entry pushed by the applications modules and the respective + * container flow merged version. In absence of container flows, the two + * flow entries are the same. */ - private ConcurrentMap> nodeFlows; - private ConcurrentMap> groupFlows; + private ConcurrentMap originalSwView; + private ConcurrentMap installedSwView; + /* + * Per node and per group indexing + */ + private ConcurrentMap> nodeFlows; + private ConcurrentMap> groupFlows; + /* * Inactive flow list. This is for the global instance of FRM It will * contain all the flow entries which were installed on the global container @@ -130,6 +138,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, private IFlowProgrammerService programmer; private IClusterContainerServices clusterContainerService = null; private ISwitchManager switchManager; + private Thread frmEventHandler; + protected BlockingQueue pendingEvents; /** * Adds a flow entry onto the network node It runs various validity checks @@ -140,8 +150,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * the original flow entry application requested to add * @param async * the flag indicating if this is a asynchronous request - * @return the status of this request. In case of asynchronous call, it - * will contain the unique id assigned to this request + * @return the status of this request. In case of asynchronous call, it will + * contain the unique id assigned to this request */ private Status addEntry(FlowEntry flowEntry, boolean async) { @@ -157,8 +167,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * Derive the container flow merged entries to install In presence of N * container flows, we may end up with N different entries to install... */ - List toInstallList = deriveInstallEntries( - flowEntry.clone(), container.getContainerFlows()); + List toInstallList = deriveInstallEntries(flowEntry.clone(), container.getContainerFlows()); // Container Flow conflict Check if (toInstallList.isEmpty()) { @@ -173,9 +182,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, for (FlowEntryInstall entry : toInstallList) { // Conflict Check: Verify new entry would not overwrite existing // ones - if (findMatch(entry.getInstall(), false) != null) { - log.warn("Operation Rejected: A flow with same match " - + "and priority exists on the target node"); + if (this.installedSwView.containsKey(entry)) { + log.warn("Operation Rejected: A flow with same match and priority exists on the target node"); log.trace("Aborting to install {}", entry); continue; } @@ -185,8 +193,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Declare failure if all the container flow merged entries clash with // existing entries if (toInstallSafe.size() == 0) { - String msg = "A flow with same match and priority exists " - + "on the target node"; + String msg = "A flow with same match and priority exists on the target node"; String logMsg = msg + ": {}"; log.warn(logMsg, flowEntry); return new Status(StatusCode.CONFLICT, msg); @@ -204,16 +211,15 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, if (ret.isSuccess()) { oneSucceded = true; /* - * The first successful status response will be returned - * For the asynchronous call, we can discard the container flow - * complication for now and assume we will always deal with - * one flow only per request + * The first successful status response will be returned For the + * asynchronous call, we can discard the container flow + * complication for now and assume we will always deal with one + * flow only per request */ succeded = ret; } else { error = ret; - log.warn("Failed to install the entry: {}. The failure is: {}", - installEntry, ret.getDescription()); + log.warn("Failed to install the entry: {}. The failure is: {}", installEntry, ret.getDescription()); } } @@ -234,13 +240,10 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * @return the list of container flow merged entries good to be installed on * this container */ - private List deriveInstallEntries(FlowEntry request, - List cFlowList) { - List toInstallList = new ArrayList( - 1); + private List deriveInstallEntries(FlowEntry request, List cFlowList) { + List toInstallList = new ArrayList(1); - if (container.getContainerFlows() == null - || container.getContainerFlows().isEmpty()) { + if (container.getContainerFlows() == null || container.getContainerFlows().isEmpty()) { // No container flows => entry good to be installed unchanged toInstallList.add(new FlowEntryInstall(request.clone(), null)); } else { @@ -249,8 +252,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // created for (ContainerFlow cFlow : container.getContainerFlows()) { if (cFlow.allowsFlow(request.getFlow())) { - toInstallList.add(new FlowEntryInstall(request.clone(), - cFlow)); + toInstallList.add(new FlowEntryInstall(request.clone(), cFlow)); } } } @@ -265,25 +267,22 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * @param newFlowEntry * @param async * the flag indicating if this is a asynchronous request - * @return the status of this request. In case of asynchronous call, it - * will contain the unique id assigned to this request + * @return the status of this request. In case of asynchronous call, it will + * contain the unique id assigned to this request */ - private Status modifyEntry(FlowEntry currentFlowEntry, - FlowEntry newFlowEntry, boolean async) { - + private Status modifyEntry(FlowEntry currentFlowEntry, FlowEntry newFlowEntry, boolean async) { Status retExt; // Sanity checks - if (currentFlowEntry == null || currentFlowEntry.getNode() == null - || newFlowEntry == null || newFlowEntry.getNode() == null) { + if (currentFlowEntry == null || currentFlowEntry.getNode() == null || newFlowEntry == null + || newFlowEntry.getNode() == null) { String msg = "Modify: Invalid FlowEntry"; String logMsg = msg + ": {} or {}"; log.warn(logMsg, currentFlowEntry, newFlowEntry); return new Status(StatusCode.NOTACCEPTABLE, msg); } if (!currentFlowEntry.getNode().equals(newFlowEntry.getNode()) - || !currentFlowEntry.getFlowName().equals( - newFlowEntry.getFlowName())) { + || !currentFlowEntry.getFlowName().equals(newFlowEntry.getFlowName())) { String msg = "Modify: Incompatible Flow Entries"; String logMsg = msg + ": {} and {}"; log.warn(logMsg, currentFlowEntry, newFlowEntry); @@ -291,38 +290,34 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } // Equality Check - if (currentFlowEntry.equals(newFlowEntry)) { + if (currentFlowEntry.getFlow().equals(newFlowEntry.getFlow())) { String msg = "Modify skipped as flows are the same"; String logMsg = msg + ": {} and {}"; log.debug(logMsg, currentFlowEntry, newFlowEntry); return new Status(StatusCode.SUCCESS, msg); } - // Conflict Check: Verify the new entry would not conflict with another - // existing one - // This is a loose check on the previous original flow entry requests. - // No check - // on the container flow merged flow entries (if any) yet - FlowEntryInstall sameMatchOriginalEntry = findMatch(newFlowEntry, true); - if (sameMatchOriginalEntry != null - && !sameMatchOriginalEntry.getOriginal().equals( - currentFlowEntry)) { - String msg = "Operation Rejected: Another flow with same match " - + "and priority exists on the target node"; + /* + * Conflict Check: Verify the new entry would not conflict with an + * existing one. This is a loose check on the previous original flow + * entry requests. No check on the container flow merged flow entries + * (if any) yet + */ + FlowEntry sameMatchOriginalEntry = originalSwView.get(newFlowEntry); + if (sameMatchOriginalEntry != null && !sameMatchOriginalEntry.equals(currentFlowEntry)) { + String msg = "Operation Rejected: Another flow with same match and priority exists on the target node"; String logMsg = msg + ": {}"; log.warn(logMsg, currentFlowEntry); return new Status(StatusCode.CONFLICT, msg); } // Derive the installed and toInstall entries - List installedList = deriveInstallEntries( - currentFlowEntry.clone(), container.getContainerFlows()); - List toInstallList = deriveInstallEntries( - newFlowEntry.clone(), container.getContainerFlows()); + List installedList = deriveInstallEntries(currentFlowEntry.clone(), + container.getContainerFlows()); + List toInstallList = deriveInstallEntries(newFlowEntry.clone(), container.getContainerFlows()); if (toInstallList.isEmpty()) { - String msg = "Modify Operation Rejected: The new entry " - + "conflicts with all the container flows"; + String msg = "Modify Operation Rejected: The new entry conflicts with all the container flows"; String logMsg = msg + ": {}"; log.warn(logMsg, newFlowEntry); log.warn(msg); @@ -354,14 +349,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } List toInstallSafe = new ArrayList(); for (FlowEntryInstall installEntry : toInstallList) { - // Conflict Check: Verify the new entry would not overwrite another - // existing one - FlowEntryInstall sameMatchEntry = findMatch( - installEntry.getInstall(), false); - if (sameMatchEntry != null - && !sameMatchEntry.getOriginal().equals(currentFlowEntry)) { - log.info("Modify: new container flow merged flow entry " - + "clashes with existing flow"); + /* + * Conflict Check: Verify the new entry would not overwrite another + * existing one + */ + FlowEntryInstall sameMatchEntry = installedSwView.get(installEntry); + if (sameMatchEntry != null && !sameMatchEntry.getOriginal().equals(currentFlowEntry)) { + log.info("Modify: new container flow merged flow entry clashes with existing flow"); decouple = true; } else { toInstallSafe.add(installEntry); @@ -394,8 +388,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, int size = toInstallList.size(); while (i < size) { // Modify and update database - retModify = modifyEntryInternal(installedList.get(i), - toInstallList.get(i), async); + retModify = modifyEntryInternal(installedList.get(i), toInstallList.get(i), async); if (retModify.isSuccess()) { i++; } else { @@ -404,14 +397,12 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } // Check if uncompleted modify if (i < size) { - log.warn("Unable to perform a complete modify for all " - + "the container flows merged entries"); + log.warn("Unable to perform a complete modify for all the container flows merged entries"); // Restore original entries int j = 0; while (j < i) { log.info("Attempting to restore initial entries"); - retExt = modifyEntryInternal(toInstallList.get(i), - installedList.get(i), async); + retExt = modifyEntryInternal(toInstallList.get(i), installedList.get(i), async); if (retExt.isSuccess()) { j++; } else { @@ -428,10 +419,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, succeeded = retModify; } /* - * The first successful status response will be returned. - * For the asynchronous call, we can discard the container flow - * complication for now and assume we will always deal with - * one flow only per request + * The first successful status response will be returned. For the + * asynchronous call, we can discard the container flow complication for + * now and assume we will always deal with one flow only per request */ return succeeded; } @@ -445,30 +435,22 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * @param newEntries * @param async * the flag indicating if this is a asynchronous request - * @return the status of this request. In case of asynchronous call, it - * will contain the unique id assigned to this request + * @return the status of this request. In case of asynchronous call, it will + * contain the unique id assigned to this request */ - private Status modifyEntryInternal(FlowEntryInstall currentEntries, - FlowEntryInstall newEntries, boolean async) { + private Status modifyEntryInternal(FlowEntryInstall currentEntries, FlowEntryInstall newEntries, boolean async) { // Modify the flow on the network node - Status status = (async)? - programmer.modifyFlowAsync(currentEntries.getNode(), - currentEntries.getInstall().getFlow(), newEntries.getInstall() - .getFlow()) : - programmer.modifyFlow(currentEntries.getNode(), - currentEntries.getInstall().getFlow(), newEntries.getInstall() - .getFlow()); - + Status status = (async) ? programmer.modifyFlowAsync(currentEntries.getNode(), currentEntries.getInstall() + .getFlow(), newEntries.getInstall().getFlow()) : programmer.modifyFlow(currentEntries.getNode(), + currentEntries.getInstall().getFlow(), newEntries.getInstall().getFlow()); if (!status.isSuccess()) { - log.warn( - "SDN Plugin failed to program the flow: {}. The failure is: {}", - newEntries.getInstall(), status.getDescription()); + log.warn("SDN Plugin failed to program the flow: {}. The failure is: {}", newEntries.getInstall(), + status.getDescription()); return status; } - log.trace("Modified {} => {}", currentEntries.getInstall(), - newEntries.getInstall()); + log.trace("Modified {} => {}", currentEntries.getInstall(), newEntries.getInstall()); // Update DB newEntries.setRequestId(status.getRequestId()); @@ -483,13 +465,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * (entry or node not present), it return successfully * * @param flowEntry - * the flow entry to remove + * the flow entry to remove * @param async * the flag indicating if this is a asynchronous request - * @return the status of this request. In case of asynchronous call, it - * will contain the unique id assigned to this request + * @return the status of this request. In case of asynchronous call, it will + * contain the unique id assigned to this request */ - private synchronized Status removeEntry(FlowEntry flowEntry, boolean async) { + private Status removeEntry(FlowEntry flowEntry, boolean async) { Status error = new Status(null, null); // Sanity Check @@ -501,20 +483,12 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } // Derive the container flows merged installed entries - List installedList = deriveInstallEntries( - flowEntry.clone(), container.getContainerFlows()); + List installedList = deriveInstallEntries(flowEntry.clone(), container.getContainerFlows()); - Set flowsOnNode = nodeFlows.get(flowEntry.getNode()); Status succeeded = null; boolean atLeastOneRemoved = false; for (FlowEntryInstall entry : installedList) { - if (flowsOnNode == null) { - String msg = "Removal skipped (Node down) for flow entry"; - String logMsg = msg + ": {}"; - log.debug(logMsg, flowEntry); - return new Status(StatusCode.SUCCESS, msg); - } - if (!flowsOnNode.contains(entry)) { + if (!installedSwView.containsKey(entry)) { String logMsg = "Removal skipped (not present in software view) for flow entry: {}"; log.debug(logMsg, flowEntry); if (installedList.size() == 1) { @@ -530,8 +504,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, if (!ret.isSuccess()) { error = ret; - log.warn("Failed to remove the entry: {}. The failure is: {}", - entry.getInstall(), ret.getDescription()); + log.warn("Failed to remove the entry: {}. The failure is: {}", entry.getInstall(), ret.getDescription()); if (installedList.size() == 1) { // If we had only one entry to remove, this is fatal failure return error; @@ -559,25 +532,20 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * the flow entry to remove * @param async * the flag indicating if this is a asynchronous request - * @return the status of this request. In case of asynchronous call, it - * will contain the unique id assigned to this request + * @return the status of this request. In case of asynchronous call, it will + * contain the unique id assigned to this request */ private Status removeEntryInternal(FlowEntryInstall entry, boolean async) { // Mark the entry to be deleted (for CC just in case we fail) entry.toBeDeleted(); // Remove from node - Status status = (async)? - programmer.removeFlowAsync(entry.getNode(), entry - .getInstall().getFlow()) : - programmer.removeFlow(entry.getNode(), entry - .getInstall().getFlow()); - + Status status = (async) ? programmer.removeFlowAsync(entry.getNode(), entry.getInstall().getFlow()) + : programmer.removeFlow(entry.getNode(), entry.getInstall().getFlow()); if (!status.isSuccess()) { - log.warn( - "SDN Plugin failed to program the flow: {}. The failure is: {}", - entry.getInstall(), status.getDescription()); + log.warn("SDN Plugin failed to program the flow: {}. The failure is: {}", entry.getInstall(), + status.getDescription()); return status; } log.trace("Removed {}", entry.getInstall()); @@ -598,22 +566,17 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * the flow entry to install * @param async * the flag indicating if this is a asynchronous request - * @return the status of this request. In case of asynchronous call, it - * will contain the unique id assigned to this request + * @return the status of this request. In case of asynchronous call, it will + * contain the unique id assigned to this request */ private Status addEntriesInternal(FlowEntryInstall entry, boolean async) { // Install the flow on the network node - Status status = (async)? - programmer.addFlowAsync(entry.getNode(), entry.getInstall() - .getFlow()) : - programmer.addFlow(entry.getNode(), entry.getInstall() - .getFlow()); - + Status status = (async) ? programmer.addFlowAsync(entry.getNode(), entry.getInstall().getFlow()) : programmer + .addFlow(entry.getNode(), entry.getInstall().getFlow()); if (!status.isSuccess()) { - log.warn( - "SDN Plugin failed to program the flow: {}. The failure is: {}", - entry.getInstall(), status.getDescription()); + log.warn("SDN Plugin failed to program the flow: {}. The failure is: {}", entry.getInstall(), + status.getDescription()); return status; } @@ -655,8 +618,10 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return true; } - private synchronized void updateLocalDatabase(FlowEntryInstall entry, - boolean add) { + private void updateLocalDatabase(FlowEntryInstall entry, boolean add) { + // Update the software view + updateSwViewes(entry, add); + // Update node indexed flow database updateNodeFlowsDB(entry, add); @@ -667,28 +632,42 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, /* * Update the node mapped flows database */ - private synchronized void updateNodeFlowsDB(FlowEntryInstall flowEntries, boolean add) { + private void updateSwViewes(FlowEntryInstall flowEntries, boolean add) { + if (add) { + originalSwView.put(flowEntries.getOriginal(), flowEntries.getOriginal()); + installedSwView.put(flowEntries, flowEntries); + } else { + originalSwView.remove(flowEntries.getOriginal()); + installedSwView.remove(flowEntries); + } + } + + /* + * Update the node mapped flows database + */ + private void updateNodeFlowsDB(FlowEntryInstall flowEntries, boolean add) { Node node = flowEntries.getNode(); - Set flowEntrylist = this.nodeFlows.get(node); - if (flowEntrylist == null) { - if (add == false) { + List nodeIndeces = this.nodeFlows.get(node); + if (nodeIndeces == null) { + if (!add) { return; } else { - flowEntrylist = new HashSet(); + nodeIndeces = new ArrayList(); } } - if (add == true) { - flowEntrylist.add(flowEntries); + if (add) { + nodeIndeces.add(flowEntries); } else { - flowEntrylist.remove(flowEntries); + nodeIndeces.remove(flowEntries); } - if (flowEntrylist.isEmpty()) { + // Update cache across cluster + if (nodeIndeces.isEmpty()) { this.nodeFlows.remove(node); } else { - this.nodeFlows.put(node, flowEntrylist); + this.nodeFlows.put(node, nodeIndeces); } } @@ -696,53 +675,33 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * Update the group name mapped flows database */ private void updateGroupFlowsDB(FlowEntryInstall flowEntries, boolean add) { - Set flowList; - FlowEntryInstall exists = null; - String flowName = flowEntries.getFlowName(); String groupName = flowEntries.getGroupName(); - if (this.groupFlows == null) { - return; - } - // Flow may not be part of a group if (groupName == null) { return; } - if (this.groupFlows.containsKey(groupName)) { - flowList = this.groupFlows.get(groupName); - } else { - if (add == false) { + List indices = this.groupFlows.get(groupName); + if (indices == null) { + if (!add) { return; } else { - flowList = new HashSet(); - } - } - - for (FlowEntryInstall flow : flowList) { - if (flow.equalsByNodeAndName(flowEntries.getNode(), flowName)) { - exists = flow; - break; + indices = new ArrayList(); } } - if (exists == null && add == false) { - return; - } - - if (exists != null) { - flowList.remove(exists); - } - - if (add == true) { - flowList.add(flowEntries); + if (add) { + indices.add(flowEntries); + } else { + indices.remove(flowEntries); } - if (flowList.isEmpty()) { + // Update cache across cluster + if (indices.isEmpty()) { this.groupFlows.remove(groupName); } else { - this.groupFlows.put(groupName, flowList); + this.groupFlows.put(groupName, indices); } } @@ -751,11 +710,11 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * entry is effectively present in the local database */ @SuppressWarnings("unused") - private synchronized Status removeEntry(Node node, String flowName) { + private Status removeEntry(Node node, String flowName) { FlowEntryInstall target = null; // Find in database - for (FlowEntryInstall entry : this.nodeFlows.get(node)) { + for (FlowEntryInstall entry : installedSwView.values()) { if (entry.equalsByNodeAndName(node, flowName)) { target = entry; break; @@ -768,17 +727,15 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } // Remove from node - Status status = programmer.removeFlow(target.getNode(), target - .getInstall().getFlow()); + Status status = programmer.removeFlow(target.getNode(), target.getInstall().getFlow()); // Update DB if (status.isSuccess()) { updateLocalDatabase(target, false); } else { // log the error - log.warn( - "SDN Plugin failed to remove the flow: {}. The failure is: {}", - target.getInstall(), status.getDescription()); + log.warn("SDN Plugin failed to remove the flow: {}. The failure is: {}", target.getInstall(), + status.getDescription()); } return status; @@ -839,8 +796,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } @Override - public Status modifyFlowEntry(FlowEntry currentFlowEntry, - FlowEntry newFlowEntry) { + public Status modifyFlowEntry(FlowEntry currentFlowEntry, FlowEntry newFlowEntry) { Status status = null; if (inContainerMode) { String msg = "Controller in container mode: Modify Refused"; @@ -869,79 +825,98 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public Status modifyOrAddFlowEntry(FlowEntry newFlowEntry) { /* - * Run a loose check on the installed entries to decide whether to go - * with a add or modify method. A loose check means only check against - * the original flow entry requests and not against the installed flow + * Run a check on the original entries to decide whether to go with a + * add or modify method. A loose check means only check against the + * original flow entry requests and not against the installed flow * entries which are the result of the original entry merged with the * container flow(s) (if any). The modifyFlowEntry method in presence of * conflicts with the Container flows (if any) would revert back to a * delete + add pattern */ - FlowEntryInstall currentFlowEntries = findMatch(newFlowEntry, true); + FlowEntry currentFlowEntry = originalSwView.get(newFlowEntry); - if (currentFlowEntries != null) { - return modifyFlowEntry(currentFlowEntries.getOriginal(), - newFlowEntry); + if (currentFlowEntry != null) { + return modifyFlowEntry(currentFlowEntry, newFlowEntry); } else { return installFlowEntry(newFlowEntry); } } @Override - public Status modifyOrAddFlowEntryAsync(FlowEntry newone) { + public Status modifyOrAddFlowEntryAsync(FlowEntry newFlowEntry) { /* - * Run a loose check on the installed entries to decide whether to go - * with a add or modify method. A loose check means only check against - * the original flow entry requests and not against the installed flow + * Run a check on the original entries to decide whether to go with a + * add or modify method. A loose check means only check against the + * original flow entry requests and not against the installed flow * entries which are the result of the original entry merged with the * container flow(s) (if any). The modifyFlowEntry method in presence of * conflicts with the Container flows (if any) would revert back to a * delete + add pattern */ - FlowEntryInstall currentFlowEntries = findMatch(newone, true); + FlowEntry currentFlowEntry = originalSwView.get(newFlowEntry); - if (currentFlowEntries != null) { - return modifyFlowEntryAsync(currentFlowEntries.getOriginal(), - newone); + if (currentFlowEntry != null) { + return modifyFlowEntryAsync(currentFlowEntry, newFlowEntry); } else { - return installFlowEntryAsync(newone); + return installFlowEntryAsync(newFlowEntry); } } - - /** - * Try to find in the database if a Flow with the same Match and priority of - * the passed one already exists for the specified network node. Flow, - * priority and network node are all specified in the FlowEntry If found, - * the respective FlowEntryInstall Object is returned - * - * @param flowEntry - * the FlowEntry to be tested against the ones installed - * @param looseCheck - * if true, the function will run the check against the original - * flow entry portion of the installed entries - * @return null if not found, otherwise the FlowEntryInstall which contains - * the existing flow entry - */ - private synchronized FlowEntryInstall findMatch(FlowEntry flowEntry, boolean looseCheck) { - Flow flow = flowEntry.getFlow(); - Match match = flow.getMatch(); - short priority = flow.getPriority(); - Set thisNodeList = nodeFlows.get(flowEntry.getNode()); - - if (thisNodeList != null) { - for (FlowEntryInstall flowEntries : thisNodeList) { - flow = (looseCheck == false) ? flowEntries.getInstall() - .getFlow() : flowEntries.getOriginal().getFlow(); - if (flow.getMatch().equals(match) - && flow.getPriority() == priority) { - return flowEntries; + @Override + public Status uninstallFlowEntryGroup(String groupName) { + if (groupName == null || groupName.isEmpty()) { + return new Status(StatusCode.BADREQUEST, "Invalid group name"); + } + if (groupName.equals(FlowConfig.internalStaticFlowsGroup)) { + return new Status(StatusCode.BADREQUEST, "Static flows group cannot be deleted through this api"); + } + if (inContainerMode) { + String msg = "Controller in container mode: Group Uninstall Refused"; + String logMsg = msg + ": {}"; + log.warn(logMsg, groupName); + return new Status(StatusCode.NOTACCEPTABLE, msg); + } + int toBeRemoved = groupFlows.get(groupName).size(); + String error = ""; + if (groupFlows.containsKey(groupName)) { + List list = new ArrayList(groupFlows.get(groupName)); + for (FlowEntryInstall entry : list) { + Status status = this.removeEntry(entry.getOriginal(), false); + if (status.isSuccess()) { + toBeRemoved -= 1; + } else { + error = status.getDescription(); } } } - return null; + return (toBeRemoved == 0) ? new Status(StatusCode.SUCCESS) : new Status(StatusCode.INTERNALERROR, + "Not all the flows were removed: " + error); + } + + @Override + public Status uninstallFlowEntryGroupAsync(String groupName) { + if (groupName == null || groupName.isEmpty()) { + return new Status(StatusCode.BADREQUEST, "Invalid group name"); + } + if (groupName.equals(FlowConfig.internalStaticFlowsGroup)) { + return new Status(StatusCode.BADREQUEST, "Static flows group cannot be deleted through this api"); + } + if (inContainerMode) { + String msg = "Controller in container mode: Group Uninstall Refused"; + String logMsg = msg + ": {}"; + log.warn(logMsg, groupName); + return new Status(StatusCode.NOTACCEPTABLE, msg); + } + if (groupFlows.containsKey(groupName)) { + List list = new ArrayList(groupFlows.get(groupName)); + for (FlowEntryInstall entry : list) { + this.removeEntry(entry.getOriginal(), true); + } + } + return new Status(StatusCode.SUCCESS); } + @Override public boolean checkFlowEntryConflict(FlowEntry flowEntry) { return entryConflictsWithContainerFlows(flowEntry); } @@ -953,39 +928,26 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * merged flow may conflict with an existing old container flows merged flow * on the network node */ - private synchronized void updateFlowsContainerFlow() { - List oldCouples = new ArrayList(); - List toReinstall = new ArrayList(); - for (Entry> entry : this.nodeFlows - .entrySet()) { - oldCouples.clear(); - toReinstall.clear(); - if (entry.getValue() == null) { - continue; - } - // Create a set of old entries and one of original entries to be - // reinstalled - for (FlowEntryInstall oldCouple : entry.getValue()) { - oldCouples.add(oldCouple); - toReinstall.add(oldCouple.getOriginal()); - } + private void updateFlowsContainerFlow() { + for (ConcurrentMap.Entry entry : installedSwView.entrySet()) { + FlowEntryInstall current = entry.getValue(); + FlowEntry reInstall = current.getOriginal(); // Remove the old couples. No validity checks to be run, use the // internal remove - for (FlowEntryInstall oldCouple : oldCouples) { - this.removeEntryInternal(oldCouple, false); - } + this.removeEntryInternal(current, false); + // Reinstall the original flow entries, via the regular path: new // cFlow merge + validations - for (FlowEntry flowEntry : toReinstall) { - this.installFlowEntry(flowEntry); - } + this.installFlowEntry(reInstall); } } public void nonClusterObjectCreate() { - nodeFlows = new ConcurrentHashMap>(); + originalSwView = new ConcurrentHashMap(); + installedSwView = new ConcurrentHashMap(); + nodeFlows = new ConcurrentHashMap>(); + groupFlows = new ConcurrentHashMap>(); TSPolicies = new ConcurrentHashMap(); - groupFlows = new ConcurrentHashMap>(); staticFlowsOrdinal = new ConcurrentHashMap(); portGroupConfigs = new ConcurrentHashMap(); portGroupData = new ConcurrentHashMap>(); @@ -995,10 +957,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } private void registerWithOSGIConsole() { - BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()) - .getBundleContext(); - bundleContext.registerService(CommandProvider.class.getName(), this, - null); + BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); + bundleContext.registerService(CommandProvider.class.getName(), this, null); } @Override @@ -1042,21 +1002,20 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public List getFlowEntriesForGroup(String policyName) { List list = new ArrayList(); - if (this.groupFlows != null && this.groupFlows.containsKey(policyName)) { - for (FlowEntryInstall entries : groupFlows.get(policyName)) { - list.add(entries.getOriginal()); + if (policyName != null && !policyName.trim().isEmpty()) { + for (Map.Entry entry : this.originalSwView.entrySet()) { + if (policyName.equals(entry.getKey().getGroupName())) { + list.add(entry.getKey().clone()); + } } } return list; } @Override - public synchronized void addOutputPort(Node node, String flowName, - List portList) { - - Set flowEntryList = this.nodeFlows.get(node); + public void addOutputPort(Node node, String flowName, List portList) { - for (FlowEntryInstall flow : flowEntryList) { + for (FlowEntryInstall flow : this.nodeFlows.get(node)) { if (flow.getFlowName().equals(flowName)) { FlowEntry currentFlowEntry = flow.getOriginal(); FlowEntry newFlowEntry = currentFlowEntry.clone(); @@ -1065,28 +1024,21 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } Status error = modifyEntry(currentFlowEntry, newFlowEntry, false); if (error.isSuccess()) { - log.info("Ports {} added to FlowEntry {}", portList, - flowName); + log.info("Ports {} added to FlowEntry {}", portList, flowName); } else { - log.warn( - "Failed to add ports {} to Flow entry {}. The failure is: {}", - portList, currentFlowEntry.toString(), - error.getDescription()); + log.warn("Failed to add ports {} to Flow entry {}. The failure is: {}", portList, + currentFlowEntry.toString(), error.getDescription()); } return; } } - log.warn("Failed to add ports to Flow {} on Node {}: Entry Not Found", - flowName, node); + log.warn("Failed to add ports to Flow {} on Node {}: Entry Not Found", flowName, node); } @Override - public synchronized void removeOutputPort(Node node, String flowName, - List portList) { - - Set flowEntryList = this.nodeFlows.get(node); - - for (FlowEntryInstall flow : flowEntryList) { + public void removeOutputPort(Node node, String flowName, List portList) { + for (FlowEntryInstall index : this.nodeFlows.get(node)) { + FlowEntryInstall flow = this.installedSwView.get(index); if (flow.getFlowName().equals(flowName)) { FlowEntry currentFlowEntry = flow.getOriginal(); FlowEntry newFlowEntry = currentFlowEntry.clone(); @@ -1096,43 +1048,35 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } Status status = modifyEntry(currentFlowEntry, newFlowEntry, false); if (status.isSuccess()) { - log.info("Ports {} removed from FlowEntry {}", portList, - flowName); + log.info("Ports {} removed from FlowEntry {}", portList, flowName); } else { - log.warn( - "Failed to remove ports {} from Flow entry {}. The failure is: {}", - portList, currentFlowEntry.toString(), - status.getDescription()); + log.warn("Failed to remove ports {} from Flow entry {}. The failure is: {}", portList, + currentFlowEntry.toString(), status.getDescription()); } return; } } - log.warn( - "Failed to remove ports from Flow {} on Node {}: Entry Not Found", - flowName, node); + log.warn("Failed to remove ports from Flow {} on Node {}: Entry Not Found", flowName, node); } /* * This function assumes the target flow has only one output port */ @Override - public synchronized void replaceOutputPort(Node node, String flowName, - NodeConnector outPort) { + public void replaceOutputPort(Node node, String flowName, NodeConnector outPort) { FlowEntry currentFlowEntry = null; FlowEntry newFlowEntry = null; - Set flowEntryList = this.nodeFlows.get(node); // Find the flow - for (FlowEntryInstall flow : flowEntryList) { + for (FlowEntryInstall index : this.nodeFlows.get(node)) { + FlowEntryInstall flow = this.installedSwView.get(index); if (flow.getFlowName().equals(flowName)) { currentFlowEntry = flow.getOriginal(); break; } } if (currentFlowEntry == null) { - log.warn( - "Failed to replace output port for flow {} on node {}: Entry Not Found", - flowName, node); + log.warn("Failed to replace output port for flow {} on node {}: Entry Not Found", flowName, node); return; } @@ -1152,21 +1096,18 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, Status status = modifyEntry(currentFlowEntry, newFlowEntry, false); if (status.isSuccess()) { - log.info("Output port replaced with {} for flow {} on node {}", - outPort, flowName, node); + log.info("Output port replaced with {} for flow {} on node {}", outPort, flowName, node); } else { - log.warn( - "Failed to replace output port for flow {} on node {}. The failure is: {}", - flowName, node, status.getDescription()); + log.warn("Failed to replace output port for flow {} on node {}. The failure is: {}", flowName, node, + status.getDescription()); } return; } @Override - public synchronized NodeConnector getOutputPort(Node node, String flowName) { - Set flowEntryList = this.nodeFlows.get(node); - - for (FlowEntryInstall flow : flowEntryList) { + public NodeConnector getOutputPort(Node node, String flowName) { + for (FlowEntryInstall index : this.nodeFlows.get(node)) { + FlowEntryInstall flow = this.installedSwView.get(index); if (flow.getFlowName().equals(flowName)) { for (Action action : flow.getOriginal().getFlow().getActions()) { if (action.getType() == ActionType.OUTPUT) { @@ -1175,7 +1116,6 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } } - return null; } @@ -1194,6 +1134,12 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, log.debug("FRM allocateCaches for Container {}", container); try { + clusterContainerService.createCache("frm.originalSwView", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + + clusterContainerService.createCache("frm.installedSwView", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + clusterContainerService.createCache("frm.nodeFlows", EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); @@ -1219,9 +1165,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); } catch (CacheConfigException cce) { - log.error("FRM CacheConfigException", cce); + log.error("FRM CacheConfigException"); } catch (CacheExistException cce) { - log.error("FRM CacheExistException", cce); + log.error("FRM CacheExistException"); } } @@ -1236,104 +1182,82 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, log.debug("FRM retrieveCaches for Container {}", container); + map = clusterContainerService.getCache("frm.originalSwView"); + if (map != null) { + originalSwView = (ConcurrentMap) map; + } else { + log.error("FRM Cache frm.originalSwView allocation failed for Container {}", container.getName()); + } + + map = clusterContainerService.getCache("frm.installedSwView"); + if (map != null) { + installedSwView = (ConcurrentMap) map; + } else { + log.error("FRM Cache frm.installedSwView allocation failed for Container {}", container.getName()); + } + map = clusterContainerService.getCache("frm.nodeFlows"); if (map != null) { - nodeFlows = (ConcurrentMap>) map; + nodeFlows = (ConcurrentMap>) map; } else { - log.error( - "FRM Cache frm.nodeFlows allocation failed for Container {}", - container); + log.error("FRM Cache frm.nodeFlows allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.groupFlows"); if (map != null) { - groupFlows = (ConcurrentMap>) map; + groupFlows = (ConcurrentMap>) map; } else { - log.error( - "FRM Cache frm.groupFlows allocation failed for Container {}", - container); + log.error("FRM Cache frm.groupFlows allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.staticFlows"); if (map != null) { staticFlows = (ConcurrentMap) map; } else { - log.error( - "FRM Cache frm.staticFlows allocation failed for Container {}", - container); + log.error("FRM Cache frm.staticFlows allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.flowsSaveEvent"); if (map != null) { flowsSaveEvent = (ConcurrentMap) map; } else { - log.error( - "FRM Cache frm.flowsSaveEvent allocation failed for Container {}", - container); + log.error("FRM Cache frm.flowsSaveEvent allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.staticFlowsOrdinal"); if (map != null) { staticFlowsOrdinal = (ConcurrentMap) map; } else { - log.error( - "FRM Cache frm.staticFlowsOrdinal allocation failed for Container {}", - container); + log.error("FRM Cache frm.staticFlowsOrdinal allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.portGroupConfigs"); if (map != null) { portGroupConfigs = (ConcurrentMap) map; } else { - log.error( - "FRM Cache frm.portGroupConfigs allocation failed for Container {}", - container); + log.error("FRM Cache frm.portGroupConfigs allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.portGroupData"); if (map != null) { portGroupData = (ConcurrentMap>) map; } else { - log.error( - "FRM Cache frm.portGroupData allocation failed for Container {}", - container); + log.error("FRM Cache frm.portGroupData allocation failed for Container {}", container.getName()); } map = clusterContainerService.getCache("frm.TSPolicies"); if (map != null) { TSPolicies = (ConcurrentMap) map; } else { - log.error( - "FRM Cache frm.TSPolicies allocation failed for Container {}", - container); + log.error("FRM Cache frm.TSPolicies allocation failed for Container {}", container.getName()); } } - @SuppressWarnings("deprecation") - private void destroyCaches() { - if (this.clusterContainerService == null) { - log.warn("Un-initialized clusterContainerService, can't destroy cache"); - return; - } - - log.debug("FRM destroyCaches for Container {}", container); - clusterContainerService.destroyCache("frm.nodeFlows"); - clusterContainerService.destroyCache("frm.TSPolicies"); - clusterContainerService.destroyCache("frm.groupFlows"); - clusterContainerService.destroyCache("frm.staticFlows"); - clusterContainerService.destroyCache("frm.flowsSaveEvent"); - clusterContainerService.destroyCache("frm.staticFlowsOrdinal"); - clusterContainerService.destroyCache("frm.portGroupData"); - clusterContainerService.destroyCache("frm.portGroupConfigs"); - nonClusterObjectCreate(); - } - private boolean flowConfigExists(FlowConfig config) { - // As per customer requirement, flow name has to be unique on per node - // id basis - for (FlowConfig fc : staticFlows.values()) { - if (fc.isByNameAndNodeIdEqual(config)) { + // Flow name has to be unique on per node id basis + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + if (entry.getValue().isByNameAndNodeIdEqual(config)) { return true; } } @@ -1342,31 +1266,27 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public Status addStaticFlow(FlowConfig config, boolean restore) { - StringBuffer resultStr = new StringBuffer(); boolean multipleFlowPush = false; String error; Status status; - config.setStatus(StatusCode.SUCCESS.toString()); + config.setStatus(SUCCESS); + + // Skip validation check if we are trying to restore a saved config + if (!restore && !(status = config.validate(container)).isSuccess()) { + log.warn("Invalid Configuration for flow {}. The failure is {}", config, status.getDescription()); + error = "Invalid Configuration (" + status.getDescription() + ")"; + config.setStatus(error); + return new Status(StatusCode.BADREQUEST, error); + } // Presence check if (flowConfigExists(config)) { error = "Entry with this name on specified switch already exists"; - log.warn( - "Entry with this name on specified switch already exists: {}", - config); + log.warn("Entry with this name on specified switch already exists: {}", config); config.setStatus(error); return new Status(StatusCode.CONFLICT, error); } - // Skip validation check if we are trying to restore a saved config - if (!restore && !config.isValid(container, resultStr)) { - log.warn("Invalid Configuration for flow {}. The failure is {}", - config, resultStr.toString()); - error = "Invalid Configuration (" + resultStr.toString() + ")"; - config.setStatus(error); - return new Status(StatusCode.BADREQUEST, error); - } - if ((config.getIngressPort() == null) && config.getPortGroup() != null) { for (String portGroupName : portGroupConfigs.keySet()) { if (portGroupName.equalsIgnoreCase(config.getPortGroup())) { @@ -1375,9 +1295,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } if (!multipleFlowPush) { - log.warn( - "Invalid Configuration(Invalid PortGroup Name) for flow {}", - config); + log.warn("Invalid Configuration(Invalid PortGroup Name) for flow {}", config); error = "Invalid Configuration (Invalid PortGroup Name)"; config.setStatus(error); return new Status(StatusCode.BADREQUEST, error); @@ -1392,7 +1310,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Program hw if (config.installInHw()) { FlowEntry entry = config.getFlowEntry(); - status = this.addEntry(entry, false); + status = this.installFlowEntry(entry); if (!status.isSuccess()) { config.setStatus(status.getDescription()); if (!restore) { @@ -1421,8 +1339,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, staticFlows.put(ordinal, config); if (multipleFlowPush) { - PortGroupConfig pgconfig = portGroupConfigs.get(config - .getPortGroup()); + PortGroupConfig pgconfig = portGroupConfigs.get(config.getPortGroup()); Map existingData = portGroupData.get(pgconfig); if (existingData != null) { portGroupChanged(pgconfig, existingData, true); @@ -1432,19 +1349,20 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } private void addStaticFlowsToSwitch(Node node) { - for (FlowConfig config : staticFlows.values()) { + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + FlowConfig config = entry.getValue(); if (config.isPortGroupEnabled()) { continue; } if (config.getNode().equals(node)) { - if (config.installInHw() - && !config.getStatus().equals( - StatusCode.SUCCESS.toString())) { - Status status = this.addEntry(config.getFlowEntry(), false); + if (config.installInHw() && !config.getStatus().equals(SUCCESS)) { + Status status = this.installFlowEntryAsync(config.getFlowEntry()); config.setStatus(status.getDescription()); } } } + // Update cluster cache + refreshClusterStaticFlowsStatus(node); } private void updateStaticFlowConfigsOnNodeDown(Node node) { @@ -1472,30 +1390,36 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, for (Integer index : toRemove) { staticFlows.remove(index); } + // Update cluster cache + refreshClusterStaticFlowsStatus(node); + } private void updateStaticFlowConfigsOnContainerModeChange(UpdateType update) { - log.trace("Updating Static Flow configs on container mode change: {}", - update); + log.trace("Updating Static Flow configs on container mode change: {}", update); - for (FlowConfig config : staticFlows.values()) { + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + FlowConfig config = entry.getValue(); if (config.isPortGroupEnabled()) { continue; } - if (config.installInHw()) { + if (config.installInHw() && !config.isInternalFlow()) { switch (update) { case ADDED: config.setStatus("Removed from node because in container mode"); break; case REMOVED: - config.setStatus(StatusCode.SUCCESS.toString()); + config.setStatus(SUCCESS); break; default: } } } + // Update cluster cache + refreshClusterStaticFlowsStatus(null); } + @Override public Status removeStaticFlow(FlowConfig config) { /* * No config.isInternal() check as NB does not take this path and GUI @@ -1504,80 +1428,98 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * reactive, so that we can remove the internal generated LLDP and ARP * punt flows */ - for (Map.Entry entry : staticFlows.entrySet()) { + + // Look for the target configuration entry + Integer key = 0; + FlowConfig target = null; + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { if (entry.getValue().isByNameAndNodeIdEqual(config)) { - // Program the network node - Status status = this.removeEntry(config.getFlowEntry(), false); - // Update configuration database if programming was successful - if (status.isSuccess()) { - staticFlows.remove(entry.getKey()); - return status; - } else { - entry.getValue().setStatus(status.getDescription()); - return status; - } + key = entry.getKey(); + target = entry.getValue(); + break; } } - return new Status(StatusCode.NOTFOUND, "Entry Not Present"); + if (target == null) { + return new Status(StatusCode.NOTFOUND, "Entry Not Present"); + } + + // Program the network node + Status status = this.removeEntry(config.getFlowEntry(), false); + + // Update configuration database if programming was successful + if (status.isSuccess()) { + staticFlows.remove(key); + } + + return status; } @Override public Status removeStaticFlow(String name, Node node) { - for (Map.Entry mapEntry : staticFlows.entrySet()) { - FlowConfig entry = mapEntry.getValue(); - Status status = new Status(null, null); - if (entry.isByNameAndNodeIdEqual(name, node)) { - // Validity check for api3 entry point - if (entry.isInternalFlow()) { - String msg = "Invalid operation: Controller generated " - + "flow cannot be deleted"; - String logMsg = msg + ": {}"; - log.warn(logMsg, name); - return new Status(StatusCode.NOTACCEPTABLE, msg); - } - if (!entry.isPortGroupEnabled()) { - // Program the network node - status = this.removeEntry(entry.getFlowEntry(), false); - } - // Update configuration database if programming was successful - if (status.isSuccess()) { - staticFlows.remove(mapEntry.getKey()); - return status; - } else { - entry.setStatus(status.getDescription()); - return status; - } + // Look for the target configuration entry + Integer key = 0; + FlowConfig target = null; + for (ConcurrentMap.Entry mapEntry : staticFlows.entrySet()) { + if (mapEntry.getValue().isByNameAndNodeIdEqual(name, node)) { + key = mapEntry.getKey(); + target = mapEntry.getValue(); + break; } } - return new Status(StatusCode.NOTFOUND, "Entry Not Present"); + if (target == null) { + return new Status(StatusCode.NOTFOUND, "Entry Not Present"); + } + + // Validity check for api3 entry point + if (target.isInternalFlow()) { + String msg = "Invalid operation: Controller generated flow cannot be deleted"; + String logMsg = msg + ": {}"; + log.warn(logMsg, name); + return new Status(StatusCode.NOTACCEPTABLE, msg); + } + + if (target.isPortGroupEnabled()) { + String msg = "Invalid operation: Port Group flows cannot be deleted through this API"; + String logMsg = msg + ": {}"; + log.warn(logMsg, name); + return new Status(StatusCode.NOTACCEPTABLE, msg); + } + + // Program the network node + Status status = this.removeEntry(target.getFlowEntry(), false); + + // Update configuration database if programming was successful + if (status.isSuccess()) { + staticFlows.remove(key); + } + + return status; } + @Override public Status modifyStaticFlow(FlowConfig newFlowConfig) { // Validity check for api3 entry point if (newFlowConfig.isInternalFlow()) { - String msg = "Invalid operation: Controller generated flow " - + "cannot be modified"; + String msg = "Invalid operation: Controller generated flow cannot be modified"; String logMsg = msg + ": {}"; log.warn(logMsg, newFlowConfig); return new Status(StatusCode.NOTACCEPTABLE, msg); } // Validity Check - StringBuffer resultStr = new StringBuffer(); - if (!newFlowConfig.isValid(container, resultStr)) { - String msg = "Invalid Configuration (" + resultStr.toString() + ")"; + Status status = newFlowConfig.validate(container); + if (!status.isSuccess()) { + String msg = "Invalid Configuration (" + status.getDescription() + ")"; newFlowConfig.setStatus(msg); - log.warn("Invalid Configuration for flow {}. The failure is {}", - newFlowConfig, resultStr.toString()); + log.warn("Invalid Configuration for flow {}. The failure is {}", newFlowConfig, status.getDescription()); return new Status(StatusCode.BADREQUEST, msg); } FlowConfig oldFlowConfig = null; Integer index = null; - for (Map.Entry mapEntry : staticFlows.entrySet()) { + for (ConcurrentMap.Entry mapEntry : staticFlows.entrySet()) { FlowConfig entry = mapEntry.getValue(); - if (entry.isByNameAndNodeIdEqual(newFlowConfig.getName(), - newFlowConfig.getNode())) { + if (entry.isByNameAndNodeIdEqual(newFlowConfig.getName(), newFlowConfig.getNode())) { oldFlowConfig = entry; index = mapEntry.getKey(); break; @@ -1594,17 +1536,14 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, // Do not attempt to reinstall the flow, warn user if (newFlowConfig.equals(oldFlowConfig)) { String msg = "No modification detected"; - log.info( - "Static flow modification skipped. New flow and old flow are the same: {}", - newFlowConfig); + log.info("Static flow modification skipped. New flow and old flow are the same: {}", newFlowConfig); return new Status(StatusCode.SUCCESS, msg); } // If flow is installed, program the network node - Status status = new Status(StatusCode.SUCCESS, "Saved in config"); + status = new Status(StatusCode.SUCCESS, "Saved in config"); if (oldFlowConfig.installInHw()) { - status = this.modifyEntry(oldFlowConfig.getFlowEntry(), - newFlowConfig.getFlowEntry(), false); + status = this.modifyEntry(oldFlowConfig.getFlowEntry(), newFlowConfig.getFlowEntry(), false); } // Update configuration database if programming was successful @@ -1630,51 +1569,73 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } // Validity check for api3 entry point if (config.isInternalFlow()) { - String msg = "Invalid operation: Controller generated flow " - + "cannot be modified"; + String msg = "Invalid operation: Controller generated flow cannot be modified"; String logMsg = msg + ": {}"; log.warn(logMsg, config); return new Status(StatusCode.NOTACCEPTABLE, msg); } + // Find the config entry + Integer key = 0; + FlowConfig target = null; for (Map.Entry entry : staticFlows.entrySet()) { FlowConfig conf = entry.getValue(); if (conf.isByNameAndNodeIdEqual(config)) { - // Program the network node - Status status = new Status(StatusCode.SUCCESS); - if (conf.installInHw()) { - status = this.removeEntry(conf.getFlowEntry(), false); - } else { - status = this.addEntry(conf.getFlowEntry(), false); - } - if (!status.isSuccess()) { - conf.setStatus(status.getDescription()); - return status; - } + key = entry.getKey(); + target = conf; + break; + } + } + if (target != null) { + // Program the network node + Status status; + if (target.installInHw()) { + status = this.removeEntry(target.getFlowEntry(), false); + } else { + status = this.addEntry(target.getFlowEntry(), false); + } + // Update Configuration database + target.setStatus(SUCCESS); + target.toggleInstallation(); + staticFlows.put(key, target); + return status; + } + + return new Status(StatusCode.NOTFOUND, "Unable to locate the entry. Failed to toggle status"); + } - // Update Configuration database - conf.setStatus(StatusCode.SUCCESS.toString()); - conf.toggleStatus(); - return status; + /** + * Reinsert all static flows entries in the cache to force cache updates in + * the cluster. This is useful when only some parameters were changed in the + * entries, like the status. + * + * @param node + * The node for which the static flow configurations have to be + * refreshed. If null, all nodes static flows will be refreshed. + */ + private void refreshClusterStaticFlowsStatus(Node node) { + // Refresh cluster cache + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + if (node == null || entry.getValue().getNode().equals(node)) { + staticFlows.put(entry.getKey(), entry.getValue()); } } - return new Status(StatusCode.NOTFOUND, - "Unable to locate the entry. Failed to toggle status"); } /** - * Uninstall all the Flow Entries present in the software view A copy of - * each entry is stored in the inactive list so that it can be re-applied - * when needed This function is called on the default container instance of - * FRM only when the first container is created + * Uninstall all the non-internal Flow Entries present in the software view. + * A copy of each entry is stored in the inactive list so that it can be + * re-applied when needed. This function is called on the global instance of + * FRM only, when the first container is created */ private void uninstallAllFlowEntries() { - log.info("Uninstalling all flows"); + log.info("Uninstalling all non-internal flows"); // Store entries / create target list - for (ConcurrentMap.Entry> mapEntry : nodeFlows - .entrySet()) { - for (FlowEntryInstall flowEntries : mapEntry.getValue()) { + for (ConcurrentMap.Entry mapEntry : installedSwView.entrySet()) { + FlowEntryInstall flowEntries = mapEntry.getValue(); + // Skip internal generated static flows + if (!flowEntries.isInternal()) { inactiveFlows.add(flowEntries.getOriginal()); } } @@ -1683,8 +1644,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, for (FlowEntry flowEntry : inactiveFlows) { Status status = this.removeEntry(flowEntry, false); if (!status.isSuccess()) { - log.warn("Failed to remove entry: {}. The failure is: {}", - flowEntry, status.getDescription()); + log.warn("Failed to remove entry: {}. The failure is: {}", flowEntry, status.getDescription()); } } } @@ -1698,28 +1658,23 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, log.info("Reinstalling all inactive flows"); for (FlowEntry flowEntry : this.inactiveFlows) { - Status status = this.addEntry(flowEntry, false); - if (!status.isSuccess()) { - log.warn("Failed to install entry: {}. The failure is: {}", - flowEntry, status.getDescription()); - } + this.addEntry(flowEntry, false); } // Empty inactive list in any case inactiveFlows.clear(); } + @Override public List getStaticFlows() { - return getStaticFlowsOrderedList(staticFlows, staticFlowsOrdinal.get(0) - .intValue()); + return getStaticFlowsOrderedList(staticFlows, staticFlowsOrdinal.get(0).intValue()); } - // TODO: need to come out with a better algorithm for mantaining the order + // TODO: need to come out with a better algorithm for maintaining the order // of the configuration entries // with actual one, index associated to deleted entries cannot be reused and // map grows... - private List getStaticFlowsOrderedList( - ConcurrentMap flowMap, int maxKey) { + private List getStaticFlowsOrderedList(ConcurrentMap flowMap, int maxKey) { List orderedList = new ArrayList(); for (int i = 0; i <= maxKey; i++) { FlowConfig entry = flowMap.get(i); @@ -1732,9 +1687,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public FlowConfig getStaticFlow(String name, Node node) { - for (FlowConfig config : staticFlows.values()) { - if (config.isByNameAndNodeIdEqual(name, node)) { - return config; + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + if (entry.getValue().isByNameAndNodeIdEqual(name, node)) { + return entry.getValue(); } } return null; @@ -1743,9 +1698,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public List getStaticFlows(Node node) { List list = new ArrayList(); - for (FlowConfig config : staticFlows.values()) { - if (config.onNode(node)) { - list.add(config); + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + if (entry.getValue().onNode(node)) { + list.add(entry.getValue()); } } return list; @@ -1754,9 +1709,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public List getStaticFlowNamesForNode(Node node) { List list = new ArrayList(); - for (FlowConfig config : staticFlows.values()) { - if (config.onNode(node)) { - list.add(config.getName()); + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + if (entry.getValue().onNode(node)) { + list.add(entry.getValue().getName()); } } return list; @@ -1765,8 +1720,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public List getListNodeWithConfiguredFlows() { Set set = new HashSet(); - for (FlowConfig config : staticFlows.values()) { - set.add(config.getNode()); + for (ConcurrentMap.Entry entry : staticFlows.entrySet()) { + set.add(entry.getValue().getNode()); } return new ArrayList(set); } @@ -1774,16 +1729,15 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @SuppressWarnings("unchecked") private void loadFlowConfiguration() { ObjectReader objReader = new ObjectReader(); - ConcurrentMap confList = (ConcurrentMap) objReader - .read(this, frmFileName); + ConcurrentMap confList = (ConcurrentMap) objReader.read(this, + frmFileName); - ConcurrentMap pgConfig = (ConcurrentMap) objReader - .read(this, portGroupFileName); + ConcurrentMap pgConfig = (ConcurrentMap) objReader.read(this, + portGroupFileName); if (pgConfig != null) { - for (Map.Entry entry : pgConfig.entrySet()) { - addPortGroupConfig(entry.getKey(), entry.getValue() - .getMatchString(), true); + for (ConcurrentMap.Entry entry : pgConfig.entrySet()) { + addPortGroupConfig(entry.getKey(), entry.getValue().getMatchString(), true); } } @@ -1793,8 +1747,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, int maxKey = 0; for (Integer key : confList.keySet()) { - if (key.intValue() > maxKey) + if (key.intValue() > maxKey) { maxKey = key.intValue(); + } } for (FlowConfig conf : getStaticFlowsOrderedList(confList, maxKey)) { @@ -1803,11 +1758,11 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } @Override - public Object readObject(ObjectInputStream ois) - throws FileNotFoundException, IOException, ClassNotFoundException { + public Object readObject(ObjectInputStream ois) throws FileNotFoundException, IOException, ClassNotFoundException { return ois.readObject(); } + @Override public Status saveConfig() { // Publish the save config event to the cluster nodes flowsSaveEvent.put(new Date().getTime(), SAVE); @@ -1816,7 +1771,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, private Status saveConfigInternal() { ObjectWriter objWriter = new ObjectWriter(); - ConcurrentHashMap nonDynamicFlows = new ConcurrentHashMap(); + ConcurrentMap nonDynamicFlows = new ConcurrentHashMap(); for (Integer ordinal : staticFlows.keySet()) { FlowConfig config = staticFlows.get(ordinal); // Do not save dynamic and controller generated static flows @@ -1826,8 +1781,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, nonDynamicFlows.put(ordinal, config); } objWriter.write(nonDynamicFlows, frmFileName); - objWriter.write(new ConcurrentHashMap( - portGroupConfigs), portGroupFileName); + objWriter.write(new ConcurrentHashMap(portGroupConfigs), portGroupFileName); return new Status(StatusCode.SUCCESS, null); } @@ -1836,8 +1790,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } @Override - public void entryUpdated(Long key, String new_value, String cacheName, - boolean originLocal) { + public void entryUpdated(Long key, String new_value, String cacheName, boolean originLocal) { saveConfigInternal(); } @@ -1863,10 +1816,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, allowARP.setName("**Punt ARP Reply"); allowARP.setPriority("500"); allowARP.setNode(node); - allowARP.setEtherType("0x" - + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase()); - allowARP.setDstMac(HexEncode.bytesToHexString(switchManager - .getControllerMAC())); + allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase()); + allowARP.setDstMac(HexEncode.bytesToHexString(switchManager.getControllerMAC())); allowARP.setActions(puntAction); addStaticFlow(allowARP, false); } @@ -1883,8 +1834,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, allowARP.setName("**Punt ARP"); allowARP.setPriority("1"); allowARP.setNode(node); - allowARP.setEtherType("0x" - + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase()); + allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase()); allowARP.setActions(puntAction); defaultConfigs.add(allowARP); @@ -1893,10 +1843,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, allowLLDP.setName("**Punt LLDP"); allowLLDP.setPriority("1"); allowLLDP.setNode(node); - allowLLDP - .setEtherType("0x" - + Integer.toHexString(EtherTypes.LLDP.intValue()) - .toUpperCase()); + allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue()).toUpperCase()); allowLLDP.setActions(puntAction); defaultConfigs.add(allowLLDP); @@ -1919,7 +1866,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } - log.info("Set Switch {} Mode to {}", node, proactive); + log.info("Set Switch {} Mode to {}", node, (proactive ? "proactive" : "reactive")); } /** @@ -1927,65 +1874,28 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * * @param node */ - private synchronized void cleanDatabaseForNode(Node node) { - log.info("Cleaning Flow database for Node {}", node.toString()); - - // Find out which groups the node's flows are part of - Set affectedGroups = new HashSet(); - Set flowEntryList = nodeFlows.get(node); - if (flowEntryList != null) { - for (FlowEntryInstall entry : flowEntryList) { - String groupName = entry.getGroupName(); - if (groupName != null) { - affectedGroups.add(groupName); - } - } - } + private void cleanDatabaseForNode(Node node) { + log.info("Cleaning Flow database for Node {}", node); + if (nodeFlows.containsKey(node)) { + List toRemove = new ArrayList(nodeFlows.get(node)); - // Remove the node's flows from the group indexed flow database - if (!affectedGroups.isEmpty()) { - for (String group : affectedGroups) { - Set flowList = groupFlows.get(group); - Set toRemove = new HashSet(); - for (FlowEntryInstall entry : flowList) { - if (node.equals(entry.getNode())) { - toRemove.add(entry); - } - } - flowList.removeAll(toRemove); - if (flowList.isEmpty()) { - groupFlows.remove(group); - } + for (FlowEntryInstall entry : toRemove) { + updateLocalDatabase(entry, false); } } - - // Remove the node's flows from the node indexed flow database - nodeFlows.remove(node); } @Override - public void notifyNode(Node node, UpdateType type, - Map propMap) { - switch (type) { - case ADDED: - addStaticFlowsToSwitch(node); - break; - case REMOVED: - cleanDatabaseForNode(node); - updateStaticFlowConfigsOnNodeDown(node); - break; - default: - break; - } + public void notifyNode(Node node, UpdateType type, Map propMap) { + this.pendingEvents.offer(new NodeUpdateEvent(type, node)); } @Override - public void notifyNodeConnector(NodeConnector nodeConnector, - UpdateType type, Map propMap) { + public void notifyNodeConnector(NodeConnector nodeConnector, UpdateType type, Map propMap) { + } - private FlowConfig getDerivedFlowConfig(FlowConfig original, - String configName, Short port) { + private FlowConfig getDerivedFlowConfig(FlowConfig original, String configName, Short port) { FlowConfig derivedFlow = new FlowConfig(original); derivedFlow.setDynamic(true); derivedFlow.setPortGroup(null); @@ -1994,38 +1904,28 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return derivedFlow; } - private void addPortGroupFlows(PortGroupConfig config, Node node, - PortGroup data) { - for (Iterator it = staticFlows.values().iterator(); it - .hasNext();) { - FlowConfig staticFlow = it.next(); + private void addPortGroupFlows(PortGroupConfig config, Node node, PortGroup data) { + for (FlowConfig staticFlow : staticFlows.values()) { if (staticFlow.getPortGroup() == null) { continue; } - if ((staticFlow.getNode().equals(node)) - && (staticFlow.getPortGroup().equals(config.getName()))) { + if ((staticFlow.getNode().equals(node)) && (staticFlow.getPortGroup().equals(config.getName()))) { for (Short port : data.getPorts()) { - FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, - config.getName(), port); + FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, config.getName(), port); addStaticFlow(derivedFlow, false); } } } } - private void removePortGroupFlows(PortGroupConfig config, Node node, - PortGroup data) { - for (Iterator it = staticFlows.values().iterator(); it - .hasNext();) { - FlowConfig staticFlow = it.next(); + private void removePortGroupFlows(PortGroupConfig config, Node node, PortGroup data) { + for (FlowConfig staticFlow : staticFlows.values()) { if (staticFlow.getPortGroup() == null) { continue; } - if ((staticFlow.getNode().equals(node)) - && (staticFlow.getPortGroup().equals(config.getName()))) { + if (staticFlow.getNode().equals(node) && staticFlow.getPortGroup().equals(config.getName())) { for (Short port : data.getPorts()) { - FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, - config.getName(), port); + FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, config.getName(), port); removeStaticFlow(derivedFlow); } } @@ -2033,8 +1933,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } @Override - public void portGroupChanged(PortGroupConfig config, - Map data, boolean add) { + public void portGroupChanged(PortGroupConfig config, Map data, boolean add) { log.info("PortGroup Changed for: {} Data: {}", config, portGroupData); Map existingData = portGroupData.get(config); if (existingData != null) { @@ -2043,20 +1942,15 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, if (existingPortGroup == null) { if (add) { existingData.put(entry.getKey(), entry.getValue()); - addPortGroupFlows(config, entry.getKey(), - entry.getValue()); + addPortGroupFlows(config, entry.getKey(), entry.getValue()); } } else { if (add) { - existingPortGroup.getPorts().addAll( - entry.getValue().getPorts()); - addPortGroupFlows(config, entry.getKey(), - entry.getValue()); + existingPortGroup.getPorts().addAll(entry.getValue().getPorts()); + addPortGroupFlows(config, entry.getKey(), entry.getValue()); } else { - existingPortGroup.getPorts().removeAll( - entry.getValue().getPorts()); - removePortGroupFlows(config, entry.getKey(), - entry.getValue()); + existingPortGroup.getPorts().removeAll(entry.getValue().getPorts()); + removePortGroupFlows(config, entry.getKey(), entry.getValue()); } } } @@ -2070,16 +1964,17 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } + @Override public boolean addPortGroupConfig(String name, String regex, boolean restore) { PortGroupConfig config = portGroupConfigs.get(name); - if (config != null) + if (config != null) { return false; + } if ((portGroupProvider == null) && !restore) { return false; } - if ((portGroupProvider != null) - && (!portGroupProvider.isMatchCriteriaSupported(regex))) { + if ((portGroupProvider != null) && (!portGroupProvider.isMatchCriteriaSupported(regex))) { return false; } @@ -2091,6 +1986,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return true; } + @Override public boolean delPortGroupConfig(String name) { PortGroupConfig config = portGroupConfigs.get(name); if (config == null) { @@ -2110,8 +2006,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return; } if (portGroupProvider != null) { - Map data = portGroupProvider - .getPortGroupData(config); + Map data = portGroupProvider.getPortGroupData(config); portGroupData.put(config, data); } } @@ -2128,22 +2023,6 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, return true; } - // Fir PortGroupProvider to use regular Dependency Manager - /* @SuppressWarnings("rawtypes") */ - /* public void bind(Object arg0, Map arg1) throws Exception { */ - /* if (arg0 instanceof PortGroupProvider) { */ - /* setPortGroupProvider((PortGroupProvider)arg0); */ - /* } */ - /* } */ - - /* @SuppressWarnings("rawtypes") */ - /* @Override */ - /* public void unbind(Object arg0, Map arg1) throws Exception { */ - /* if (arg0 instanceof PortGroupProvider) { */ - /* portGroupProvider = null; */ - /* } */ - /* } */ - public void setIContainer(IContainer s) { this.container = s; } @@ -2154,6 +2033,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } } + @Override public PortGroupProvider getPortGroupProvider() { return portGroupProvider; } @@ -2213,12 +2093,9 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * */ void init() { - frmAware = Collections - .synchronizedSet(new HashSet()); - frmFileName = GlobalConstants.STARTUPHOME.toString() - + "frm_staticflows_" + this.getContainerName() + ".conf"; - portGroupFileName = GlobalConstants.STARTUPHOME.toString() - + "portgroup_" + this.getContainerName() + ".conf"; + frmAware = Collections.synchronizedSet(new HashSet()); + frmFileName = GlobalConstants.STARTUPHOME.toString() + "frm_staticflows_" + this.getContainerName() + ".conf"; + portGroupFileName = GlobalConstants.STARTUPHOME.toString() + "portgroup_" + this.getContainerName() + ".conf"; inContainerMode = false; @@ -2239,6 +2116,45 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, if (staticFlowsOrdinal.size() == 0) { staticFlowsOrdinal.put(0, Integer.valueOf(0)); } + + pendingEvents = new LinkedBlockingQueue(); + + // Initialize the event handler thread + frmEventHandler = new Thread(new Runnable() { + @Override + public void run() { + while (!stopping) { + try { + FRMEvent event = pendingEvents.take(); + if (event == null) { + log.warn("Dequeued null event"); + continue; + } + if (event instanceof NodeUpdateEvent) { + NodeUpdateEvent update = (NodeUpdateEvent) event; + Node node = update.getNode(); + switch (update.getUpdateType()) { + case ADDED: + addStaticFlowsToSwitch(node); + break; + case REMOVED: + cleanDatabaseForNode(node); + updateStaticFlowConfigsOnNodeDown(node); + break; + default: + } + } else if (event instanceof ErrorReportedEvent) { + ErrorReportedEvent errEvent = (ErrorReportedEvent) event; + processErrorEvent(errEvent); + } else { + log.warn("Dequeued unknown event {}", event.getClass().getSimpleName()); + } + } catch (InterruptedException e) { + log.warn("FRM EventHandler thread interrupted", e); + } + } + } + }, "FRM EventHandler Collector"); } /** @@ -2248,7 +2164,6 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * */ void destroy() { - destroyCaches(); } /** @@ -2257,6 +2172,12 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * */ void start() { + // Initialize graceful stop flag + stopping = false; + + // Start event handler thread + frmEventHandler.start(); + /* * Read startup and build database if we have not already gotten the * configurations synced from another node @@ -2273,6 +2194,8 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, * */ void stop() { + // Set graceful stop flag + stopping = true; } public void setFlowProgrammerService(IFlowProgrammerService service) { @@ -2296,14 +2219,13 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } @Override - public void tagUpdated(String containerName, Node n, short oldTag, - short newTag, UpdateType t) { + public void tagUpdated(String containerName, Node n, short oldTag, short newTag, UpdateType t) { } @Override - public void containerFlowUpdated(String containerName, - ContainerFlow previousFlow, ContainerFlow currentFlow, UpdateType t) { + public void containerFlowUpdated(String containerName, ContainerFlow previousFlow, ContainerFlow currentFlow, + UpdateType t) { /* * Whether it is an addition or removal, we have to recompute the merged * flows entries taking into account all the current container flows @@ -2313,8 +2235,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } @Override - public void nodeConnectorUpdated(String containerName, NodeConnector p, - UpdateType t) { + public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType t) { // No action } @@ -2336,6 +2257,52 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, updateStaticFlowConfigsOnContainerModeChange(update); } + protected abstract class FRMEvent { + + } + + private class NodeUpdateEvent extends FRMEvent { + private final Node node; + private final UpdateType update; + + public NodeUpdateEvent(UpdateType update, Node node) { + this.update = update; + this.node = node; + } + + public UpdateType getUpdateType() { + return update; + } + + public Node getNode() { + return node; + } + } + + private class ErrorReportedEvent extends FRMEvent { + private final long rid; + private final Node node; + private final Object error; + + public ErrorReportedEvent(long rid, Node node, Object error) { + this.rid = rid; + this.node = node; + this.error = error; + } + + public long getRequestId() { + return rid; + } + + public Object getError() { + return error; + } + + public Node getNode() { + return node; + } + } + /* * OSGI COMMANDS */ @@ -2399,8 +2366,7 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, ci.println(this.programmer.addFlow(node, getSampleFlow(node))); } - public void _frmremoveflow(CommandInterpreter ci) - throws UnknownHostException { + public void _frmremoveflow(CommandInterpreter ci) throws UnknownHostException { Node node = null; String nodeId = ci.nextArgument(); if (nodeId == null) { @@ -2417,14 +2383,10 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } private Flow getSampleFlow(Node node) throws UnknownHostException { - NodeConnector port = NodeConnectorCreator.createOFNodeConnector( - (short) 24, node); - NodeConnector oport = NodeConnectorCreator.createOFNodeConnector( - (short) 30, node); - byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, - (byte) 0x9a, (byte) 0xbc }; - byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, - (byte) 0x5e, (byte) 0x6f }; + NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 24, node); + NodeConnector oport = NodeConnectorCreator.createOFNodeConnector((short) 30, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; InetAddress srcIP = InetAddress.getByName("172.28.30.50"); InetAddress dstIP = InetAddress.getByName("171.71.9.52"); InetAddress ipMask = InetAddress.getByName("255.255.255.0"); @@ -2468,44 +2430,53 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, } public void _frmNodeFlows(CommandInterpreter ci) { + String nodeId = ci.nextArgument(); + Node node = Node.fromString(nodeId); + if (node == null) { + ci.println("frmNodeFlows [verbose]"); + return; + } boolean verbose = false; String verboseCheck = ci.nextArgument(); if (verboseCheck != null) { verbose = verboseCheck.equals("true"); } + if (!nodeFlows.containsKey(node)) { + return; + } // Dump per node database - for (Entry> entry : this.nodeFlows - .entrySet()) { - Node node = entry.getKey(); - for (FlowEntryInstall flow : entry.getValue()) { - if (!verbose) { - ci.println(node + " " + flow.getFlowName()); - } else { - ci.println(node + " " + flow.toString()); - } + for (FlowEntryInstall entry : nodeFlows.get(node)) { + if (!verbose) { + ci.println(node + " " + installedSwView.get(entry).getFlowName()); + } else { + ci.println(node + " " + installedSwView.get(entry).toString()); } } } public void _frmGroupFlows(CommandInterpreter ci) { + String group = ci.nextArgument(); + if (group == null) { + ci.println("frmGroupFlows [verbose]"); + return; + } boolean verbose = false; String verboseCheck = ci.nextArgument(); if (verboseCheck != null) { verbose = verboseCheck.equalsIgnoreCase("true"); } + if (!groupFlows.containsKey(group)) { + return; + } // Dump per node database - for (Entry> entry : this.groupFlows - .entrySet()) { - String group = entry.getKey(); - ci.println("Group " + group + ":"); - for (FlowEntryInstall flow : entry.getValue()) { - if (!verbose) { - ci.println(flow.getNode() + " " + flow.getFlowName()); - } else { - ci.println(flow.getNode() + " " + flow.toString()); - } + ci.println("Group " + group + ":\n"); + for (FlowEntryInstall flowEntry : groupFlows.get(group)) { + if (!verbose) { + ci.println(flowEntry.getNode() + " " + flowEntry.getFlowName()); + } else { + ci.println(flowEntry.getNode() + " " + flowEntry.toString()); } } } @@ -2513,59 +2484,73 @@ public class ForwardingRulesManagerImpl implements IForwardingRulesManager, @Override public void flowRemoved(Node node, Flow flow) { log.trace("Received flow removed notification on {} for {}", node, flow); - // For flow entry identification, only match and priority matter - FlowEntry toFind = new FlowEntry("any", "any", flow, node); - FlowEntryInstall installedEntry = this.findMatch(toFind, false); + + // For flow entry identification, only node, match and priority matter + FlowEntryInstall test = new FlowEntryInstall(new FlowEntry("","",flow, node), null); + FlowEntryInstall installedEntry = this.installedSwView.get(test); if (installedEntry == null) { - log.trace("Entry is not know to us"); + log.trace("Entry is not known to us"); return; } // Update Static flow status + Integer key = 0; + FlowConfig target = null; for (Map.Entry entry : staticFlows.entrySet()) { FlowConfig conf = entry.getValue(); if (conf.isByNameAndNodeIdEqual(installedEntry.getFlowName(), node)) { - // Update Configuration database - conf.toggleStatus(); + key = entry.getKey(); + target = conf; break; } } + if (target != null) { + // Update Configuration database + target.toggleInstallation(); + target.setStatus(SUCCESS); + staticFlows.put(key, target); + } + // Update software views this.updateLocalDatabase(installedEntry, false); } @Override - public synchronized void flowErrorReported(Node node, long rid, Object err) { - log.trace("Got error {} for message rid {} from node {}", - new Object[] {err, rid, node }); + public void flowErrorReported(Node node, long rid, Object err) { + log.trace("Got error {} for message rid {} from node {}", new Object[] { err, rid, node }); + pendingEvents.offer(new ErrorReportedEvent(rid, node, err)); + } + + private void processErrorEvent(ErrorReportedEvent event) { + Node node = event.getNode(); + long rid = event.getRequestId(); + Object error = event.getError(); + String errorString = (error == null) ? "Not provided" : error.toString(); /* - * If this was for a flow install, remove the corresponding entry - * from the software view. If it was a Looking for the rid going through the - * software database. - * TODO: A more efficient rid <-> FlowEntryInstall mapping will - * have to be added in future + * If this was for a flow install, remove the corresponding entry from + * the software view. If it was a Looking for the rid going through the + * software database. TODO: A more efficient rid <-> FlowEntryInstall + * mapping will have to be added in future */ - Set entries = nodeFlows.get(node); - if (entries != null) { - FlowEntryInstall target = null; - for (FlowEntryInstall entry : entries) { - if (entry.getRequestId() == rid) { - target = entry; - break; - } - } - if (target != null) { - // This was a flow install, update database - this.updateLocalDatabase(target, false); + FlowEntryInstall target = null; + for (FlowEntryInstall index : nodeFlows.get(node)) { + FlowEntryInstall entry = installedSwView.get(index); + if (entry.getRequestId() == rid) { + target = entry; + break; } } + if (target != null) { + // This was a flow install, update database + this.updateLocalDatabase(target, false); + } // Notify listeners if (frmAware != null) { synchronized (frmAware) { for (IForwardingRulesManagerAware frma : frmAware) { try { - frma.requestFailed(rid, err.toString()); + frma.requestFailed(rid, errorString); } catch (Exception e) { log.warn("Failed to notify {}", frma); } diff --git a/opendaylight/forwardingrulesmanager/integrationtest/src/test/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerIT.java b/opendaylight/forwardingrulesmanager/integrationtest/src/test/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerIT.java index 6876144905..c3f41059cf 100644 --- a/opendaylight/forwardingrulesmanager/integrationtest/src/test/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerIT.java +++ b/opendaylight/forwardingrulesmanager/integrationtest/src/test/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerIT.java @@ -4,8 +4,6 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; -import java.util.Map; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.osgi.framework.ServiceReference; @@ -21,13 +19,9 @@ import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManage import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.Drop; import org.opendaylight.controller.sal.core.Node; -import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchType; -import org.opendaylight.controller.sal.reader.FlowOnNode; -import org.opendaylight.controller.sal.reader.NodeConnectorStatistics; -import org.opendaylight.controller.sal.reader.NodeDescription; import org.opendaylight.controller.sal.utils.NodeCreator; import org.opendaylight.controller.sal.utils.Status; import org.opendaylight.controller.sal.utils.StatusCode; @@ -156,10 +150,10 @@ public class ForwardingRulesManagerIT { assertNotNull(bc); boolean debugit = false; Bundle b[] = bc.getBundles(); - for (int i = 0; i < b.length; i++) { - int state = b[i].getState(); + for (Bundle element : b) { + int state = element.getState(); if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) { - log.debug("Bundle:" + b[i].getSymbolicName() + " state:" + log.debug("Bundle:" + element.getSymbolicName() + " state:" + stateToString(state)); debugit = true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java index 332e31f6bf..8fc8fc16bf 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Action.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -9,6 +8,8 @@ package org.opendaylight.controller.sal.action; +import java.io.Serializable; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; @@ -19,30 +20,32 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Represents the generic action to be applied to the matched frame/packet/message + * Represents the generic action to be applied to the matched + * frame/packet/message */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) -@XmlSeeAlso({Controller.class, Drop.class, Flood.class, FloodAll.class, HwPath.class, Loopback.class, Output.class, - PopVlan.class, PushVlan.class, SetDlDst.class, SetDlSrc.class, SetDlType.class, SetNwDst.class, SetNwSrc.class, - SetNwTos.class, SetTpDst.class, SetTpSrc.class, SetVlanCfi.class, SetVlanId.class, SetVlanPcp.class, SwPath.class}) -public abstract class Action { +@XmlSeeAlso({ Controller.class, Drop.class, Flood.class, FloodAll.class, HwPath.class, Loopback.class, Output.class, + PopVlan.class, PushVlan.class, SetDlDst.class, SetDlSrc.class, SetDlType.class, SetNwDst.class, SetNwSrc.class, + SetNwTos.class, SetTpDst.class, SetTpSrc.class, SetVlanCfi.class, SetVlanId.class, SetVlanPcp.class, + SwPath.class }) +public abstract class Action implements Serializable { + private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(Action.class); - private static boolean debug = false; // Enable to find where in the code an invalid assignment is made + private static boolean debug = false; // Enable to find where in the code an + // invalid assignment is made @XmlTransient protected ActionType type; private transient boolean isValid = true; /* Dummy constructor for JAXB */ - public Action () { + public Action() { } /* - public Action (ActionType type, Object value) { - this.type = type; - this.value = value; - this.isValid = true; - } */ + * public Action (ActionType type, Object value) { this.type = type; + * this.value = value; this.isValid = true; } + */ /** * Checks if the passed value is in the valid range for this action @@ -58,8 +61,8 @@ public abstract class Action { } /** - * Checks if the passed value is in the valid range for the passed action type - * This method is used for complex Action types which are + * Checks if the passed value is in the valid range for the passed action + * type This method is used for complex Action types which are * * @param value * @return boolean @@ -78,15 +81,14 @@ public abstract class Action { * @return void */ private void throwValueException(int value) { - String error = "Invalid field value assignement. For type: " - + type.getId() + " Expected: " + type.getRange() + ", Got: 0x" - + Integer.toHexString(value); + String error = "Invalid field value assignement. For type: " + type.getId() + " Expected: " + type.getRange() + + ", Got: 0x" + Integer.toHexString(value); try { throw new Exception(error); } catch (Exception e) { logger.error(e.getMessage()); if (debug) { - logger.error("",e); + logger.error("", e); } } } @@ -112,7 +114,7 @@ public abstract class Action { /** * Returns whether the Action is valid or not * - * @return boolean + * @return boolean */ public boolean isValid() { return isValid; @@ -128,15 +130,19 @@ public abstract class Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } Action other = (Action) obj; - if (type != other.type) + if (type != other.type) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java index 0e085473d5..7da6fa9115 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/ActionType.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -12,9 +11,6 @@ package org.opendaylight.controller.sal.action; /** * The enumeration of actions supported by the controller * Each entry has a unique id and the values range for the action element where applicable - * - * - * */ public enum ActionType { DROP("drop", 0, 0), @@ -61,8 +57,7 @@ public enum ActionType { } public String getRange() { - return "[0x" + Long.toHexString(minValue) + "-0x" - + Long.toHexString(maxValue) + "]"; + return "[0x" + Long.toHexString(minValue) + "-0x" + Long.toHexString(maxValue) + "]"; } public boolean takesParameter() { diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java index 1c7cc7b7a3..e7958ce0bc 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Controller.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -15,14 +14,11 @@ import javax.xml.bind.annotation.XmlRootElement; /** * Represents the action of punting the packet to the controller - * - * - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class Controller extends Action { + private static final long serialVersionUID = 1L; public Controller() { type = ActionType.CONTROLLER; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java index 1297a15f69..2e72f047db 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Drop.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -15,13 +14,12 @@ import javax.xml.bind.annotation.XmlRootElement; /** * Represent the action of dropping the matched packet - * - * - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class Drop extends Action { + private static final long serialVersionUID = 1L; + public Drop() { type = ActionType.DROP; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java index 4d2436b1bf..ca307e23c6 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Flood.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -15,14 +14,11 @@ import javax.xml.bind.annotation.XmlRootElement; /** * Represents the action of flooding the packet out - * - * - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class Flood extends Action { + private static final long serialVersionUID = 1L; public Flood() { type = ActionType.FLOOD; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java index b0f60d4b92..086f5f2209 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/FloodAll.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -14,15 +13,13 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; /** - * Represents the action of flooding the packet out all the physical ports except the input port - * - * - * + * Represents the action of flooding the packet out all the physical ports + * except the input port */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class FloodAll extends Action { + private static final long serialVersionUID = 1L; public FloodAll() { type = ActionType.FLOOD_ALL; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java index fc7786719d..3b11a7cbf0 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/HwPath.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -14,15 +13,13 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; /** - * Represents the action of sending the packet to the local hardware path for processing - * - * - * + * Represents the action of sending the packet to the local hardware path for + * processing */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class HwPath extends Action { + private static final long serialVersionUID = 1L; public HwPath() { type = ActionType.HW_PATH; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java index b930eecacc..05682c3e8f 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Loopback.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -15,14 +14,11 @@ import javax.xml.bind.annotation.XmlRootElement; /** * Represents the action of looping the packet back the port it came in from - * - * - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class Loopback extends Action { + private static final long serialVersionUID = 1L; public Loopback() { type = ActionType.LOOPBACK; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java index 774c79a543..5bd9efb30b 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/Output.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -18,25 +17,23 @@ import org.opendaylight.controller.sal.core.NodeConnector; /** * Represents the action of sending the packet out of a physical port - * - * - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class Output extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private NodeConnector port; /* Dummy constructor for JAXB */ - private Output () { + @SuppressWarnings("unused") + private Output() { } public Output(NodeConnector port) { type = ActionType.OUTPUT; this.port = port; - //checkValue(port); + // checkValue(port); } public NodeConnector getPort() { @@ -45,18 +42,23 @@ public class Output extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } Output other = (Output) obj; if (port == null) { - if (other.port != null) + if (other.port != null) { return false; - } else if (!port.equals(other.port)) + } + } else if (!port.equals(other.port)) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java index 6ef37fd9fa..d0d2a94417 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PopVlan.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -15,14 +14,11 @@ import javax.xml.bind.annotation.XmlRootElement; /** * Pop vlan action (strip the outermost 802.1q header) - * - * - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class PopVlan extends Action { + private static final long serialVersionUID = 1L; public PopVlan() { type = ActionType.POP_VLAN; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java index b5783d487a..edb30ae031 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/PushVlan.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -17,19 +16,15 @@ import javax.xml.bind.annotation.XmlRootElement; import org.opendaylight.controller.sal.utils.EtherTypes; /** - * Insert a 802.1q (outermost) header action - * Execute it multiple times to achieve QinQ - * - * 802.1q = [TPID(16) + TCI(16)] - * TCI = [PCP(3) + CFI(1) + VID(12)] - * - * + * Insert a 802.1q (outermost) header action Execute it multiple times to + * achieve QinQ * + * 802.1q = [TPID(16) + TCI(16)] TCI = [PCP(3) + CFI(1) + VID(12)] */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class PushVlan extends Action { + private static final long serialVersionUID = 1L; private int tag; // TPID - 16 bits private int pcp; // PCP - 3 bits private int cfi; // CFI - 1 bit (drop eligible) @@ -38,7 +33,8 @@ public class PushVlan extends Action { private transient int header; // full 802.1q header [TPID + TCI] - 32 bits /* Dummy constructor for JAXB */ - private PushVlan () { + @SuppressWarnings("unused") + private PushVlan() { } public PushVlan(int tag, int pcp, int cfi, int vlanId) { @@ -68,8 +64,7 @@ public class PushVlan extends Action { } private int createHeader() { - return (tag & 0xffff) << 16 | (pcp & 0x7) << 13 | (cfi & 0x1) << 12 - | (vlanId & 0xfff); + return (tag & 0xffff) << 16 | (pcp & 0x7) << 13 | (cfi & 0x1) << 12 | (vlanId & 0xfff); } private void runChecks() { @@ -80,18 +75,18 @@ public class PushVlan extends Action { checkValue(tci); // Run action specific check which cannot be run by parent - if (tag != EtherTypes.VLANTAGGED.intValue() - && tag != EtherTypes.QINQ.intValue() - && tag != EtherTypes.OLDQINQ.intValue() - && tag != EtherTypes.CISCOQINQ.intValue()) { - // pass a value which will tell fail and tell something about the original wrong value + if (tag != EtherTypes.VLANTAGGED.intValue() && tag != EtherTypes.QINQ.intValue() + && tag != EtherTypes.OLDQINQ.intValue() && tag != EtherTypes.CISCOQINQ.intValue()) { + // pass a value which will tell fail and tell something about the + // original wrong value checkValue(ActionType.SET_DL_TYPE, 0xBAD << 16 | tag); } } /** - * Returns the VID portion of the 802.1q header this action will insert - * VID - (12 bits) + * Returns the VID portion of the 802.1q header this action will insert VID + * - (12 bits) + * * @return byte[] */ public int getVlanId() { @@ -99,8 +94,9 @@ public class PushVlan extends Action { } /** - * Returns the CFI portion of the 802.1q header this action will insert - * CFI - (1 bit) + * Returns the CFI portion of the 802.1q header this action will insert CFI + * - (1 bit) + * * @return */ public int getCfi() { @@ -110,6 +106,7 @@ public class PushVlan extends Action { /** * Returns the vlan PCP portion of the 802.1q header this action will insert * PCP - (3 bits) + * * @return byte[] */ public int getPcp() { @@ -125,8 +122,9 @@ public class PushVlan extends Action { } /** - * Returns the TCI portion of the 802.1q header this action will insert - * TCI = [PCP + CFI + VID] - (16 bits) + * Returns the TCI portion of the 802.1q header this action will insert TCI + * = [PCP + CFI + VID] - (16 bits) + * * @return */ public int getTci() { @@ -134,33 +132,40 @@ public class PushVlan extends Action { } /** - * Returns the full 802.1q header this action will insert - * header = [TPID + TIC] (32 bits) + * Returns the full 802.1q header this action will insert header = [TPID + + * TIC] (32 bits) * * @return int */ - @XmlElement(name="VlanHeader") + @XmlElement(name = "VlanHeader") public int getHeader() { return header; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } PushVlan other = (PushVlan) obj; - if (cfi != other.cfi) + if (cfi != other.cfi) { return false; - if (pcp != other.pcp) + } + if (pcp != other.pcp) { return false; - if (tag != other.tag) + } + if (tag != other.tag) { return false; - if (vlanId != other.vlanId) + } + if (vlanId != other.vlanId) { return false; + } return true; } @@ -177,8 +182,7 @@ public class PushVlan extends Action { @Override public String toString() { - return type + "[tag = " + tag + ", pcp = " + pcp + ", cfi = " + cfi - + ", vlanId = " + vlanId + "]"; + return type + "[tag = " + tag + ", pcp = " + pcp + ", cfi = " + cfi + ", vlanId = " + vlanId + "]"; } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java index c2c40bfcc8..da6dc93943 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlDst.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,16 +19,16 @@ import org.opendaylight.controller.sal.utils.HexEncode; /** * Set destination datalayer address action - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetDlDst extends Action { + private static final long serialVersionUID = 1L; private byte[] address; /* Dummy constructor for JAXB */ - private SetDlDst () { + @SuppressWarnings("unused") + private SetDlDst() { } public SetDlDst(byte[] dlAddress) { @@ -53,15 +52,19 @@ public class SetDlDst extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetDlDst other = (SetDlDst) obj; - if (!Arrays.equals(address, other.address)) + if (!Arrays.equals(address, other.address)) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java index 91909993f3..2b70535ecf 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlSrc.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -24,12 +23,13 @@ import org.opendaylight.controller.sal.utils.HexEncode; */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetDlSrc extends Action { + private static final long serialVersionUID = 1L; private byte[] address; /* Dummy constructor for JAXB */ - private SetDlSrc () { + @SuppressWarnings("unused") + private SetDlSrc() { } public SetDlSrc(byte[] dlAddress) { @@ -57,15 +57,19 @@ public class SetDlSrc extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetDlSrc other = (SetDlSrc) obj; - if (!Arrays.equals(address, other.address)) + if (!Arrays.equals(address, other.address)) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java index d15424ee15..225c4f7821 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetDlType.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -22,13 +21,14 @@ import org.opendaylight.controller.sal.utils.EtherTypes; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetDlType extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int dlType; /* Dummy constructor for JAXB */ - private SetDlType () { + @SuppressWarnings("unused") + private SetDlType() { } public SetDlType(int dlType) { @@ -54,15 +54,19 @@ public class SetDlType extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetDlType other = (SetDlType) obj; - if (dlType != other.dlType) + if (dlType != other.dlType) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNextHop.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNextHop.java index 33d9b9361d..80d457b8b4 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNextHop.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNextHop.java @@ -10,6 +10,7 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class SetNextHop extends Action { + private static final long serialVersionUID = 1L; @XmlElement private InetAddress address; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java index 2fa71f5d7b..db19cd6520 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwDst.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -22,12 +21,13 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetNwDst extends Action { + private static final long serialVersionUID = 1L; InetAddress address; /* Dummy constructor for JAXB */ - private SetNwDst () { + @SuppressWarnings("unused") + private SetNwDst() { } public SetNwDst(InetAddress address) { @@ -38,31 +38,36 @@ public class SetNwDst extends Action { /** * Returns the network address this action will set * - * @return InetAddress + * @return InetAddress */ public InetAddress getAddress() { return address; } - @XmlElement (name="address") + @XmlElement(name = "address") public String getAddressAsString() { return address.getHostAddress(); } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetNwDst other = (SetNwDst) obj; if (address == null) { - if (other.address != null) + if (other.address != null) { return false; - } else if (!address.equals(other.address)) + } + } else if (!address.equals(other.address)) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java index c57f1a53a9..dcd56f762a 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwSrc.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -22,12 +21,13 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetNwSrc extends Action { + private static final long serialVersionUID = 1L; InetAddress address; /* Dummy constructor for JAXB */ - private SetNwSrc () { + @SuppressWarnings("unused") + private SetNwSrc() { } public SetNwSrc(InetAddress address) { @@ -38,31 +38,36 @@ public class SetNwSrc extends Action { /** * Returns the network address this action will set * - * @return InetAddress + * @return InetAddress */ public InetAddress getAddress() { return address; } - @XmlElement (name="address") + @XmlElement(name = "address") public String getAddressAsString() { return address.getHostAddress(); } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetNwSrc other = (SetNwSrc) obj; if (address == null) { - if (other.address != null) + if (other.address != null) { return false; - } else if (!address.equals(other.address)) + } + } else if (!address.equals(other.address)) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java index 62dec0cd58..e5a85db638 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetNwTos.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -19,13 +18,14 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetNwTos extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int tos; /* Dummy constructor for JAXB */ - private SetNwTos () { + @SuppressWarnings("unused") + private SetNwTos() { } public SetNwTos(int tos) { @@ -45,15 +45,19 @@ public class SetNwTos extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetNwTos other = (SetNwTos) obj; - if (tos != other.tos) + if (tos != other.tos) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java index c32c346307..32cffa57ef 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpDst.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -19,13 +18,14 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetTpDst extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int port; /* Dummy constructor for JAXB */ - private SetTpDst () { + @SuppressWarnings("unused") + private SetTpDst() { } public SetTpDst(int port) { @@ -36,6 +36,7 @@ public class SetTpDst extends Action { /** * Returns the transport port the action will set + * * @return */ public int getPort() { @@ -44,15 +45,19 @@ public class SetTpDst extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetTpDst other = (SetTpDst) obj; - if (port != other.port) + if (port != other.port) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java index d56f33d51e..faa32978c1 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetTpSrc.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,13 +19,14 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetTpSrc extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int port; /* Dummy constructor for JAXB */ - private SetTpSrc () { + @SuppressWarnings("unused") + private SetTpSrc() { } public SetTpSrc(int port) { @@ -37,6 +37,7 @@ public class SetTpSrc extends Action { /** * Returns the transport port the action will set + * * @return */ public int getPort() { @@ -45,15 +46,19 @@ public class SetTpSrc extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetTpSrc other = (SetTpSrc) obj; - if (port != other.port) + if (port != other.port) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java index 0385f63d56..0c90fb41fc 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanCfi.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,13 +19,14 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetVlanCfi extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int cfi; /* Dummy constructor for JAXB */ - private SetVlanCfi () { + @SuppressWarnings("unused") + private SetVlanCfi() { } public SetVlanCfi(int cfi) { @@ -37,6 +37,7 @@ public class SetVlanCfi extends Action { /** * Returns the 802.1q CFI value that this action will set + * * @return */ public int getCfi() { @@ -45,15 +46,19 @@ public class SetVlanCfi extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetVlanCfi other = (SetVlanCfi) obj; - if (cfi != other.cfi) + if (cfi != other.cfi) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java index 5370648227..fcc71f32d8 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanId.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -20,14 +19,15 @@ import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetVlanId extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int vlanId; - private SetVlanId() { + @SuppressWarnings("unused") + private SetVlanId() { - } + } public SetVlanId(int vlanId) { type = ActionType.SET_VLAN_ID; @@ -46,15 +46,19 @@ public class SetVlanId extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetVlanId other = (SetVlanId) obj; - if (vlanId != other.vlanId) + if (vlanId != other.vlanId) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java index 1ee74fdf3f..4930d0721d 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SetVlanPcp.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -19,14 +18,15 @@ import javax.xml.bind.annotation.XmlRootElement; */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SetVlanPcp extends Action { - @XmlElement + private static final long serialVersionUID = 1L; + @XmlElement private int pcp; - private SetVlanPcp() { + @SuppressWarnings("unused") + private SetVlanPcp() { - } + } public SetVlanPcp(int pcp) { type = ActionType.SET_VLAN_PCP; @@ -36,6 +36,7 @@ public class SetVlanPcp extends Action { /** * Returns the value of the vlan PCP this action will set + * * @return int */ public int getPcp() { @@ -44,15 +45,19 @@ public class SetVlanPcp extends Action { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SetVlanPcp other = (SetVlanPcp) obj; - if (pcp != other.pcp) + if (pcp != other.pcp) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java index f30d2ee743..152ad7d486 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/action/SwPath.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -14,12 +13,13 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; /** - * Represents the action of sending the packet to the local software path for processing + * Represents the action of sending the packet to the local software path for + * processing */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) - public class SwPath extends Action { + private static final long serialVersionUID = 1L; public SwPath() { type = ActionType.SW_PATH; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java index f70e254ff5..0df6d4cec4 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -32,15 +31,13 @@ import org.slf4j.LoggerFactory; /** * Represent a flow: match + actions + flow specific properties - * */ @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) public class Flow implements Cloneable, Serializable { - protected static final Logger logger = LoggerFactory - .getLogger(Flow.class); - private static final long serialVersionUID = 1L; - @XmlElement + protected static final Logger logger = LoggerFactory.getLogger(Flow.class); + private static final long serialVersionUID = 1L; + @XmlElement private Match match; @XmlElement private List actions; @@ -63,7 +60,7 @@ public class Flow implements Cloneable, Serializable { try { throw new Exception("Conflicting Match and Action list"); } catch (Exception e) { - logger.error("",e); + logger.error("", e); } } else { this.match = match; @@ -81,8 +78,8 @@ public class Flow implements Cloneable, Serializable { } /** - * Set the Match for this flow - * This operation will overwrite an existing Match if present + * Set the Match for this flow This operation will overwrite an existing + * Match if present * * @param match */ @@ -92,6 +89,7 @@ public class Flow implements Cloneable, Serializable { /** * Returns a copy of the actions list of this flow + * * @return */ public List getActions() { @@ -99,12 +97,10 @@ public class Flow implements Cloneable, Serializable { } /** - * Set the actions list for this flow - * If a list is already present, it will be - * replaced with the passed one. During - * addition, only the valid actions will be added - * It is a no op if the passed actions is null - * An empty actions is a vlaid input + * Set the actions list for this flow If a list is already present, it will + * be replaced with the passed one. During addition, only the valid actions + * will be added It is a no op if the passed actions is null An empty + * actions is a vlaid input * * @param actions */ @@ -122,8 +118,8 @@ public class Flow implements Cloneable, Serializable { } /** - * Returns whether the Flow is for IPv4 or IPv6 - * Information is derived from match and actions list + * Returns whether the Flow is for IPv4 or IPv6 Information is derived from + * match and actions list * * @return */ @@ -132,8 +128,8 @@ public class Flow implements Cloneable, Serializable { } /** - * Returns true if it finds at least one action which is for IPv6 - * in the list of actions for this Flow + * Returns true if it finds at least one action which is for IPv6 in the + * list of actions for this Flow * * @return */ @@ -152,8 +148,7 @@ public class Flow implements Cloneable, Serializable { } break; case SET_DL_TYPE: - if (((SetDlType) action).getDlType() == EtherTypes.IPv6 - .intValue()) { + if (((SetDlType) action).getDlType() == EtherTypes.IPv6.intValue()) { return true; } break; @@ -172,7 +167,7 @@ public class Flow implements Cloneable, Serializable { cloned.match = this.getMatch(); cloned.actions = this.getActions(); } catch (CloneNotSupportedException e) { - logger.error("",e); + logger.error("", e); } return cloned; } @@ -192,40 +187,49 @@ public class Flow implements Cloneable, Serializable { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } Flow other = (Flow) obj; if (actions == null) { - if (other.actions != null) + if (other.actions != null) { return false; - } else if (!actions.equals(other.actions)) + } + } else if (!actions.equals(other.actions)) { return false; - if (hardTimeout != other.hardTimeout) + } + if (hardTimeout != other.hardTimeout) { return false; - if (id != other.id) + } + if (id != other.id) { return false; - if (idleTimeout != other.idleTimeout) + } + if (idleTimeout != other.idleTimeout) { return false; + } if (match == null) { - if (other.match != null) + if (other.match != null) { return false; - } else if (!match.equals(other.match)) + } + } else if (!match.equals(other.match)) { return false; - if (priority != other.priority) + } + if (priority != other.priority) { return false; + } return true; } @Override public String toString() { - return "Flow[match = " + match + ", actions = " + actions - + ", priority = " + priority + ", id = " + id - + ", idleTimeout = " + idleTimeout + ", hardTimeout = " - + hardTimeout + "]"; + return "Flow[match = " + match + ", actions = " + actions + ", priority = " + priority + ", id = " + id + + ", idleTimeout = " + idleTimeout + ", hardTimeout = " + hardTimeout + "]"; } public short getPriority() { @@ -264,7 +268,8 @@ public class Flow implements Cloneable, Serializable { * Adds the specified action to the list of action of this flow * * @param action - * @return false if the passed action is null or not valid or if it fails to add it + * @return false if the passed action is null or not valid or if it fails to + * add it */ public boolean addAction(Action action) { if (action == null || !action.isValid()) { @@ -281,18 +286,21 @@ public class Flow implements Cloneable, Serializable { } /** - * remove ALL actions of type actionType from the list of actions of this flow + * remove ALL actions of type actionType from the list of actions of this + * flow * * @param actionType - * @return false if an action of that type is present and it fails to remove it + * @return false if an action of that type is present and it fails to remove + * it */ public boolean removeAction(ActionType actionType) { Iterator actionIter = this.getActions().iterator(); while (actionIter.hasNext()) { Action action = actionIter.next(); if (action.getType() == actionType) { - if (!this.removeAction(action)) + if (!this.removeAction(action)) { return false; + } } } return true; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerListener.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerListener.java index c66a3de474..c7eace3c98 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerListener.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/IFlowProgrammerListener.java @@ -13,7 +13,6 @@ package org.opendaylight.controller.sal.flowprogrammer; * functional modules the asynchronous messages related to flow programming * coming from the network nodes. */ -public interface IFlowProgrammerListener extends - IPluginOutFlowProgrammerService { +public interface IFlowProgrammerListener extends IPluginOutFlowProgrammerService { } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java index 4dcf2b3c37..9bab839198 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java @@ -202,6 +202,7 @@ public class Match implements Cloneable, Serializable { Match cloned = null; try { cloned = (Match) super.clone(); + cloned.matches = matches; cloned.fields = new HashMap(); for (Entry entry : this.fields.entrySet()) { cloned.fields.put(entry.getKey(), entry.getValue().clone()); @@ -345,20 +346,26 @@ public class Match implements Cloneable, Serializable { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } Match other = (Match) obj; if (fields == null) { - if (other.fields != null) + if (other.fields != null) { return false; - } else if (!fields.equals(other.fields)) + } + } else if (!fields.equals(other.fields)) { return false; - if (matches != other.matches) + } + if (matches != other.matches) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java index bd5ef2bafb..4f3cbbd54b 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java @@ -27,12 +27,11 @@ import org.slf4j.LoggerFactory; @XmlAccessorType(XmlAccessType.NONE) public class MatchField implements Cloneable, Serializable { private static final long serialVersionUID = 1L; - private static final Logger logger = LoggerFactory - .getLogger(MatchField.class); + private static final Logger logger = LoggerFactory.getLogger(MatchField.class); private MatchType type; // the field we want to match private Object value; // the value of the field we want to match private Object mask; // the value of the mask we want to match on the - // specified field + // specified field private transient boolean isValid; // To satisfy JAXB @@ -134,16 +133,11 @@ public class MatchField implements Cloneable, Serializable { private boolean checkValueType() { if (type.isCongruentType(value, mask) == false) { - String valueClass = (value == null) ? "null" : value.getClass() - .getSimpleName(); - String maskClass = (mask == null) ? "null" : mask.getClass() - .getSimpleName(); - String error = "Invalid match field's value or mask types.For field: " - + type.id() - + " Expected:" - + type.dataType().getSimpleName() - + " or equivalent," - + " Got:(" + valueClass + "," + maskClass + ")"; + String valueClass = (value == null) ? "null" : value.getClass().getSimpleName(); + String maskClass = (mask == null) ? "null" : mask.getClass().getSimpleName(); + String error = "Invalid match field's value or mask types.For field: " + type.id() + " Expected:" + + type.dataType().getSimpleName() + " or equivalent," + " Got:(" + valueClass + "," + maskClass + + ")"; throwException(error); return false; } @@ -154,13 +148,9 @@ public class MatchField implements Cloneable, Serializable { if (type.isValid(value, mask) == false) { String maskString = (mask == null) ? "null" : ("0x" + Integer .toHexString(Integer.parseInt(mask.toString()))); - String error = "Invalid match field's value or mask assignement.For field: " - + type.id() - + " Expected: " - + type.getRange() - + ", Got:(0x" - + Integer.toHexString(Integer.parseInt(value.toString())) - + "," + maskString + ")"; + String error = "Invalid match field's value or mask assignement.For field: " + type.id() + " Expected: " + + type.getRange() + ", Got:(0x" + Integer.toHexString(Integer.parseInt(value.toString())) + "," + + maskString + ")"; throwException(error); return false; @@ -188,7 +178,7 @@ public class MatchField implements Cloneable, Serializable { } } } catch (CloneNotSupportedException e) { - logger.error("",e); + logger.error("", e); } return cloned; } @@ -200,12 +190,7 @@ public class MatchField implements Cloneable, Serializable { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mask == null) ? 0 : mask.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; + return type.hashCode(value, mask); } @Override @@ -223,7 +208,6 @@ public class MatchField implements Cloneable, Serializable { if (type != other.type) { return false; } - return (type.equalValues(this.value, other.value) && type.equalMasks( - this.mask, other.mask)); + return (type.equalValues(this.value, other.value) && type.equalMasks(this.mask, other.mask)); } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java index 62c1b435dc..bb5e0079b7 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java @@ -8,6 +8,7 @@ package org.opendaylight.controller.sal.match; +import java.net.Inet6Address; import java.net.InetAddress; import java.util.Arrays; @@ -19,9 +20,6 @@ import org.opendaylight.controller.sal.utils.NetUtils; * Represents the binding between the id, the value and mask type and the range * values of the elements type that can be matched on the network * frame/packet/message - * - * - * */ public enum MatchType { IN_PORT("inPort", 1 << 0, NodeConnector.class, 1, 0), @@ -45,8 +43,7 @@ public enum MatchType { private long minValue; private long maxValue; - private MatchType(String id, int index, Class dataType, long minValue, - long maxValue) { + private MatchType(String id, int index, Class dataType, long minValue, long maxValue) { this.id = id; this.index = index; this.dataType = dataType; @@ -67,8 +64,7 @@ public enum MatchType { } public String getRange() { - return "[0x" + Long.toHexString(minValue) + "-0x" - + Long.toHexString(maxValue) + "]"; + return "[0x" + Long.toHexString(minValue) + "-0x" + Long.toHexString(maxValue) + "]"; } /** @@ -146,13 +142,11 @@ public enum MatchType { val = ((Integer) value).intValue(); msk = (mask != null) ? ((Integer) mask).intValue() : 0; - } else if (value.getClass() == Short.class - || value.getClass() == short.class) { + } else if (value.getClass() == Short.class || value.getClass() == short.class) { val = ((Short) value).intValue() & 0xffff; msk = (mask != null) ? ((Short) mask).intValue() & 0xffff : 0; - } else if (value.getClass() == Byte.class - || value.getClass() == byte.class) { + } else if (value.getClass() == Byte.class || value.getClass() == byte.class) { val = ((Byte) value).intValue() & 0xff; msk = (mask != null) ? ((Byte) mask).intValue() & 0xff : 0; } @@ -178,13 +172,12 @@ public enum MatchType { byte mac[] = (byte[]) mask; long bitmask = 0; for (short i = 0; i < 6; i++) { - bitmask |= (((long) mac[i] & 0xffL) << ((5 - i) * 8)); + bitmask |= ((mac[i] & 0xffL) << ((5 - i) * 8)); } return bitmask; } if (this.dataType == Integer.class || this.dataType == int.class) { - return (mask == null) ? this.maxValue : ((Integer) mask) - .longValue(); + return (mask == null) ? this.maxValue : ((Integer) mask).longValue(); } if (this.dataType == Short.class || this.dataType == short.class) { @@ -208,24 +201,56 @@ public enum MatchType { return HexEncode.bytesToHexStringFormat((byte[]) value); case DL_TYPE: case DL_VLAN: - return ((Integer) NetUtils.getUnsignedShort((Short) value)) - .toString(); + return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString(); case NW_SRC: case NW_DST: return ((InetAddress) value).getHostAddress(); case NW_TOS: - return ((Integer) NetUtils.getUnsignedByte((Byte) value)) - .toString(); + return ((Integer) NetUtils.getUnsignedByte((Byte) value)).toString(); case TP_SRC: case TP_DST: - return ((Integer) NetUtils.getUnsignedShort((Short) value)) - .toString(); + return ((Integer) NetUtils.getUnsignedShort((Short) value)).toString(); default: break; } return value.toString(); } + public int valueHashCode(Object o) { + if (o == null) { + return 0; + } + switch (this) { + case DL_SRC: + case DL_DST: + return NetUtils.byteArray4ToInt((byte[])o); + default: + return o.hashCode(); + } + } + + public int hashCode(Object v, Object m) { + final int prime = 31; + int result = 1; + result = prime * result + this.hashCode(); + + switch (this) { + case DL_SRC: + case DL_DST: + result = prime * result + ((v == null)? 0 : NetUtils.byteArray4ToInt((byte[])v)); + result = prime * result + ((m == null)? 0 : NetUtils.byteArray4ToInt((byte[])m)); + break; + case NW_SRC: + case NW_DST: + result = prime * result + ((v == null)? 0 : v.hashCode()); + result = prime * result + ((m == null)? NetUtils.gethighestIP(v instanceof Inet6Address).hashCode() : m.hashCode()); + break; + default: + result = prime * result + ((v == null)? 0 : v.hashCode()); + result = prime * result + ((m == null)? 0 : m.hashCode()); + } + return result; + } public boolean equalValues(Object a, Object b) { if (a == b) { return true; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java index fe93d1c985..6466177ecd 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/reader/FlowOnNode.java @@ -38,6 +38,7 @@ public class FlowOnNode { private long byteCount; /* Dummy constructor for JAXB */ + @SuppressWarnings("unused") private FlowOnNode () { } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java index 90a7803ba0..8e76c3fc60 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/NetUtils.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -19,15 +18,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Utility class containing the common utility functions needed - * for operating on networking data structures - * - * - * + * Utility class containing the common utility functions needed for operating on + * networking data structures */ public abstract class NetUtils { - protected static final Logger logger = LoggerFactory - .getLogger(NetUtils.class); + protected static final Logger logger = LoggerFactory.getLogger(NetUtils.class); /** * Constant holding the number of bits in a byte */ @@ -36,15 +31,15 @@ public abstract class NetUtils { /** * Converts a 4 bytes array into an integer number * - * @param ba the 4 bytes long byte array - * @return the integer number + * @param ba + * the 4 bytes long byte array + * @return the integer number */ public static int byteArray4ToInt(byte[] ba) { if (ba == null || ba.length != 4) { return 0; } - return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 - | (0xff & ba[2]) << 8 | (0xff & ba[3]); + return (0xff & ba[0]) << 24 | (0xff & ba[1]) << 16 | (0xff & ba[2]) << 8 | (0xff & ba[3]); } /** @@ -65,45 +60,47 @@ public abstract class NetUtils { /** * Converts an integer number into a 4 bytes array * - * @param i the integer number - * @return the byte array + * @param i + * the integer number + * @return the byte array */ public static byte[] intToByteArray4(int i) { - return new byte[] { (byte) ((i >> 24) & 0xff), - (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff), + return new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff), (byte) (i & 0xff) }; } /** - * Converts an IP address passed as integer value into the - * respective InetAddress object + * Converts an IP address passed as integer value into the respective + * InetAddress object * - * @param address the IP address in integer form - * @return the IP address in InetAddress form + * @param address + * the IP address in integer form + * @return the IP address in InetAddress form */ public static InetAddress getInetAddress(int address) { InetAddress ip = null; try { ip = InetAddress.getByAddress(NetUtils.intToByteArray4(address)); } catch (UnknownHostException e) { - logger.error("",e); + logger.error("", e); } return ip; } /** - * Return the InetAddress Network Mask given the length of the prefix bit mask. - * The prefix bit mask indicates the contiguous leading bits that are NOT masked out. - * Example: A prefix bit mask length of 8 will give an InetAddress Network Mask of 255.0.0.0 + * Return the InetAddress Network Mask given the length of the prefix bit + * mask. The prefix bit mask indicates the contiguous leading bits that are + * NOT masked out. Example: A prefix bit mask length of 8 will give an + * InetAddress Network Mask of 255.0.0.0 * - * @param prefixMaskLength integer representing the length of the prefix network mask - * @param isV6 boolean representing the IP version of the returned address + * @param prefixMaskLength + * integer representing the length of the prefix network mask + * @param isV6 + * boolean representing the IP version of the returned address * @return */ - public static InetAddress getInetNetworkMask(int prefixMaskLength, - boolean isV6) { - if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) - || (isV6 && prefixMaskLength > 128)) { + public static InetAddress getInetNetworkMask(int prefixMaskLength, boolean isV6) { + if (prefixMaskLength < 0 || (!isV6 && prefixMaskLength > 32) || (isV6 && prefixMaskLength > 128)) { return null; } byte v4Address[] = { 0, 0, 0, 0 }; @@ -126,19 +123,20 @@ public abstract class NetUtils { try { return InetAddress.getByAddress(address); } catch (UnknownHostException e) { - logger.error("",e); + logger.error("", e); } return null; } /** - * Returns the number of contiguous bits belonging to the subnet, that have to be masked out - * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8, - * while ff.00.00.00 will return a subnet mask length of 24. - * If the passed prefixMask object is null, 0 is returned + * Returns the number of contiguous bits belonging to the subnet, that have + * to be masked out Example: A prefix network byte mask of ff.ff.ff.00 will + * give a subnet mask length of 8, while ff.00.00.00 will return a subnet + * mask length of 24. If the passed prefixMask object is null, 0 is returned * - * @param prefixMask the prefix mask as byte array - * @return the length of the prefix network mask + * @param prefixMask + * the prefix mask as byte array + * @return the length of the prefix network mask */ public static int getSubnetMaskLength(byte[] prefixMask) { int maskLength = 0; @@ -160,27 +158,29 @@ public abstract class NetUtils { } /** - * Returns the number of contiguous bits belonging to the subnet, that have to be masked out - * Example: A prefix network byte mask of ff.ff.ff.00 will give a subnet mask length of 8, - * while ff.00.00.00 will return a subnet mask length of 24 - * If the passed prefixMask object is null, 0 is returned + * Returns the number of contiguous bits belonging to the subnet, that have + * to be masked out Example: A prefix network byte mask of ff.ff.ff.00 will + * give a subnet mask length of 8, while ff.00.00.00 will return a subnet + * mask length of 24 If the passed prefixMask object is null, 0 is returned * - * @param prefixMask the prefix mask as InetAddress - * @return the length of the prefix network mask + * @param prefixMask + * the prefix mask as InetAddress + * @return the length of the prefix network mask */ public static int getSubnetMaskLength(InetAddress prefixMask) { - return (prefixMask == null) ? 0 : NetUtils - .getSubnetMaskLength(prefixMask.getAddress()); + return (prefixMask == null) ? 0 : NetUtils.getSubnetMaskLength(prefixMask.getAddress()); } /** - * Given an IP address and a prefix network mask length, it returns - * the equivalent subnet prefix IP address - * Example: for ip = "172.28.30.254" and maskLen = 25 it will return "172.28.30.128" + * Given an IP address and a prefix network mask length, it returns the + * equivalent subnet prefix IP address Example: for ip = "172.28.30.254" and + * maskLen = 25 it will return "172.28.30.128" * - * @param ip the IP address in InetAddress form - * @param maskLen the length of the prefix network mask - * @return the subnet prefix IP address in InetAddress form + * @param ip + * the IP address in InetAddress form + * @param maskLen + * the length of the prefix network mask + * @return the subnet prefix IP address in InetAddress form */ public static InetAddress getSubnetPrefix(InetAddress ip, int maskLen) { int bytes = maskLen / 8; @@ -203,17 +203,14 @@ public abstract class NetUtils { } /** - * Checks if the test address and mask conflicts with - * the filter address and mask + * Checks if the test address and mask conflicts with the filter address and + * mask * - * For example: - * testAddress: 172.28.2.23 testMask: 255.255.255.0 - * filtAddress: 172.28.1.10 testMask: 255.255.255.0 - * conflict + * For example: testAddress: 172.28.2.23 testMask: 255.255.255.0 + * filtAddress: 172.28.1.10 testMask: 255.255.255.0 conflict * - * testAddress: 172.28.2.23 testMask: 255.255.255.0 - * filtAddress: 172.28.1.10 testMask: 255.255.0.0 - * do not conflict + * testAddress: 172.28.2.23 testMask: 255.255.255.0 filtAddress: 172.28.1.10 + * testMask: 255.255.0.0 do not conflict * * Null parameters are permitted * @@ -223,8 +220,7 @@ public abstract class NetUtils { * @param filterMask * @return */ - public static boolean inetAddressConflict(InetAddress testAddress, - InetAddress filterAddress, InetAddress testMask, + public static boolean inetAddressConflict(InetAddress testAddress, InetAddress filterAddress, InetAddress testMask, InetAddress filterMask) { // Sanity check if ((testAddress == null) || (filterAddress == null)) { @@ -256,8 +252,9 @@ public abstract class NetUtils { /** * Returns true if the passed MAC address is all zero * - * @param mac the byte array representing the MAC address - * @return true if all MAC bytes are zero + * @param mac + * the byte array representing the MAC address + * @return true if all MAC bytes are zero */ public static boolean isZeroMAC(byte[] mac) { for (short i = 0; i < 6; i++) { @@ -271,8 +268,9 @@ public abstract class NetUtils { /** * Returns true if the passed InetAddress contains all zero * - * @param ip the IP address to test - * @return true if the address is all zero + * @param ip + * the IP address to test + * @return true if the address is all zero */ public static boolean isAny(InetAddress ip) { for (byte b : ip.getAddress()) { @@ -295,16 +293,17 @@ public abstract class NetUtils { try { address = InetAddress.getByName(addressString); } catch (UnknownHostException e) { - logger.error("",e); + logger.error("", e); } return address; } /** - * Checks if the passed IP v4 address in string form is valid - * The address may specify a mask at the end as "/MM" + * Checks if the passed IP v4 address in string form is valid The address + * may specify a mask at the end as "/MM" * - * @param cidr the v4 address as A.B.C.D/MM + * @param cidr + * the v4 address as A.B.C.D/MM * @return */ public static boolean isIPv4AddressValid(String cidr) { @@ -329,10 +328,11 @@ public abstract class NetUtils { } /** - * Checks if the passed IP v6 address in string form is valid - * The address may specify a mask at the end as "/MMM" + * Checks if the passed IP v6 address in string form is valid The address + * may specify a mask at the end as "/MMM" * - * @param cidr the v6 address as A::1/MMM + * @param cidr + * the v6 address as A::1/MMM * @return */ public static boolean isIPv6AddressValid(String cidr) { @@ -342,7 +342,8 @@ public abstract class NetUtils { String values[] = cidr.split("/"); try { - //when given an IP address, InetAddress.getByName validates the ip address + // when given an IP address, InetAddress.getByName validates the ip + // address InetAddress addr = InetAddress.getByName(values[0]); if (!(addr instanceof Inet6Address)) { return false; @@ -369,32 +370,48 @@ public abstract class NetUtils { * @return */ public static boolean isIPAddressValid(String cidr) { - return NetUtils.isIPv4AddressValid(cidr) - || NetUtils.isIPv6AddressValid(cidr); + return NetUtils.isIPv4AddressValid(cidr) || NetUtils.isIPv6AddressValid(cidr); } /* - * Following utilities are useful when you need to - * compare or bit shift java primitive type variable - * which are inerently signed + * Following utilities are useful when you need to compare or bit shift java + * primitive type variable which are inerently signed */ /** * Returns the unsigned value of the passed byte variable * - * @param b the byte value + * @param b + * the byte value * @return the int variable containing the unsigned byte value */ public static int getUnsignedByte(byte b) { - return (b > 0)? (int)b : (b & 0x7F | 0x80); + return (b > 0) ? (int) b : (b & 0x7F | 0x80); } /** * Return the unsigned value of the passed short variable * - * @param s the short value + * @param s + * the short value * @return the int variable containing the unsigned short value */ public static int getUnsignedShort(short s) { - return (s > 0)? (int)s : (s & 0x7FFF | 0x8000); + return (s > 0) ? (int) s : (s & 0x7FFF | 0x8000); + } + + /** + * Returns the highest v4 or v6 InetAddress + * + * @param v6 + * true for IPv6, false for Ipv4 + * @return The highest IPv4 or IPv6 address + */ + public static InetAddress gethighestIP(boolean v6) { + try { + return (v6) ? InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") : InetAddress + .getByName("255.255.255.255"); + } catch (UnknownHostException e) { + return null; + } } } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java index 5ec7d089b6..cfa53fb7f3 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -29,8 +28,7 @@ public class MatchTest { @Test public void testMatchCreation() { Node node = NodeCreator.createOFNode(7l); - NodeConnector port = NodeConnectorCreator.createOFNodeConnector( - (short) 6, node); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 6, node); MatchField field = new MatchField(MatchType.IN_PORT, port); Assert.assertTrue(field != null); @@ -50,10 +48,8 @@ public class MatchTest { field = new MatchField(MatchType.TP_SRC, 120000); Assert.assertFalse(field.isValid()); - byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, - (byte) 11, (byte) 22 }; - byte mask[] = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff }; + byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, (byte) 11, (byte) 22 }; + byte mask[] = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }; field = null; field = new MatchField(MatchType.DL_SRC, mac, mask); Assert.assertFalse(field.getValue() == null); @@ -67,39 +63,30 @@ public class MatchTest { public void testMatchSetGet() { Match x = new Match(); short val = 2346; - NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector(val, - NodeCreator.createOFNode(1l)); + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector(val, NodeCreator.createOFNode(1l)); x.setField(MatchType.IN_PORT, inPort); - Assert.assertTrue(((NodeConnector) x.getField(MatchType.IN_PORT) - .getValue()).equals(inPort)); - Assert - .assertTrue((Short) ((NodeConnector) x.getField( - MatchType.IN_PORT).getValue()).getID() == val); + Assert.assertTrue(((NodeConnector) x.getField(MatchType.IN_PORT).getValue()).equals(inPort)); + Assert.assertTrue((Short) ((NodeConnector) x.getField(MatchType.IN_PORT).getValue()).getID() == val); } @Test public void testMatchSetGetMAC() { Match x = new Match(); - byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, - (byte) 11, (byte) 22 }; + byte mac[] = { (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd, (byte) 11, (byte) 22 }; byte mac2[] = { (byte) 0xaa, (byte) 0xbb, 0, 0, 0, (byte) 0xbb }; - byte mask1[] = { (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, - (byte) 0x55, (byte) 0x66 }; - byte mask2[] = { (byte) 0xff, (byte) 0xff, (byte) 0, (byte) 0, - (byte) 0, (byte) 0xff }; + byte mask1[] = { (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66 }; + byte mask2[] = { (byte) 0xff, (byte) 0xff, (byte) 0, (byte) 0, (byte) 0, (byte) 0xff }; x.setField(MatchType.DL_SRC, mac.clone(), mask1); x.setField(MatchType.DL_DST, mac2.clone(), mask2); - Assert.assertTrue(Arrays.equals(mac, (byte[]) x.getField( - MatchType.DL_SRC).getValue())); - Assert.assertFalse(Arrays.equals((byte[]) x.getField(MatchType.DL_SRC) - .getValue(), (byte[]) x.getField(MatchType.DL_DST).getValue())); - Assert.assertFalse(x.getField(MatchType.DL_SRC).getBitMask() == x - .getField(MatchType.DL_DST).getBitMask()); + Assert.assertTrue(Arrays.equals(mac, (byte[]) x.getField(MatchType.DL_SRC).getValue())); + Assert.assertFalse(Arrays.equals((byte[]) x.getField(MatchType.DL_SRC).getValue(), + (byte[]) x.getField(MatchType.DL_DST).getValue())); + Assert.assertFalse(x.getField(MatchType.DL_SRC).getBitMask() == x.getField(MatchType.DL_DST).getBitMask()); x.setField(new MatchField(MatchType.DL_DST, mac.clone(), mask1)); - Assert.assertTrue(Arrays.equals((byte[]) x.getField(MatchType.DL_SRC) - .getValue(), (byte[]) x.getField(MatchType.DL_DST).getValue())); + Assert.assertTrue(Arrays.equals((byte[]) x.getField(MatchType.DL_SRC).getValue(), + (byte[]) x.getField(MatchType.DL_DST).getValue())); } @Test @@ -110,8 +97,7 @@ public class MatchTest { InetAddress mask = InetAddress.getByName("255.255.0.0"); x.setField(MatchType.NW_SRC, address, mask); - Assert.assertTrue(ip.equals(((InetAddress) x.getField(MatchType.NW_SRC) - .getValue()).getHostAddress())); + Assert.assertTrue(ip.equals(((InetAddress) x.getField(MatchType.NW_SRC).getValue()).getHostAddress())); Assert.assertTrue(x.getField(MatchType.NW_SRC).getMask().equals(mask)); } @@ -119,21 +105,14 @@ public class MatchTest { public void testMatchSetGetEtherType() throws UnknownHostException { Match x = new Match(); - x.setField(MatchType.DL_TYPE, EtherTypes.QINQ.shortValue(), - (short) 0xffff); - Assert.assertTrue(((Short) x.getField(MatchType.DL_TYPE).getValue()) - .equals(EtherTypes.QINQ.shortValue())); - Assert - .assertFalse(x.getField(MatchType.DL_TYPE).getValue() == EtherTypes.QINQ); - Assert.assertFalse(x.getField(MatchType.DL_TYPE).getValue().equals( - EtherTypes.QINQ)); - - x.setField(MatchType.DL_TYPE, EtherTypes.LLDP.shortValue(), - (short) 0xffff); - Assert.assertTrue(((Short) x.getField(MatchType.DL_TYPE).getValue()) - .equals(EtherTypes.LLDP.shortValue())); - Assert.assertFalse(x.getField(MatchType.DL_TYPE).equals( - EtherTypes.LLDP.intValue())); + x.setField(MatchType.DL_TYPE, EtherTypes.QINQ.shortValue(), (short) 0xffff); + Assert.assertTrue(((Short) x.getField(MatchType.DL_TYPE).getValue()).equals(EtherTypes.QINQ.shortValue())); + Assert.assertFalse(x.getField(MatchType.DL_TYPE).getValue() == EtherTypes.QINQ); + Assert.assertFalse(x.getField(MatchType.DL_TYPE).getValue().equals(EtherTypes.QINQ)); + + x.setField(MatchType.DL_TYPE, EtherTypes.LLDP.shortValue(), (short) 0xffff); + Assert.assertTrue(((Short) x.getField(MatchType.DL_TYPE).getValue()).equals(EtherTypes.LLDP.shortValue())); + Assert.assertFalse(x.getField(MatchType.DL_TYPE).equals(EtherTypes.LLDP.intValue())); } @Test @@ -161,24 +140,18 @@ public class MatchTest { @Test public void testMatchMask() { Match x = new Match(); - NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector( - (short) 6, NodeCreator.createOFNode(3l)); + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector((short) 6, NodeCreator.createOFNode(3l)); x.setField(MatchType.IN_PORT, inPort); x.setField(MatchType.DL_VLAN, (short) 28, (short) 0xfff); Assert.assertFalse(x.getMatches() == 0); - Assert - .assertTrue(x.getMatches() == (MatchType.IN_PORT.getIndex() | MatchType.DL_VLAN - .getIndex())); + Assert.assertTrue(x.getMatches() == (MatchType.IN_PORT.getIndex() | MatchType.DL_VLAN.getIndex())); } @Test public void testMatchBitMask() { - byte mac[] = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 22, (byte) 12 }; - byte mask[] = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0 }; - NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector( - (short) 4095, NodeCreator.createOFNode(7l)); + byte mac[] = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 22, (byte) 12 }; + byte mask[] = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0 }; + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector((short) 4095, NodeCreator.createOFNode(7l)); MatchField x = new MatchField(MatchType.IN_PORT, inPort); Assert.assertTrue((x.getMask()) == null); @@ -193,10 +166,8 @@ public class MatchTest { @Test public void testNullMask() { - byte mac[] = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 22, (byte) 12 }; - NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector( - (short) 2000, NodeCreator.createOFNode(7l)); + byte mac[] = { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 22, (byte) 12 }; + NodeConnector inPort = NodeConnectorCreator.createOFNodeConnector((short) 2000, NodeCreator.createOFNode(7l)); MatchField x = new MatchField(MatchType.IN_PORT, inPort); Assert.assertTrue(x.getBitMask() == 0); @@ -214,41 +185,26 @@ public class MatchTest { @Test public void testEquality() throws Exception { Node node = NodeCreator.createOFNode(7l); - NodeConnector port = NodeConnectorCreator.createOFNodeConnector( - (short) 24, node); - NodeConnector port2 = NodeConnectorCreator.createOFNodeConnector( - (short) 24, node); - byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, - (byte) 0x9a, (byte) 0xbc }; - byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, - (byte) 0x5e, (byte) 0x6f }; - byte srcMac2[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, - (byte) 0x9a, (byte) 0xbc }; - byte dstMac2[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, - (byte) 0x5e, (byte) 0x6f }; - InetAddress srcIP = InetAddress - .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); - InetAddress dstIP = InetAddress - .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress ipMask = InetAddress - .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); - InetAddress ipMaskd = InetAddress - .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); - InetAddress srcIP2 = InetAddress - .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); - InetAddress dstIP2 = InetAddress - .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress ipMask2 = InetAddress - .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); - InetAddress ipMaskd2 = InetAddress - .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 24, node); + NodeConnector port2 = NodeConnectorCreator.createOFNodeConnector((short) 24, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + byte srcMac2[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac2[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress.getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask = InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + InetAddress srcIP2 = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP2 = InetAddress.getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMask2 = InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd2 = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); short ethertype = EtherTypes.IPv6.shortValue(); short ethertype2 = EtherTypes.IPv6.shortValue(); short vlan = (short) 27, vlan2 = (short) 27; byte vlanPr = (byte) 3, vlanPr2 = (byte) 3; Byte tos = 4, tos2 = 4; - byte proto = IPProtocols.UDP.byteValue(), proto2 = IPProtocols.UDP - .byteValue(); + byte proto = IPProtocols.UDP.byteValue(), proto2 = IPProtocols.UDP.byteValue(); short src = (short) 5500, src2 = (short) 5500; short dst = 80, dst2 = 80; @@ -288,8 +244,7 @@ public class MatchTest { // Make sure all values are equals for (MatchType type : MatchType.values()) { if (match1.isPresent(type)) { - Assert.assertTrue(match1.getField(type).equals( - match2.getField(type))); + Assert.assertTrue(match1.getField(type).equals(match2.getField(type))); } } @@ -347,23 +302,66 @@ public class MatchTest { Assert.assertTrue(match1.equals(match2)); } + @Test + public void testHashCode() throws Exception { + byte srcMac1[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte srcMac2[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac1[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + byte dstMac2[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + short ethertype = EtherTypes.IPv4.shortValue(); + short ethertype2 = EtherTypes.IPv4.shortValue(); + InetAddress srcIP1 = InetAddress.getByName("1.1.1.1"); + InetAddress ipMask1 = InetAddress.getByName("255.255.255.255"); + InetAddress srcIP2 = InetAddress.getByName("1.1.1.1"); + InetAddress ipMask2 = InetAddress.getByName("255.255.255.255"); + + Match match1 = new Match(); + Match match2 = new Match(); + + MatchField field1 = new MatchField(MatchType.DL_SRC, srcMac1); + MatchField field2 = new MatchField(MatchType.DL_SRC, srcMac2); + Assert.assertTrue(field1.hashCode() == field2.hashCode()); + + match1.setField(field1); + match2.setField(field2); + Assert.assertTrue(match1.hashCode() == match2.hashCode()); + + MatchField field3 = new MatchField(MatchType.DL_DST, dstMac1); + MatchField field4 = new MatchField(MatchType.DL_DST, dstMac2); + Assert.assertTrue(field3.hashCode() == field4.hashCode()); + + match1.setField(field3); + match2.setField(field4); + Assert.assertTrue(match1.hashCode() == match2.hashCode()); + + MatchField field5 = new MatchField(MatchType.DL_TYPE, ethertype); + MatchField field6 = new MatchField(MatchType.DL_TYPE, ethertype2); + Assert.assertTrue(field5.hashCode() == field6.hashCode()); + + match1.setField(field5); + match2.setField(field6); + Assert.assertTrue(match1.hashCode() == match2 .hashCode()); + + MatchField field7 = new MatchField(MatchType.NW_SRC, srcIP1, ipMask1); + MatchField field8 = new MatchField(MatchType.NW_SRC, srcIP2, ipMask2); + Assert.assertTrue(field7.hashCode() == field8.hashCode()); + + match1.setField(field7); + match2.setField(field8); + Assert.assertTrue(match1.hashCode() == match2.hashCode()); + + } + @Test public void testCloning() throws Exception { Node node = NodeCreator.createOFNode(7l); - NodeConnector port = NodeConnectorCreator.createOFNodeConnector( - (short) 24, node); - byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, - (byte) 0x9a, (byte) 0xbc }; - byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, - (byte) 0x5e, (byte) 0x6f }; - InetAddress srcIP = InetAddress - .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); - InetAddress dstIP = InetAddress - .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress ipMasks = InetAddress - .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); - InetAddress ipMaskd = InetAddress - .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 24, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress.getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMasks = InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); short ethertype = EtherTypes.IPv6.shortValue(); short vlan = (short) 27; byte vlanPr = (byte) 3; @@ -395,13 +393,13 @@ public class MatchTest { for (MatchType type : MatchType.values()) { if (match.isPresent(type)) { if (!match.getField(type).equals(cloned.getField(type))) { - Assert.assertTrue(match.getField(type).equals( - cloned.getField(type))); + Assert.assertTrue(match.getField(type).equals(cloned.getField(type))); } } } - // Make sure none of the fields couples are pointing to the same reference + // Make sure none of the fields couples are pointing to the same + // reference MatchField a = null, b = null; for (MatchType type : MatchType.values()) { a = match.getField(type); @@ -413,31 +411,23 @@ public class MatchTest { Assert.assertTrue(match.equals(cloned)); - Assert.assertFalse(match.getField(MatchType.DL_SRC) == cloned - .getField(MatchType.DL_SRC)); - Assert.assertFalse(match.getField(MatchType.NW_DST) == cloned - .getField(MatchType.NW_DST)); - Assert.assertTrue(match.getField(MatchType.NW_DST).getMask().equals( - cloned.getField(MatchType.NW_DST).getMask())); + Assert.assertFalse(match.getField(MatchType.DL_SRC) == cloned.getField(MatchType.DL_SRC)); + Assert.assertFalse(match.getField(MatchType.NW_DST) == cloned.getField(MatchType.NW_DST)); + Assert.assertTrue(match.getField(MatchType.NW_DST).getMask() + .equals(cloned.getField(MatchType.NW_DST).getMask())); + Assert.assertTrue(match.hashCode() == cloned.hashCode()); } @Test public void testFlip() throws Exception { Node node = NodeCreator.createOFNode(7l); - NodeConnector port = NodeConnectorCreator.createOFNodeConnector( - (short) 24, node); - byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, - (byte) 0x9a, (byte) 0xbc }; - byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, - (byte) 0x5e, (byte) 0x6f }; - InetAddress srcIP = InetAddress - .getByName("2001:420:281:1004:407a:57f4:4d15:c355"); - InetAddress dstIP = InetAddress - .getByName("2001:420:281:1004:e123:e688:d655:a1b0"); - InetAddress ipMasks = InetAddress - .getByName("ffff:ffff:ffff:ffff:0:0:0:0"); - InetAddress ipMaskd = InetAddress - .getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); + NodeConnector port = NodeConnectorCreator.createOFNodeConnector((short) 24, node); + byte srcMac[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; + byte dstMac[] = { (byte) 0x1a, (byte) 0x2b, (byte) 0x3c, (byte) 0x4d, (byte) 0x5e, (byte) 0x6f }; + InetAddress srcIP = InetAddress.getByName("2001:420:281:1004:407a:57f4:4d15:c355"); + InetAddress dstIP = InetAddress.getByName("2001:420:281:1004:e123:e688:d655:a1b0"); + InetAddress ipMasks = InetAddress.getByName("ffff:ffff:ffff:ffff:0:0:0:0"); + InetAddress ipMaskd = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"); short ethertype = EtherTypes.IPv6.shortValue(); short vlan = (short) 27; byte vlanPr = (byte) 3; @@ -465,25 +455,20 @@ public class MatchTest { Match flipped = match.reverse(); - Assert.assertTrue(match.getField(MatchType.DL_TYPE).equals( - flipped.getField(MatchType.DL_TYPE))); - Assert.assertTrue(match.getField(MatchType.DL_VLAN).equals( - flipped.getField(MatchType.DL_VLAN))); - - Assert.assertTrue(match.getField(MatchType.DL_DST).getValue().equals( - flipped.getField(MatchType.DL_SRC).getValue())); - Assert.assertTrue(match.getField(MatchType.DL_DST).getMask() == flipped - .getField(MatchType.DL_SRC).getMask()); - - Assert.assertTrue(match.getField(MatchType.NW_DST).getValue().equals( - flipped.getField(MatchType.NW_SRC).getValue())); - Assert.assertTrue(match.getField(MatchType.NW_DST).getMask() == flipped - .getField(MatchType.NW_SRC).getMask()); - - Assert.assertTrue(match.getField(MatchType.TP_DST).getValue().equals( - flipped.getField(MatchType.TP_SRC).getValue())); - Assert.assertTrue(match.getField(MatchType.TP_DST).getMask() == flipped - .getField(MatchType.TP_SRC).getMask()); + Assert.assertTrue(match.getField(MatchType.DL_TYPE).equals(flipped.getField(MatchType.DL_TYPE))); + Assert.assertTrue(match.getField(MatchType.DL_VLAN).equals(flipped.getField(MatchType.DL_VLAN))); + + Assert.assertTrue(match.getField(MatchType.DL_DST).getValue() + .equals(flipped.getField(MatchType.DL_SRC).getValue())); + Assert.assertTrue(match.getField(MatchType.DL_DST).getMask() == flipped.getField(MatchType.DL_SRC).getMask()); + + Assert.assertTrue(match.getField(MatchType.NW_DST).getValue() + .equals(flipped.getField(MatchType.NW_SRC).getValue())); + Assert.assertTrue(match.getField(MatchType.NW_DST).getMask() == flipped.getField(MatchType.NW_SRC).getMask()); + + Assert.assertTrue(match.getField(MatchType.TP_DST).getValue() + .equals(flipped.getField(MatchType.TP_SRC).getValue())); + Assert.assertTrue(match.getField(MatchType.TP_DST).getMask() == flipped.getField(MatchType.TP_SRC).getMask()); Match flipflip = flipped.reverse().reverse(); Assert.assertTrue(flipflip.equals(flipped)); diff --git a/opendaylight/web/flows/src/main/resources/js/page.js b/opendaylight/web/flows/src/main/resources/js/page.js index 577570f431..59557dccd2 100644 --- a/opendaylight/web/flows/src/main/resources/js/page.js +++ b/opendaylight/web/flows/src/main/resources/js/page.js @@ -372,7 +372,7 @@ one.f.flows = { }); // toggle button var toggle; - if (flow['flow']['installInHw'] == 'true') { + if (flow['flow']['installInHw'] == 'true' && flow['flow']['status'] == 'Success') { toggle = one.lib.dashlet.button.single("Uninstall Flow", one.f.flows.id.dashlet.toggle, "btn-warning", "btn-mini"); } else { toggle = one.lib.dashlet.button.single("Install Flow", one.f.flows.id.dashlet.toggle, "btn-success", "btn-mini"); @@ -1177,9 +1177,11 @@ one.f.flows = { var entry = []; entry.push(value['name']); entry.push(value['node']); - if (value['flow']['installInHw'] == 'true') + if (value['flow']['installInHw'] == 'true' && value['flow']['status'] == 'Success') tr['type'] = ['success']; - else if (value['flow']['installInHw'] == 'false') + else if (value['flow']['installInHw'] == 'false' && value['flow']['status'] == 'Success') + tr['type'] = ['warning']; + else tr['type'] = ['warning']; tr['entry'] = entry; tr['id'] = value['nodeId'];