Merge "Refactored yang-maven-plugin. Updated tests. Removed backup files."
[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.io.Serializable;
13 import java.net.Inet6Address;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17
18 import javax.xml.bind.annotation.XmlAccessType;
19 import javax.xml.bind.annotation.XmlAccessorType;
20 import javax.xml.bind.annotation.XmlElement;
21 import javax.xml.bind.annotation.XmlRootElement;
22
23 import org.opendaylight.controller.sal.action.Action;
24 import org.opendaylight.controller.sal.action.ActionType;
25 import org.opendaylight.controller.sal.action.SetDlType;
26 import org.opendaylight.controller.sal.action.SetNwDst;
27 import org.opendaylight.controller.sal.action.SetNwSrc;
28 import org.opendaylight.controller.sal.match.Match;
29 import org.opendaylight.controller.sal.utils.EtherTypes;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Represent a flow: match + actions + flow specific properties
35  *
36  */
37 @XmlRootElement
38 @XmlAccessorType(XmlAccessType.NONE)
39 public class Flow implements Cloneable, Serializable {
40     protected static final Logger logger = LoggerFactory
41     .getLogger(Flow.class);
42         private static final long serialVersionUID = 1L;
43         @XmlElement
44     private Match match;
45     @XmlElement
46     private List<Action> actions;
47     @XmlElement
48     private short priority;
49     @XmlElement
50     private short idleTimeout;
51     @XmlElement
52     private short hardTimeout;
53     @XmlElement
54     private long id; // unique identifier for this flow
55
56     public Flow() {
57         match = null;
58         actions = null;
59     }
60
61     public Flow(Match match, List<Action> actions) {
62         if (match.isIPv4() && actionsAreIPv6()) {
63             try {
64                 throw new Exception("Conflicting Match and Action list");
65             } catch (Exception e) {
66                 logger.error("",e);
67             }
68         } else {
69             this.match = match;
70             this.actions = actions;
71         }
72     }
73
74     /**
75      * Return a copy of the Match configured on this flow
76      *
77      * @return
78      */
79     public Match getMatch() {
80         return match.clone();
81     }
82
83     /**
84      * Set the Match for this flow
85      * This operation will overwrite an existing Match if present
86      *
87      * @param match
88      */
89     public void setMatch(Match match) {
90         this.match = match;
91     }
92
93     /**
94      * Returns a copy of the actions list of this flow
95      * @return
96      */
97     public List<Action> getActions() {
98         return (actions == null) ? null : new ArrayList<Action>(actions);
99     }
100
101     /**
102      * Set the actions list for this flow
103      * If a list is already present, it will be
104      * replaced with the passed one. During
105      * addition, only the valid actions will be added
106      * It is a no op if the passed actions is null
107      * An empty actions is a vlaid input
108      *
109      * @param actions
110      */
111     public void setActions(List<Action> actions) {
112         if (actions == null) {
113             return;
114         }
115
116         this.actions = new ArrayList<Action>(actions.size());
117         for (Action action : actions) {
118             if (action.isValid()) {
119                 this.actions.add(action);
120             }
121         }
122     }
123
124     /**
125      * Returns whether the Flow is for IPv4 or IPv6
126      * Information is derived from match and actions list
127      *
128      * @return
129      */
130     public boolean isIPv6() {
131         return (match.isIPv6()) ? true : actionsAreIPv6();
132     }
133
134     /**
135      * Returns true if it finds at least one action which is for IPv6
136      * in the list of actions for this Flow
137      *
138      * @return
139      */
140     private boolean actionsAreIPv6() {
141         if (this.actions != null) {
142             for (Action action : actions) {
143                 switch (action.getType()) {
144                 case SET_NW_SRC:
145                     if (((SetNwSrc) action).getAddress() instanceof Inet6Address) {
146                         return true;
147                     }
148                     break;
149                 case SET_NW_DST:
150                     if (((SetNwDst) action).getAddress() instanceof Inet6Address) {
151                         return true;
152                     }
153                     break;
154                 case SET_DL_TYPE:
155                     if (((SetDlType) action).getDlType() == EtherTypes.IPv6
156                             .intValue()) {
157                         return true;
158                     }
159                     break;
160                 default:
161                 }
162             }
163         }
164         return false;
165     }
166
167     @Override
168     public Flow clone() {
169         Flow cloned = null;
170         try {
171             cloned = (Flow) super.clone();
172             cloned.match = this.getMatch();
173             cloned.actions = this.getActions();
174         } catch (CloneNotSupportedException e) {
175             logger.error("",e);
176         }
177         return cloned;
178     }
179
180     @Override
181     public int hashCode() {
182         final int prime = 31;
183         int result = 1;
184         result = prime * result + ((actions == null) ? 0 : actions.hashCode());
185         result = prime * result + hardTimeout;
186         result = prime * result + (int) (id ^ (id >>> 32));
187         result = prime * result + idleTimeout;
188         result = prime * result + ((match == null) ? 0 : match.hashCode());
189         result = prime * result + priority;
190         return result;
191     }
192
193     @Override
194     public boolean equals(Object obj) {
195         if (this == obj)
196             return true;
197         if (obj == null)
198             return false;
199         if (getClass() != obj.getClass())
200             return false;
201         Flow other = (Flow) obj;
202         if (actions == null) {
203             if (other.actions != null)
204                 return false;
205         } else if (!actions.equals(other.actions))
206             return false;
207         if (hardTimeout != other.hardTimeout)
208             return false;
209         if (id != other.id)
210             return false;
211         if (idleTimeout != other.idleTimeout)
212             return false;
213         if (match == null) {
214             if (other.match != null)
215                 return false;
216         } else if (!match.equals(other.match))
217             return false;
218         if (priority != other.priority)
219             return false;
220         return true;
221     }
222
223     @Override
224     public String toString() {
225         return "Flow[match = " + match + ", actions = " + actions
226                 + ", priority = " + priority + ", id = " + id
227                 + ", idleTimeout = " + idleTimeout + ", hardTimeout = "
228                 + hardTimeout + "]";
229     }
230
231     public short getPriority() {
232         return priority;
233     }
234
235     public void setPriority(short priority) {
236         this.priority = priority;
237     }
238
239     public short getIdleTimeout() {
240         return idleTimeout;
241     }
242
243     public void setIdleTimeout(short idleTimeout) {
244         this.idleTimeout = idleTimeout;
245     }
246
247     public short getHardTimeout() {
248         return hardTimeout;
249     }
250
251     public void setHardTimeout(short hardTimeout) {
252         this.hardTimeout = hardTimeout;
253     }
254
255     public long getId() {
256         return id;
257     }
258
259     public void setId(long id) {
260         this.id = id;
261     }
262
263     /**
264      * Adds the specified action to the list of action of this flow
265      *
266      * @param action
267      * @return false if the passed action is null or not valid or if it fails to add it
268      */
269     public boolean addAction(Action action) {
270         if (action == null || !action.isValid()) {
271             return false;
272         }
273         return actions.add(action);
274     }
275
276     public boolean removeAction(Action action) {
277         if (action == null) {
278             return false;
279         }
280         return actions.remove(action);
281     }
282
283     /**
284      * remove ALL actions of type actionType from the list of actions of this flow
285      *
286      * @param actionType
287      * @return false if an action of that type is present and it fails to remove it
288      */
289     public boolean removeAction(ActionType actionType) {
290         Iterator<Action> actionIter = this.getActions().iterator();
291         while (actionIter.hasNext()) {
292             Action action = actionIter.next();
293             if (action.getType() == actionType) {
294                 if (!this.removeAction(action))
295                     return false;
296             }
297         }
298         return true;
299     }
300 }