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