Initial opendaylight infrastructure commit!!
[controller.git] / opendaylight / sal / api / src / main / java / org / opendaylight / controller / sal / flowprogrammer / Flow.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.sal.flowprogrammer;
11
12 import java.net.Inet6Address;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16
17 import javax.xml.bind.annotation.XmlAccessType;
18 import javax.xml.bind.annotation.XmlAccessorType;
19 import javax.xml.bind.annotation.XmlElement;
20 import javax.xml.bind.annotation.XmlRootElement;
21
22 import org.apache.commons.lang3.builder.EqualsBuilder;
23 import org.apache.commons.lang3.builder.HashCodeBuilder;
24 import org.opendaylight.controller.sal.action.Action;
25 import org.opendaylight.controller.sal.action.ActionType;
26 import org.opendaylight.controller.sal.action.SetDlType;
27 import org.opendaylight.controller.sal.action.SetNwDst;
28 import org.opendaylight.controller.sal.action.SetNwSrc;
29 import org.opendaylight.controller.sal.match.Match;
30 import org.opendaylight.controller.sal.utils.EtherTypes;
31
32 /**
33  * Represent a flow: match + actions + flow specific properties
34  *
35  */
36 @XmlRootElement
37 @XmlAccessorType(XmlAccessType.NONE)
38 public class Flow implements Cloneable {
39     @XmlElement
40     private Match match;
41     @XmlElement
42     private List<Action> actions;
43     @XmlElement
44     private short priority;
45     @XmlElement
46     private short idleTimeout;
47     @XmlElement
48     private short hardTimeout;
49     @XmlElement
50     private long id; // unique identifier for this flow
51
52     public Flow() {
53         match = null;
54         actions = null;
55     }
56
57     public Flow(Match match, List<Action> actions) {
58         if (match.isIPv4() && actionsAreIPv6()) {
59             try {
60                 throw new Exception("Conflicting Match and Action list");
61             } catch (Exception e) {
62                 e.printStackTrace();
63             }
64         } else {
65             this.match = match;
66             this.actions = actions;
67         }
68     }
69
70     /**
71      * Return a copy of the Match configured on this flow
72      *
73      * @return
74      */
75     public Match getMatch() {
76         return match.clone();
77     }
78
79     /**
80      * Set the Match for this flow
81      * This operation will overwrite an existing Match if present
82      *
83      * @param match
84      */
85     public void setMatch(Match match) {
86         this.match = match;
87     }
88
89     /**
90      * Returns a copy of the actions list of this flow
91      * @return
92      */
93     public List<Action> getActions() {
94         return (actions == null) ? null : new ArrayList<Action>(actions);
95     }
96
97     /**
98      * Set the actions list for this flow
99      * If a list is already present, it will be
100      * replaced with the passed one. During
101      * addition, only the valid actions will be added
102      * It is a no op if the passed actions is null
103      * An empty actions is a vlaid input
104      *
105      * @param actions
106      */
107     public void setActions(List<Action> actions) {
108         if (actions == null) {
109             return;
110         }
111
112         this.actions = new ArrayList<Action>(actions.size());
113         for (Action action : actions) {
114             if (action.isValid()) {
115                 this.actions.add(action);
116             }
117         }
118     }
119
120     /**
121      * Returns whether the Flow is for IPv4 or IPv6
122      * Information is derived from match and actions list
123      *
124      * @return
125      */
126     public boolean isIPv6() {
127         return (match.isIPv6()) ? true : actionsAreIPv6();
128     }
129
130     /**
131      * Returns true if it finds at least one action which is for IPv6
132      * in the list of actions for this Flow
133      *
134      * @return
135      */
136     private boolean actionsAreIPv6() {
137         if (this.actions != null) {
138             for (Action action : actions) {
139                 switch (action.getType()) {
140                 case SET_NW_SRC:
141                     if (((SetNwSrc) action).getAddress() instanceof Inet6Address) {
142                         return true;
143                     }
144                     break;
145                 case SET_NW_DST:
146                     if (((SetNwDst) action).getAddress() instanceof Inet6Address) {
147                         return true;
148                     }
149                     break;
150                 case SET_DL_TYPE:
151                     if (((SetDlType) action).getDlType() == EtherTypes.IPv6
152                             .intValue()) {
153                         return true;
154                     }
155                     break;
156                 default:
157                 }
158             }
159         }
160         return false;
161     }
162
163     @Override
164     public Flow clone() {
165         Flow cloned = null;
166         try {
167             cloned = (Flow) super.clone();
168             cloned.match = this.getMatch();
169             cloned.actions = this.getActions();
170         } catch (CloneNotSupportedException e) {
171             e.printStackTrace();
172         }
173         return cloned;
174     }
175
176     @Override
177     public int hashCode() {
178         return HashCodeBuilder.reflectionHashCode(this);
179     }
180
181     @Override
182     public boolean equals(Object obj) {
183         return EqualsBuilder.reflectionEquals(this, obj);
184     }
185
186     @Override
187     public String toString() {
188         return "Flow[match = " + match + ", actions = " + actions
189                 + ", priority = " + priority + ", id = " + id
190                 + ", idleTimeout = " + idleTimeout + ", hardTimeout = "
191                 + hardTimeout + "]";
192     }
193
194     public short getPriority() {
195         return priority;
196     }
197
198     public void setPriority(short priority) {
199         this.priority = priority;
200     }
201
202     public short getIdleTimeout() {
203         return idleTimeout;
204     }
205
206     public void setIdleTimeout(short idleTimeout) {
207         this.idleTimeout = idleTimeout;
208     }
209
210     public short getHardTimeout() {
211         return hardTimeout;
212     }
213
214     public void setHardTimeout(short hardTimeout) {
215         this.hardTimeout = hardTimeout;
216     }
217
218     public long getId() {
219         return id;
220     }
221
222     public void setId(long id) {
223         this.id = id;
224     }
225
226     /**
227      * Adds the specified action to the list of action of this flow
228      *
229      * @param action
230      * @return false if the passed action is null or not valid or if it fails to add it
231      */
232     public boolean addAction(Action action) {
233         if (action == null || !action.isValid()) {
234             return false;
235         }
236         return actions.add(action);
237     }
238
239     public boolean removeAction(Action action) {
240         if (action == null) {
241             return false;
242         }
243         return actions.remove(action);
244     }
245
246     /**
247      * remove ALL actions of type actionType from the list of actions of this flow
248      *
249      * @param actionType
250      * @return false if an action of that type is present and it fails to remove it
251      */
252     public boolean removeAction(ActionType actionType) {
253         Iterator<Action> actionIter = this.getActions().iterator();
254         while (actionIter.hasNext()) {
255             Action action = actionIter.next();
256             if (action.getType() == actionType) {
257                 if (!this.removeAction(action))
258                     return false;
259             }
260         }
261         return true;
262     }
263 }