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