BUG 2302 : odl-clustering-test-app should not be part of the odl-restconf-all feature set
[controller.git] / opendaylight / adsal / sal / api / src / main / java / org / opendaylight / controller / sal / flowprogrammer / Flow.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.sal.flowprogrammer;
10
11 import org.opendaylight.controller.sal.action.Action;
12 import org.opendaylight.controller.sal.action.ActionType;
13 import org.opendaylight.controller.sal.action.SetDlType;
14 import org.opendaylight.controller.sal.action.SetNwDst;
15 import org.opendaylight.controller.sal.action.SetNwSrc;
16 import org.opendaylight.controller.sal.match.Match;
17 import org.opendaylight.controller.sal.utils.EtherTypes;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 import javax.xml.bind.annotation.XmlAccessType;
22 import javax.xml.bind.annotation.XmlAccessorType;
23 import javax.xml.bind.annotation.XmlElement;
24 import javax.xml.bind.annotation.XmlRootElement;
25 import java.io.Serializable;
26 import java.net.Inet6Address;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30
31 /**
32  * Represent a flow: match + actions + flow specific properties
33  */
34 @XmlRootElement
35 @XmlAccessorType(XmlAccessType.NONE)
36 public class Flow implements Cloneable, Serializable {
37     protected static final Logger logger = LoggerFactory.getLogger(Flow.class);
38     private static final long serialVersionUID = 1L;
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                 logger.error("", e);
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 This operation will overwrite an existing
81      * 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      *
92      * @return
93      */
94     public List<Action> getActions() {
95         return (actions == null) ? null : new ArrayList<Action>(actions);
96     }
97
98     /**
99      * Set the actions list for this flow If a list is already present, it will
100      * be replaced with the passed one. During addition, only the valid actions
101      * will be added It is a no op if the passed actions is null An empty
102      * actions is a vlaid input
103      *
104      * @param actions
105      */
106     public void setActions(List<Action> actions) {
107         if (actions == null) {
108             return;
109         }
110
111         this.actions = new ArrayList<Action>(actions.size());
112         for (Action action : actions) {
113             if (action.isValid()) {
114                 this.actions.add(action);
115             }
116         }
117     }
118
119     /**
120      * Returns whether the Flow is for IPv4 or IPv6 Information is derived from
121      * match and actions list
122      *
123      * @return
124      */
125     public boolean isIPv6() {
126         return (match.isIPv6()) ? true : actionsAreIPv6();
127     }
128
129     /**
130      * Returns true if it finds at least one action which is for IPv6 in the
131      * list of actions for this Flow
132      *
133      * @return
134      */
135     private boolean actionsAreIPv6() {
136         if (this.actions != null) {
137             for (Action action : actions) {
138                 switch (action.getType()) {
139                 case SET_NW_SRC:
140                     if (((SetNwSrc) action).getAddress() instanceof Inet6Address) {
141                         return true;
142                     }
143                     break;
144                 case SET_NW_DST:
145                     if (((SetNwDst) action).getAddress() instanceof Inet6Address) {
146                         return true;
147                     }
148                     break;
149                 case SET_DL_TYPE:
150                     if (((SetDlType) action).getDlType() == EtherTypes.IPv6.intValue()) {
151                         return true;
152                     }
153                     break;
154                 default:
155                 }
156             }
157         }
158         return false;
159     }
160
161     @Override
162     public Flow clone() {
163         Flow cloned = null;
164         try {
165             cloned = (Flow) super.clone();
166             cloned.match = this.getMatch();
167             cloned.actions = this.getActions();
168         } catch (CloneNotSupportedException e) {
169             logger.error("", e);
170         }
171         return cloned;
172     }
173
174     @Override
175     public int hashCode() {
176         final int prime = 31;
177         int result = 1;
178         result = prime * result + ((actions == null) ? 0 : actions.hashCode());
179         result = prime * result + hardTimeout;
180         result = prime * result + (int) (id ^ (id >>> 32));
181         result = prime * result + idleTimeout;
182         result = prime * result + ((match == null) ? 0 : match.hashCode());
183         result = prime * result + priority;
184         return result;
185     }
186
187     @Override
188     public boolean equals(Object obj) {
189         if (this == obj) {
190             return true;
191         }
192         if (obj == null) {
193             return false;
194         }
195         if (getClass() != obj.getClass()) {
196             return false;
197         }
198         Flow other = (Flow) obj;
199         if (actions == null) {
200             if (other.actions != null) {
201                 return false;
202             }
203         } else if (!actions.equals(other.actions)) {
204             return false;
205         }
206         if (hardTimeout != other.hardTimeout) {
207             return false;
208         }
209         if (id != other.id) {
210             return false;
211         }
212         if (idleTimeout != other.idleTimeout) {
213             return false;
214         }
215         if (match == null) {
216             if (other.match != null) {
217                 return false;
218             }
219         } else if (!match.equals(other.match)) {
220             return false;
221         }
222         if (priority != other.priority) {
223             return false;
224         }
225         return true;
226     }
227
228     @Override
229     public String toString() {
230         return "Flow[match = " + match + ", actions = " + actions + ", priority = " + priority + ", id = " + id
231                 + ", idleTimeout = " + idleTimeout + ", hardTimeout = " + hardTimeout + "]";
232     }
233
234     public short getPriority() {
235         return priority;
236     }
237
238     public void setPriority(short priority) {
239         this.priority = priority;
240     }
241
242     public short getIdleTimeout() {
243         return idleTimeout;
244     }
245
246     public void setIdleTimeout(short idleTimeout) {
247         this.idleTimeout = idleTimeout;
248     }
249
250     public short getHardTimeout() {
251         return hardTimeout;
252     }
253
254     public void setHardTimeout(short hardTimeout) {
255         this.hardTimeout = hardTimeout;
256     }
257
258     public long getId() {
259         return id;
260     }
261
262     public void setId(long id) {
263         this.id = id;
264     }
265
266     /**
267      * Adds the specified action to the list of action of this flow
268      *
269      * @param action
270      * @return false if the passed action is null or not valid or if it fails to
271      *         add it
272      */
273     public boolean addAction(Action action) {
274         if (action == null || !action.isValid()) {
275             return false;
276         }
277         return actions.add(action);
278     }
279
280     public boolean removeAction(Action action) {
281         if (action == null) {
282             return false;
283         }
284         return actions.remove(action);
285     }
286
287     /**
288      * remove ALL actions of type actionType from the list of actions of this
289      * flow
290      *
291      * @param actionType
292      * @return false if an action of that type is present and it fails to remove
293      *         it
294      */
295     public boolean removeAction(ActionType actionType) {
296         Iterator<Action> actionIter = this.getActions().iterator();
297         while (actionIter.hasNext()) {
298             Action action = actionIter.next();
299             if (action.getType() == actionType) {
300                 if (!this.removeAction(action)) {
301                     return false;
302                 }
303             }
304         }
305         return true;
306     }
307
308 }