blob: 7f839cf39cfda95673bc456a9ca5f252be58ccd5 [file] [log] [blame]
Saurav Das261c3002017-06-13 15:35:54 -07001/*
2 * Copyright 2015-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.segmentrouting.grouphandler;
18
19import org.onosproject.net.DeviceId;
20import org.slf4j.Logger;
21
22import com.google.common.base.MoreObjects.ToStringHelper;
23import java.util.HashSet;
24import java.util.Objects;
25import java.util.Set;
26
27import static com.google.common.base.MoreObjects.toStringHelper;
28import static org.slf4j.LoggerFactory.getLogger;
29
30/**
31 * Representation of a set of destination switch dpids along with their edge-node
32 * labels. Meant to be used as a lookup-key in a hash-map to retrieve an ECMP-group
33 * that hashes packets towards a specific destination switch,
34 * or paired-destination switches.
35 */
36public class DestinationSet {
37 public static final int NO_EDGE_LABEL = -1;
38 private static final int NOT_ASSIGNED = 0;
39 private boolean mplsSet;
40 private final DeviceId dstSw1;
41 private final int edgeLabel1;
42 private final DeviceId dstSw2;
43 private final int edgeLabel2;
44
45
Ray Milkey5247fa92018-01-12 14:22:06 -080046 private static final Logger log = getLogger(DestinationSet.class);
Saurav Das261c3002017-06-13 15:35:54 -070047
48 /**
49 * Constructor for a single destination with no Edge label.
50 *
51 * @param isMplsSet indicates if it is a mpls destination set
52 * @param dstSw the destination switch
53 */
54 public DestinationSet(boolean isMplsSet, DeviceId dstSw) {
55 this.edgeLabel1 = NO_EDGE_LABEL;
56 this.mplsSet = isMplsSet;
57 this.dstSw1 = dstSw;
58 this.edgeLabel2 = NOT_ASSIGNED;
59 this.dstSw2 = null;
60 }
61
62 /**
63 * Constructor for a single destination with Edge label.
64 *
65 * @param isMplsSet indicates if it is a mpls destination set
66 * @param edgeLabel label to be pushed as part of group operation
67 * @param dstSw the destination switch
68 */
69 public DestinationSet(boolean isMplsSet,
70 int edgeLabel, DeviceId dstSw) {
71 this.mplsSet = isMplsSet;
72 this.edgeLabel1 = edgeLabel;
73 this.dstSw1 = dstSw;
74 this.edgeLabel2 = NOT_ASSIGNED;
75 this.dstSw2 = null;
76 }
77
78 /**
79 * Constructor for paired destination switches and their associated
80 * edge labels.
81 *
82 * @param isMplsSet indicates if it is a mpls destination set
83 * @param edgeLabel1 label to be pushed as part of group operation for dstSw1
84 * @param dstSw1 one of the paired destination switches
85 * @param edgeLabel2 label to be pushed as part of group operation for dstSw2
86 * @param dstSw2 the other paired destination switch
87 */
88 public DestinationSet(boolean isMplsSet,
89 int edgeLabel1, DeviceId dstSw1,
90 int edgeLabel2, DeviceId dstSw2) {
91 this.mplsSet = isMplsSet;
92 if (dstSw1.toString().compareTo(dstSw2.toString()) <= 0) {
93 this.edgeLabel1 = edgeLabel1;
94 this.dstSw1 = dstSw1;
95 this.edgeLabel2 = edgeLabel2;
96 this.dstSw2 = dstSw2;
97 } else {
98 this.edgeLabel1 = edgeLabel2;
99 this.dstSw1 = dstSw2;
100 this.edgeLabel2 = edgeLabel1;
101 this.dstSw2 = dstSw1;
102 }
103 }
104
105 /**
106 * Default constructor for kryo serialization.
107 */
108 public DestinationSet() {
109 this.edgeLabel1 = NOT_ASSIGNED;
110 this.edgeLabel2 = NOT_ASSIGNED;
111 this.mplsSet = true;
112 this.dstSw1 = DeviceId.NONE;
113 this.dstSw2 = DeviceId.NONE;
114 }
115
116 /**
117 * Factory method for DestinationSet hierarchy.
118 *
119 * @param random the expected behavior.
120 * @param isMplsSet indicates if it is a mpls destination set
121 * @param dstSw the destination switch
122 * @return the destination set object.
123 */
124 public static DestinationSet destinationSet(boolean random,
125 boolean isMplsSet, DeviceId dstSw) {
126 return random ? new RandomDestinationSet(dstSw)
127 : new DestinationSet(isMplsSet, dstSw);
128 }
129
130 /**
131 * Factory method for DestinationSet hierarchy.
132 *
133 * @param random the expected behavior.
134 * @param isMplsSet indicates if it is a mpls destination set
135 * @param edgeLabel label to be pushed as part of group operation
136 * @param dstSw the destination switch
137 * @return the destination set object
138 */
139 public static DestinationSet destinationSet(boolean random,
140 boolean isMplsSet, int edgeLabel,
141 DeviceId dstSw) {
142 return random ? new RandomDestinationSet(edgeLabel, dstSw)
143 : new DestinationSet(isMplsSet, edgeLabel, dstSw);
144 }
145
146 /**
147 * Factory method for DestinationSet hierarchy.
148 *
149 * @param random the expected behavior.
150 * @return the destination set object
151 */
152 public static DestinationSet destinationSet(boolean random) {
153 return random ? new RandomDestinationSet() : new DestinationSet();
154 }
155
156 /**
157 * Gets the label associated with given destination switch.
158 *
159 * @param dstSw the destination switch
160 * @return integer the label associated with the destination switch
161 */
162 public int getEdgeLabel(DeviceId dstSw) {
163 if (dstSw.equals(dstSw1)) {
164 return edgeLabel1;
165 } else if (dstSw.equals(dstSw2)) {
166 return edgeLabel2;
167 }
168 return NOT_ASSIGNED;
169 }
170
171 /**
172 * Gets all the destination switches in this destination set.
173 *
174 * @return a set of destination switch ids
175 */
176 public Set<DeviceId> getDestinationSwitches() {
177 Set<DeviceId> dests = new HashSet<>();
178 dests.add(dstSw1);
179 if (dstSw2 != null) {
180 dests.add(dstSw2);
181 }
182 return dests;
183 }
184
185 /**
186 * Gets the value of mplsSet.
187 *
188 * @return the value of mplsSet
189 */
190 public boolean mplsSet() {
191 return mplsSet;
192 }
193
194 // The list of destination ids and label are used for comparison.
195 @Override
196 public boolean equals(Object o) {
197 if (this == o) {
198 return true;
199 }
200 if (!(o instanceof DestinationSet)) {
201 return false;
202 }
203 DestinationSet that = (DestinationSet) o;
204 boolean equal = (this.edgeLabel1 == that.edgeLabel1 &&
205 this.mplsSet == that.mplsSet &&
206 this.dstSw1.equals(that.dstSw1));
207 if (this.dstSw2 != null && that.dstSw2 == null ||
208 this.dstSw2 == null && that.dstSw2 != null) {
209 return false;
210 }
211 if (this.dstSw2 != null && that.dstSw2 != null) {
212 equal = equal && (this.edgeLabel2 == that.edgeLabel2 &&
213 this.dstSw2.equals(that.dstSw2));
214 }
215 return equal;
216 }
217
218 // The list of destination ids and label are used for comparison.
219 @Override
220 public int hashCode() {
221 if (dstSw2 == null) {
222 return Objects.hash(mplsSet, edgeLabel1, dstSw1);
223 }
224 return Objects.hash(mplsSet, edgeLabel1, dstSw1, edgeLabel2, dstSw2);
225 }
226
227 @Override
228 public String toString() {
229 ToStringHelper h = toStringHelper(this)
230 .add("MplsSet", mplsSet)
231 .add("DstSw1", dstSw1)
232 .add("Label1", edgeLabel1);
233 if (dstSw2 != null) {
234 h.add("DstSw2", dstSw2)
235 .add("Label2", edgeLabel2);
236 }
237 return h.toString();
238 }
239}