- 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 <aboch@cisco.com>
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;
* 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;
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<String> 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<String> actions) {
super();
this.installInHw = installInHw;
this.name = name;
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() {
@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) {
}
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<String> getActions() {
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;
}
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;
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<ContainerFlow> cFlowList = container.getContainerFlows();
if (((cFlowList == null)) || cFlowList.isEmpty()) {
- return false;
+ return new Status(StatusCode.SUCCESS);
}
// Check against each container's flow
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)) {
}
}
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;
}
}
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;
}
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) {
} 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));
}
}
} 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;
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);
}
}
}
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());
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";
}
/*
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;
}
}
* 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
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() {
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);
+ }
}
package org.opendaylight.controller.forwardingrulesmanager;
+import java.io.Serializable;
+
import org.opendaylight.controller.sal.core.ContainerFlow;
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;
}
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 + "]";
}
}
/**
* Interface that describes methods for installing or removing forwarding rules
* and to access to the flows database.
- *
*/
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
* 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
* 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
*/
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
* @param dstPort
* the list of ports to be added to the flow output actions
*/
- public void addOutputPort(Node node, String flowName,
- List<NodeConnector> dstPort);
+ public void addOutputPort(Node node, String flowName, List<NodeConnector> dstPort);
/**
* Remove a list of output port from the flow with the specified name on the
* @param dstPortthe
* list of ports to be removed from the flow output actions
*/
- public void removeOutputPort(Node node, String flowName,
- List<NodeConnector> dstPort);
+ public void removeOutputPort(Node node, String flowName, List<NodeConnector> dstPort);
/**
* Replace the current output port in the specified flow with the specified
* @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
/**
* The interface which describes the methods forwarding rules manager will call
* for notifying the listeners of policy installation updates.
- *
*/
public interface IForwardingRulesManagerAware {
*
* PortGroup is used by PortGroupProvider application to signal a set of ports
* that represent a configured PortGroupConfig.
- *
- *
*/
public class PortGroup {
private long matrixSwitchId;
@Override
public String toString() {
- return "PortGroup [matrixSwitchId=" + matrixSwitchId + ", ports="
- + ports + "]";
+ return "PortGroup [matrixSwitchId=" + matrixSwitchId + ", ports=" + ports + "]";
}
}
* true indicates that the PortGroup is added. False indicates
* that the PortGroup is removed.
*/
- void portGroupChanged(PortGroupConfig config,
- Map<Node, PortGroup> portGroupData, boolean add);
+ void portGroupChanged(PortGroupConfig config, Map<Node, PortGroup> portGroupData, boolean add);
}
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;
}
@Override
public String toString() {
- return "PortGroupConfig [name=" + name + ", matchString=" + matchString
- + "]";
+ return "PortGroupConfig [name=" + name + ", matchString=" + matchString + "]";
}
}
* @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
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;
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;
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()));
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)));
}
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"));
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<FlowEntry, FlowEntry> map = new ConcurrentHashMap<FlowEntry, FlowEntry>();
+ 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<FlowEntryInstall, FlowEntryInstall> map =
+ new ConcurrentHashMap<FlowEntryInstall, FlowEntryInstall>();
+ 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));
}
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));
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"));
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");
@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());
}
@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());
}
ArrayList<String> 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;
}
}
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;
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);
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
// 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));
}
}
}
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;
* 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<Long, String>, CommandProvider,
- IFlowProgrammerListener {
+public class ForwardingRulesManagerImpl implements IForwardingRulesManager, PortGroupChangeListener,
+ IContainerListener, ISwitchManagerAware, IConfigurationContainerAware, IInventoryListener, IObjectReader,
+ ICacheUpdateAware<Long, String>, 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<Long, String> flowsSaveEvent;
private String frmFileName;
private String portGroupFileName;
private ConcurrentMap<String, PortGroupConfig> portGroupConfigs;
private ConcurrentMap<PortGroupConfig, Map<Node, PortGroup>> portGroupData;
private ConcurrentMap<String, Object> 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<Node, Set<FlowEntryInstall>> nodeFlows;
- private ConcurrentMap<String, Set<FlowEntryInstall>> groupFlows;
+ private ConcurrentMap<FlowEntry, FlowEntry> originalSwView;
+ private ConcurrentMap<FlowEntryInstall, FlowEntryInstall> installedSwView;
+ /*
+ * Per node and per group indexing
+ */
+ private ConcurrentMap<Node, List<FlowEntryInstall>> nodeFlows;
+ private ConcurrentMap<String, List<FlowEntryInstall>> 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
private IFlowProgrammerService programmer;
private IClusterContainerServices clusterContainerService = null;
private ISwitchManager switchManager;
+ private Thread frmEventHandler;
+ protected BlockingQueue<FRMEvent> pendingEvents;
/**
* Adds a flow entry onto the network node It runs various validity checks
* 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) {
* 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<FlowEntryInstall> toInstallList = deriveInstallEntries(
- flowEntry.clone(), container.getContainerFlows());
+ List<FlowEntryInstall> toInstallList = deriveInstallEntries(flowEntry.clone(), container.getContainerFlows());
// Container Flow conflict Check
if (toInstallList.isEmpty()) {
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;
}
// 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);
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());
}
}
* @return the list of container flow merged entries good to be installed on
* this container
*/
- private List<FlowEntryInstall> deriveInstallEntries(FlowEntry request,
- List<ContainerFlow> cFlowList) {
- List<FlowEntryInstall> toInstallList = new ArrayList<FlowEntryInstall>(
- 1);
+ private List<FlowEntryInstall> deriveInstallEntries(FlowEntry request, List<ContainerFlow> cFlowList) {
+ List<FlowEntryInstall> toInstallList = new ArrayList<FlowEntryInstall>(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 {
// 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));
}
}
}
* @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);
}
// 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<FlowEntryInstall> installedList = deriveInstallEntries(
- currentFlowEntry.clone(), container.getContainerFlows());
- List<FlowEntryInstall> toInstallList = deriveInstallEntries(
- newFlowEntry.clone(), container.getContainerFlows());
+ List<FlowEntryInstall> installedList = deriveInstallEntries(currentFlowEntry.clone(),
+ container.getContainerFlows());
+ List<FlowEntryInstall> 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);
}
List<FlowEntryInstall> toInstallSafe = new ArrayList<FlowEntryInstall>();
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);
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 {
}
// 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 {
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;
}
* @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());
* (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
}
// Derive the container flows merged installed entries
- List<FlowEntryInstall> installedList = deriveInstallEntries(
- flowEntry.clone(), container.getContainerFlows());
+ List<FlowEntryInstall> installedList = deriveInstallEntries(flowEntry.clone(), container.getContainerFlows());
- Set<FlowEntryInstall> 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) {
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;
* 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());
* 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;
}
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);
/*
* 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<FlowEntryInstall> flowEntrylist = this.nodeFlows.get(node);
- if (flowEntrylist == null) {
- if (add == false) {
+ List<FlowEntryInstall> nodeIndeces = this.nodeFlows.get(node);
+ if (nodeIndeces == null) {
+ if (!add) {
return;
} else {
- flowEntrylist = new HashSet<FlowEntryInstall>();
+ nodeIndeces = new ArrayList<FlowEntryInstall>();
}
}
- 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);
}
}
* Update the group name mapped flows database
*/
private void updateGroupFlowsDB(FlowEntryInstall flowEntries, boolean add) {
- Set<FlowEntryInstall> 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<FlowEntryInstall> indices = this.groupFlows.get(groupName);
+ if (indices == null) {
+ if (!add) {
return;
} else {
- flowList = new HashSet<FlowEntryInstall>();
- }
- }
-
- for (FlowEntryInstall flow : flowList) {
- if (flow.equalsByNodeAndName(flowEntries.getNode(), flowName)) {
- exists = flow;
- break;
+ indices = new ArrayList<FlowEntryInstall>();
}
}
- 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);
}
}
* 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;
}
// 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;
}
@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";
@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<FlowEntryInstall> 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<FlowEntryInstall> list = new ArrayList<FlowEntryInstall>(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<FlowEntryInstall> list = new ArrayList<FlowEntryInstall>(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);
}
* merged flow may conflict with an existing old container flows merged flow
* on the network node
*/
- private synchronized void updateFlowsContainerFlow() {
- List<FlowEntryInstall> oldCouples = new ArrayList<FlowEntryInstall>();
- List<FlowEntry> toReinstall = new ArrayList<FlowEntry>();
- for (Entry<Node, Set<FlowEntryInstall>> 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<FlowEntryInstall, FlowEntryInstall> 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<Node, Set<FlowEntryInstall>>();
+ originalSwView = new ConcurrentHashMap<FlowEntry, FlowEntry>();
+ installedSwView = new ConcurrentHashMap<FlowEntryInstall, FlowEntryInstall>();
+ nodeFlows = new ConcurrentHashMap<Node, List<FlowEntryInstall>>();
+ groupFlows = new ConcurrentHashMap<String, List<FlowEntryInstall>>();
TSPolicies = new ConcurrentHashMap<String, Object>();
- groupFlows = new ConcurrentHashMap<String, Set<FlowEntryInstall>>();
staticFlowsOrdinal = new ConcurrentHashMap<Integer, Integer>();
portGroupConfigs = new ConcurrentHashMap<String, PortGroupConfig>();
portGroupData = new ConcurrentHashMap<PortGroupConfig, Map<Node, PortGroup>>();
}
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
@Override
public List<FlowEntry> getFlowEntriesForGroup(String policyName) {
List<FlowEntry> list = new ArrayList<FlowEntry>();
- 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<FlowEntry, FlowEntry> 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<NodeConnector> portList) {
-
- Set<FlowEntryInstall> flowEntryList = this.nodeFlows.get(node);
+ public void addOutputPort(Node node, String flowName, List<NodeConnector> 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();
}
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<NodeConnector> portList) {
-
- Set<FlowEntryInstall> flowEntryList = this.nodeFlows.get(node);
-
- for (FlowEntryInstall flow : flowEntryList) {
+ public void removeOutputPort(Node node, String flowName, List<NodeConnector> 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();
}
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<FlowEntryInstall> 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;
}
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<FlowEntryInstall> 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) {
}
}
}
-
return null;
}
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));
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");
}
}
log.debug("FRM retrieveCaches for Container {}", container);
+ map = clusterContainerService.getCache("frm.originalSwView");
+ if (map != null) {
+ originalSwView = (ConcurrentMap<FlowEntry, FlowEntry>) map;
+ } else {
+ log.error("FRM Cache frm.originalSwView allocation failed for Container {}", container.getName());
+ }
+
+ map = clusterContainerService.getCache("frm.installedSwView");
+ if (map != null) {
+ installedSwView = (ConcurrentMap<FlowEntryInstall, FlowEntryInstall>) map;
+ } else {
+ log.error("FRM Cache frm.installedSwView allocation failed for Container {}", container.getName());
+ }
+
map = clusterContainerService.getCache("frm.nodeFlows");
if (map != null) {
- nodeFlows = (ConcurrentMap<Node, Set<FlowEntryInstall>>) map;
+ nodeFlows = (ConcurrentMap<Node, List<FlowEntryInstall>>) 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<String, Set<FlowEntryInstall>>) map;
+ groupFlows = (ConcurrentMap<String, List<FlowEntryInstall>>) 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<Integer, FlowConfig>) 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<Long, String>) 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<Integer, Integer>) 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<String, PortGroupConfig>) 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<PortGroupConfig, Map<Node, PortGroup>>) 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<String, Object>) 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<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+ if (entry.getValue().isByNameAndNodeIdEqual(config)) {
return true;
}
}
@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())) {
}
}
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);
// 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) {
staticFlows.put(ordinal, config);
if (multipleFlowPush) {
- PortGroupConfig pgconfig = portGroupConfigs.get(config
- .getPortGroup());
+ PortGroupConfig pgconfig = portGroupConfigs.get(config.getPortGroup());
Map<Node, PortGroup> existingData = portGroupData.get(pgconfig);
if (existingData != null) {
portGroupChanged(pgconfig, existingData, true);
}
private void addStaticFlowsToSwitch(Node node) {
- for (FlowConfig config : staticFlows.values()) {
+ for (ConcurrentMap.Entry<Integer, FlowConfig> 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) {
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<Integer, FlowConfig> 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
* reactive, so that we can remove the internal generated LLDP and ARP
* punt flows
*/
- for (Map.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+
+ // Look for the target configuration entry
+ Integer key = 0;
+ FlowConfig target = null;
+ for (ConcurrentMap.Entry<Integer, FlowConfig> 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<Integer, FlowConfig> 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<Integer, FlowConfig> 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<Integer, FlowConfig> mapEntry : staticFlows.entrySet()) {
+ for (ConcurrentMap.Entry<Integer, FlowConfig> 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;
// 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
}
// 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<Integer, FlowConfig> 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<Integer, FlowConfig> 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<Node, Set<FlowEntryInstall>> mapEntry : nodeFlows
- .entrySet()) {
- for (FlowEntryInstall flowEntries : mapEntry.getValue()) {
+ for (ConcurrentMap.Entry<FlowEntryInstall, FlowEntryInstall> mapEntry : installedSwView.entrySet()) {
+ FlowEntryInstall flowEntries = mapEntry.getValue();
+ // Skip internal generated static flows
+ if (!flowEntries.isInternal()) {
inactiveFlows.add(flowEntries.getOriginal());
}
}
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());
}
}
}
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<FlowConfig> 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<FlowConfig> getStaticFlowsOrderedList(
- ConcurrentMap<Integer, FlowConfig> flowMap, int maxKey) {
+ private List<FlowConfig> getStaticFlowsOrderedList(ConcurrentMap<Integer, FlowConfig> flowMap, int maxKey) {
List<FlowConfig> orderedList = new ArrayList<FlowConfig>();
for (int i = 0; i <= maxKey; i++) {
FlowConfig entry = flowMap.get(i);
@Override
public FlowConfig getStaticFlow(String name, Node node) {
- for (FlowConfig config : staticFlows.values()) {
- if (config.isByNameAndNodeIdEqual(name, node)) {
- return config;
+ for (ConcurrentMap.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+ if (entry.getValue().isByNameAndNodeIdEqual(name, node)) {
+ return entry.getValue();
}
}
return null;
@Override
public List<FlowConfig> getStaticFlows(Node node) {
List<FlowConfig> list = new ArrayList<FlowConfig>();
- for (FlowConfig config : staticFlows.values()) {
- if (config.onNode(node)) {
- list.add(config);
+ for (ConcurrentMap.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+ if (entry.getValue().onNode(node)) {
+ list.add(entry.getValue());
}
}
return list;
@Override
public List<String> getStaticFlowNamesForNode(Node node) {
List<String> list = new ArrayList<String>();
- for (FlowConfig config : staticFlows.values()) {
- if (config.onNode(node)) {
- list.add(config.getName());
+ for (ConcurrentMap.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+ if (entry.getValue().onNode(node)) {
+ list.add(entry.getValue().getName());
}
}
return list;
@Override
public List<Node> getListNodeWithConfiguredFlows() {
Set<Node> set = new HashSet<Node>();
- for (FlowConfig config : staticFlows.values()) {
- set.add(config.getNode());
+ for (ConcurrentMap.Entry<Integer, FlowConfig> entry : staticFlows.entrySet()) {
+ set.add(entry.getValue().getNode());
}
return new ArrayList<Node>(set);
}
@SuppressWarnings("unchecked")
private void loadFlowConfiguration() {
ObjectReader objReader = new ObjectReader();
- ConcurrentMap<Integer, FlowConfig> confList = (ConcurrentMap<Integer, FlowConfig>) objReader
- .read(this, frmFileName);
+ ConcurrentMap<Integer, FlowConfig> confList = (ConcurrentMap<Integer, FlowConfig>) objReader.read(this,
+ frmFileName);
- ConcurrentMap<String, PortGroupConfig> pgConfig = (ConcurrentMap<String, PortGroupConfig>) objReader
- .read(this, portGroupFileName);
+ ConcurrentMap<String, PortGroupConfig> pgConfig = (ConcurrentMap<String, PortGroupConfig>) objReader.read(this,
+ portGroupFileName);
if (pgConfig != null) {
- for (Map.Entry<String, PortGroupConfig> entry : pgConfig.entrySet()) {
- addPortGroupConfig(entry.getKey(), entry.getValue()
- .getMatchString(), true);
+ for (ConcurrentMap.Entry<String, PortGroupConfig> entry : pgConfig.entrySet()) {
+ addPortGroupConfig(entry.getKey(), entry.getValue().getMatchString(), true);
}
}
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)) {
}
@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);
private Status saveConfigInternal() {
ObjectWriter objWriter = new ObjectWriter();
- ConcurrentHashMap<Integer, FlowConfig> nonDynamicFlows = new ConcurrentHashMap<Integer, FlowConfig>();
+ ConcurrentMap<Integer, FlowConfig> nonDynamicFlows = new ConcurrentHashMap<Integer, FlowConfig>();
for (Integer ordinal : staticFlows.keySet()) {
FlowConfig config = staticFlows.get(ordinal);
// Do not save dynamic and controller generated static flows
nonDynamicFlows.put(ordinal, config);
}
objWriter.write(nonDynamicFlows, frmFileName);
- objWriter.write(new ConcurrentHashMap<String, PortGroupConfig>(
- portGroupConfigs), portGroupFileName);
+ objWriter.write(new ConcurrentHashMap<String, PortGroupConfig>(portGroupConfigs), portGroupFileName);
return new Status(StatusCode.SUCCESS, null);
}
}
@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();
}
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);
}
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);
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);
}
}
- log.info("Set Switch {} Mode to {}", node, proactive);
+ log.info("Set Switch {} Mode to {}", node, (proactive ? "proactive" : "reactive"));
}
/**
*
* @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<String> affectedGroups = new HashSet<String>();
- Set<FlowEntryInstall> 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<FlowEntryInstall> toRemove = new ArrayList<FlowEntryInstall>(nodeFlows.get(node));
- // Remove the node's flows from the group indexed flow database
- if (!affectedGroups.isEmpty()) {
- for (String group : affectedGroups) {
- Set<FlowEntryInstall> flowList = groupFlows.get(group);
- Set<FlowEntryInstall> toRemove = new HashSet<FlowEntryInstall>();
- 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<String, Property> 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<String, Property> propMap) {
+ this.pendingEvents.offer(new NodeUpdateEvent(type, node));
}
@Override
- public void notifyNodeConnector(NodeConnector nodeConnector,
- UpdateType type, Map<String, Property> propMap) {
+ public void notifyNodeConnector(NodeConnector nodeConnector, UpdateType type, Map<String, Property> 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);
return derivedFlow;
}
- private void addPortGroupFlows(PortGroupConfig config, Node node,
- PortGroup data) {
- for (Iterator<FlowConfig> 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<FlowConfig> 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);
}
}
}
@Override
- public void portGroupChanged(PortGroupConfig config,
- Map<Node, PortGroup> data, boolean add) {
+ public void portGroupChanged(PortGroupConfig config, Map<Node, PortGroup> data, boolean add) {
log.info("PortGroup Changed for: {} Data: {}", config, portGroupData);
Map<Node, PortGroup> existingData = portGroupData.get(config);
if (existingData != null) {
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());
}
}
}
}
}
+ @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;
}
return true;
}
+ @Override
public boolean delPortGroupConfig(String name) {
PortGroupConfig config = portGroupConfigs.get(name);
if (config == null) {
return;
}
if (portGroupProvider != null) {
- Map<Node, PortGroup> data = portGroupProvider
- .getPortGroupData(config);
+ Map<Node, PortGroup> data = portGroupProvider.getPortGroupData(config);
portGroupData.put(config, data);
}
}
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;
}
}
}
+ @Override
public PortGroupProvider getPortGroupProvider() {
return portGroupProvider;
}
*
*/
void init() {
- frmAware = Collections
- .synchronizedSet(new HashSet<IForwardingRulesManagerAware>());
- frmFileName = GlobalConstants.STARTUPHOME.toString()
- + "frm_staticflows_" + this.getContainerName() + ".conf";
- portGroupFileName = GlobalConstants.STARTUPHOME.toString()
- + "portgroup_" + this.getContainerName() + ".conf";
+ frmAware = Collections.synchronizedSet(new HashSet<IForwardingRulesManagerAware>());
+ frmFileName = GlobalConstants.STARTUPHOME.toString() + "frm_staticflows_" + this.getContainerName() + ".conf";
+ portGroupFileName = GlobalConstants.STARTUPHOME.toString() + "portgroup_" + this.getContainerName() + ".conf";
inContainerMode = false;
if (staticFlowsOrdinal.size() == 0) {
staticFlowsOrdinal.put(0, Integer.valueOf(0));
}
+
+ pendingEvents = new LinkedBlockingQueue<FRMEvent>();
+
+ // 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");
}
/**
*
*/
void destroy() {
- destroyCaches();
}
/**
*
*/
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
*
*/
void stop() {
+ // Set graceful stop flag
+ stopping = true;
}
public void setFlowProgrammerService(IFlowProgrammerService service) {
}
@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
}
@Override
- public void nodeConnectorUpdated(String containerName, NodeConnector p,
- UpdateType t) {
+ public void nodeConnectorUpdated(String containerName, NodeConnector p, UpdateType t) {
// No action
}
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
*/
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) {
}
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");
}
public void _frmNodeFlows(CommandInterpreter ci) {
+ String nodeId = ci.nextArgument();
+ Node node = Node.fromString(nodeId);
+ if (node == null) {
+ ci.println("frmNodeFlows <node> [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<Node, Set<FlowEntryInstall>> 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 <group> [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<String, Set<FlowEntryInstall>> 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());
}
}
}
@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<Integer, FlowConfig> 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<FlowEntryInstall> 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);
}
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;
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;
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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
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;
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
}
/**
- * 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
* @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);
}
}
}
/**
* Returns whether the Action is valid or not
*
- * @return boolean
+ * @return boolean
*/
public boolean isValid() {
return isValid;
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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),
}
public String getRange() {
- return "[0x" + Long.toHexString(minValue) + "-0x"
- + Long.toHexString(maxValue) + "]";
+ return "[0x" + Long.toHexString(minValue) + "-0x" + Long.toHexString(maxValue) + "]";
}
public boolean takesParameter() {
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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() {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
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)
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) {
}
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() {
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() {
}
/**
- * 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() {
/**
* Returns the vlan PCP portion of the 802.1q header this action will insert
* PCP - (3 bits)
+ *
* @return byte[]
*/
public int getPcp() {
}
/**
- * 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() {
}
/**
- * 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;
}
@Override
public String toString() {
- return type + "[tag = " + tag + ", pcp = " + pcp + ", cfi = " + cfi
- + ", vlanId = " + vlanId + "]";
+ return type + "[tag = " + tag + ", pcp = " + pcp + ", cfi = " + cfi + ", vlanId = " + vlanId + "]";
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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) {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
*/
@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) {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
@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) {
@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;
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class SetNextHop extends Action {
+ private static final long serialVersionUID = 1L;
@XmlElement
private InetAddress address;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
@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) {
/**
* 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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
@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) {
/**
* 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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
*/
@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) {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
*/
@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) {
/**
* Returns the transport port the action will set
+ *
* @return
*/
public int getPort() {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
*/
@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) {
/**
* Returns the transport port the action will set
+ *
* @return
*/
public int getPort() {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
*/
@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) {
/**
* Returns the 802.1q CFI value that this action will set
+ *
* @return
*/
public int getCfi() {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
@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;
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
*/
@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;
/**
* Returns the value of the vlan PCP this action will set
+ *
* @return int
*/
public int getPcp() {
@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;
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
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;
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
/**
* 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<Action> actions;
try {
throw new Exception("Conflicting Match and Action list");
} catch (Exception e) {
- logger.error("",e);
+ logger.error("", e);
}
} else {
this.match = match;
}
/**
- * 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
*/
/**
* Returns a copy of the actions list of this flow
+ *
* @return
*/
public List<Action> getActions() {
}
/**
- * 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
*/
}
/**
- * 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
*/
}
/**
- * 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
*/
}
break;
case SET_DL_TYPE:
- if (((SetDlType) action).getDlType() == EtherTypes.IPv6
- .intValue()) {
+ if (((SetDlType) action).getDlType() == EtherTypes.IPv6.intValue()) {
return true;
}
break;
cloned.match = this.getMatch();
cloned.actions = this.getActions();
} catch (CloneNotSupportedException e) {
- logger.error("",e);
+ logger.error("", e);
}
return cloned;
}
@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() {
* 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()) {
}
/**
- * 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<Action> 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;
* functional modules the asynchronous messages related to flow programming
* coming from the network nodes.
*/
-public interface IFlowProgrammerListener extends
- IPluginOutFlowProgrammerService {
+public interface IFlowProgrammerListener extends IPluginOutFlowProgrammerService {
}
Match cloned = null;
try {
cloned = (Match) super.clone();
+ cloned.matches = matches;
cloned.fields = new HashMap<MatchType, MatchField>();
for (Entry<MatchType, MatchField> entry : this.fields.entrySet()) {
cloned.fields.put(entry.getKey(), entry.getValue().clone());
@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;
}
@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
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;
}
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;
}
}
} catch (CloneNotSupportedException e) {
- logger.error("",e);
+ logger.error("", e);
}
return cloned;
}
@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
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));
}
}
package org.opendaylight.controller.sal.match;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Arrays;
* 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),
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;
}
public String getRange() {
- return "[0x" + Long.toHexString(minValue) + "-0x"
- + Long.toHexString(maxValue) + "]";
+ return "[0x" + Long.toHexString(minValue) + "-0x" + Long.toHexString(maxValue) + "]";
}
/**
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;
}
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) {
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;
private long byteCount;
/* Dummy constructor for JAXB */
+ @SuppressWarnings("unused")
private FlowOnNode () {
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
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
*/
/**
* 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]);
}
/**
/**
* 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 };
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;
}
/**
- * 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;
}
/**
- * 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
*
* @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)) {
/**
* 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++) {
/**
* 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()) {
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) {
}
/**
- * 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) {
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;
* @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;
+ }
}
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
@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);
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);
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
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));
}
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
@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);
@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);
@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;
// 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)));
}
}
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;
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);
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;
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));
});
// 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");
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'];