Initial opendaylight infrastructure commit!!
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / flowprogrammer / Flow.java
diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/flowprogrammer/Flow.java
new file mode 100644 (file)
index 0000000..16c85a1
--- /dev/null
@@ -0,0 +1,263 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.sal.flowprogrammer;
+
+import java.net.Inet6Address;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.ActionType;
+import org.opendaylight.controller.sal.action.SetDlType;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.utils.EtherTypes;
+
+/**
+ * Represent a flow: match + actions + flow specific properties
+ *
+ */
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Flow implements Cloneable {
+    @XmlElement
+    private Match match;
+    @XmlElement
+    private List<Action> actions;
+    @XmlElement
+    private short priority;
+    @XmlElement
+    private short idleTimeout;
+    @XmlElement
+    private short hardTimeout;
+    @XmlElement
+    private long id; // unique identifier for this flow
+
+    public Flow() {
+        match = null;
+        actions = null;
+    }
+
+    public Flow(Match match, List<Action> actions) {
+        if (match.isIPv4() && actionsAreIPv6()) {
+            try {
+                throw new Exception("Conflicting Match and Action list");
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        } else {
+            this.match = match;
+            this.actions = actions;
+        }
+    }
+
+    /**
+     * Return a copy of the Match configured on this flow
+     *
+     * @return
+     */
+    public Match getMatch() {
+        return match.clone();
+    }
+
+    /**
+     * Set the Match for this flow
+     * This operation will overwrite an existing Match if present
+     *
+     * @param match
+     */
+    public void setMatch(Match match) {
+        this.match = match;
+    }
+
+    /**
+     * Returns a copy of the actions list of this flow
+     * @return
+     */
+    public List<Action> getActions() {
+        return (actions == null) ? null : new ArrayList<Action>(actions);
+    }
+
+    /**
+     * 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
+     */
+    public void setActions(List<Action> actions) {
+        if (actions == null) {
+            return;
+        }
+
+        this.actions = new ArrayList<Action>(actions.size());
+        for (Action action : actions) {
+            if (action.isValid()) {
+                this.actions.add(action);
+            }
+        }
+    }
+
+    /**
+     * Returns whether the Flow is for IPv4 or IPv6
+     * Information is derived from match and actions list
+     *
+     * @return
+     */
+    public boolean isIPv6() {
+        return (match.isIPv6()) ? true : actionsAreIPv6();
+    }
+
+    /**
+     * Returns true if it finds at least one action which is for IPv6
+     * in the list of actions for this Flow
+     *
+     * @return
+     */
+    private boolean actionsAreIPv6() {
+        if (this.actions != null) {
+            for (Action action : actions) {
+                switch (action.getType()) {
+                case SET_NW_SRC:
+                    if (((SetNwSrc) action).getAddress() instanceof Inet6Address) {
+                        return true;
+                    }
+                    break;
+                case SET_NW_DST:
+                    if (((SetNwDst) action).getAddress() instanceof Inet6Address) {
+                        return true;
+                    }
+                    break;
+                case SET_DL_TYPE:
+                    if (((SetDlType) action).getDlType() == EtherTypes.IPv6
+                            .intValue()) {
+                        return true;
+                    }
+                    break;
+                default:
+                }
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public Flow clone() {
+        Flow cloned = null;
+        try {
+            cloned = (Flow) super.clone();
+            cloned.match = this.getMatch();
+            cloned.actions = this.getActions();
+        } catch (CloneNotSupportedException e) {
+            e.printStackTrace();
+        }
+        return cloned;
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return "Flow[match = " + match + ", actions = " + actions
+                + ", priority = " + priority + ", id = " + id
+                + ", idleTimeout = " + idleTimeout + ", hardTimeout = "
+                + hardTimeout + "]";
+    }
+
+    public short getPriority() {
+        return priority;
+    }
+
+    public void setPriority(short priority) {
+        this.priority = priority;
+    }
+
+    public short getIdleTimeout() {
+        return idleTimeout;
+    }
+
+    public void setIdleTimeout(short idleTimeout) {
+        this.idleTimeout = idleTimeout;
+    }
+
+    public short getHardTimeout() {
+        return hardTimeout;
+    }
+
+    public void setHardTimeout(short hardTimeout) {
+        this.hardTimeout = hardTimeout;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    /**
+     * 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
+     */
+    public boolean addAction(Action action) {
+        if (action == null || !action.isValid()) {
+            return false;
+        }
+        return actions.add(action);
+    }
+
+    public boolean removeAction(Action action) {
+        if (action == null) {
+            return false;
+        }
+        return actions.remove(action);
+    }
+
+    /**
+     * 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
+     */
+    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))
+                    return false;
+            }
+        }
+        return true;
+    }
+}