Merge "Fix for Bug 3"
[controller.git] / opendaylight / forwardingrulesmanager / api / src / main / java / org / opendaylight / controller / forwardingrulesmanager / FlowEntry.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.forwardingrulesmanager;
10
11 import java.io.Serializable;
12 import java.util.Date;
13
14 import org.opendaylight.controller.sal.core.ContainerFlow;
15 import org.opendaylight.controller.sal.core.Node;
16 import org.opendaylight.controller.sal.flowprogrammer.Flow;
17 import org.opendaylight.controller.sal.match.Match;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 /**
22  * Represents a flow applications request Forwarding Rules Manager to install on
23  * a network node. A FlowEntry is constituted of a flow (match + actions), the
24  * target network node, and the flow name. It also includes a group name. For
25  * instance the flows constituting a policy all share the same group name.
26  */
27 public class FlowEntry implements Cloneable, Serializable {
28     protected static final Logger logger = LoggerFactory.getLogger(FlowEntry.class);
29     private static final long serialVersionUID = 1L;
30     private static final Logger log = LoggerFactory.getLogger(FlowEntry.class);
31     private String groupName; // group name
32     private String flowName; // flow name (may be null)
33     private Node node; // network node where to install the flow
34     private Flow flow; // match + action
35
36     public FlowEntry(String groupName, String flowName, Flow flow, Node node) {
37         this.groupName = groupName;
38         this.flow = flow;
39         this.node = node;
40         this.flowName = (flowName != null) ? flowName : constructFlowName();
41     }
42
43     public String getGroupName() {
44         return groupName;
45     }
46
47     public void setGroupName(String name) {
48         this.groupName = name;
49     }
50
51     /**
52      * Return the actual Flow contained in this entry
53      *
54      * @return the flow
55      */
56     public Flow getFlow() {
57         return flow;
58     }
59
60     public Node getNode() {
61         return node;
62     }
63
64     public void setNode(Node n) {
65         this.node = n;
66     }
67
68     public String getFlowName() {
69         return flowName;
70     }
71
72     public void setFlowName(String n) {
73         this.flowName = n;
74     }
75
76     @Override
77     public FlowEntry clone() {
78         FlowEntry cloned = null;
79         try {
80             cloned = (FlowEntry) super.clone();
81             cloned.flow = this.flow.clone();
82         } catch (CloneNotSupportedException e) {
83             log.warn("exception in clone", e);
84         }
85         return cloned;
86     }
87
88     /*
89      * Only accounts fields which uniquely identify a flow for collision
90      * purposes: node, match and priority
91      */
92     @Override
93     public int hashCode() {
94         final int prime = 31;
95         int result = 1;
96         result = prime * result + ((node == null) ? 0 : node.hashCode());
97         result = prime * result + ((flow == null) ? 0 : (int) flow.getPriority());
98         result = prime * result + ((flow == null || flow.getMatch() == null) ? 0 : flow.getMatch().hashCode());
99
100         return result;
101     }
102
103     @Override
104     public boolean equals(Object obj) {
105         if (this == obj) {
106             return true;
107         }
108         if (obj == null) {
109             return false;
110         }
111         if (getClass() != obj.getClass()) {
112             return false;
113         }
114         FlowEntry other = (FlowEntry) obj;
115
116         if (node == null) {
117             if (other.node != null) {
118                 return false;
119             }
120         } else if (!node.equals(other.node)) {
121             return false;
122         }
123
124         if (flow == null) {
125             return other.flow == null;
126         } else if (other.flow == null) {
127             return false;
128         }
129         if (flow.getPriority() != other.flow.getPriority()) {
130             return false;
131         }
132         if (flow.getMatch() == null) {
133             if (other.flow.getMatch() != null) {
134                 return false;
135             }
136         } else if (!flow.getMatch().equals(other.flow.getMatch())) {
137             return false;
138         }
139
140         return true;
141     }
142
143     @Override
144     public String toString() {
145         return "FlowEntry[flowName = " + flowName + ", groupName = " + groupName + ", node = " + node + ", flow = "
146                 + flow + "]";
147     }
148
149     private String constructFlowName() {
150         return this.groupName + "_" + new Date().toString();
151     }
152
153     public boolean equalsByNodeAndName(Node node, String flowName) {
154         return this.node.equals(node) && this.flowName.equals(flowName);
155     }
156
157     /**
158      * Merges the current Flow with the passed Container Flow
159      *
160      * Note: Container Flow merging is not an injective function. Be m1 and m2
161      * two different matches, and be f() the flow merge function, such that y1 =
162      * f(m1) and y2 = f(m2) are the two merged matches, we may have: y1 = y2
163      *
164      *
165      * @param containerFlow
166      * @return this merged FlowEntry
167      */
168     public FlowEntry mergeWith(ContainerFlow containerFlow) {
169         Match myMatch = flow.getMatch();
170
171         Match filter = containerFlow.getMatch();
172
173         // Merge
174         Match merge = myMatch.mergeWithFilter(filter);
175
176         // Replace this Flow's match with merged version
177         flow.setMatch(merge);
178
179         return this;
180     }
181
182     /**
183      * Returns whether this entry is the result of an internal generated static
184      * flow
185      *
186      * @return true if internal generated static flow, false otherwise
187      */
188     public boolean isInternal() {
189         return flowName.startsWith(FlowConfig.INTERNALSTATICFLOWBEGIN)
190                 && flowName.endsWith(FlowConfig.INTERNALSTATICFLOWEND);
191     }
192 }