blob: 4da1f33cc98fe0b9fdf393ff3d355ec189ece96a [file] [log] [blame]
alshabibeff00542015-09-23 13:22:33 -07001/*
2 * Copyright 2015 Open Networking Laboratory
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 */
16package org.onosproject.mfwd.impl;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19
20import org.onlab.packet.IpPrefix;
21import org.onosproject.net.ConnectPoint;
alshabibeff00542015-09-23 13:22:33 -070022import org.onosproject.net.intent.SinglePointToMultiPointIntent;
23import org.onosproject.net.intent.Key;
24
25import java.util.Set;
26import java.util.HashSet;
27
28/**
29 * McastRouteBase base class for McastRouteGroup and McastRouteSource.
30 */
31public class McastRouteBase implements McastRoute {
32 protected final IpPrefix gaddr;
33 protected final IpPrefix saddr;
34
Rusty Eddyddef8932015-09-25 01:15:53 +000035 protected McastConnectPoint ingressPoint;
36 protected Set<McastConnectPoint> egressPoints;
alshabibeff00542015-09-23 13:22:33 -070037
38 protected boolean isGroup = false;
39
Rusty Eddyddef8932015-09-25 01:15:53 +000040 protected boolean dirty = false;
41
alshabibeff00542015-09-23 13:22:33 -070042 /**
43 * How may times has this packet been punted.
44 */
45 private int puntCount = 0;
46
47 /**
48 * If the intentKey is null that means no intent has
49 * been installed.
50 */
51 protected Key intentKey = null;
52
53 /**
54 * Create a multicast route. This is the parent class for both the Group
55 * and the source.
56 *
57 * @param saddr source address
58 * @param gaddr multicast group address
59 */
60 public McastRouteBase(String saddr, String gaddr) {
61 this.gaddr = IpPrefix.valueOf(checkNotNull(gaddr));
62 if (saddr == null || saddr.equals("*")) {
63 this.saddr = IpPrefix.valueOf(0, 0);
64 } else {
65 this.saddr = IpPrefix.valueOf(checkNotNull(gaddr));
66 }
67 this.init();
68 }
69
70 /**
71 * Create a multicast group table entry.
72 * @param gaddr multicast group address
73 */
74 public McastRouteBase(String gaddr) {
75 this("*", gaddr);
76 }
77
78 /**
79 * Set the source and group address value of a (*, G) group.
80 *
81 * @param gpfx the group prefix address
82 */
83 public McastRouteBase(IpPrefix gpfx) {
84 this(IpPrefix.valueOf(0, 0), gpfx);
85 }
86
87 /**
88 * Create a multicast route constructor.
89 *
90 * @param saddr source address
91 * @param gaddr group address
92 */
93 public McastRouteBase(IpPrefix saddr, IpPrefix gaddr) {
94 this.saddr = checkNotNull(saddr);
95 this.gaddr = checkNotNull(gaddr);
96
97 this.init();
98 }
99
100 private void init() {
101 this.isGroup = (this.saddr.prefixLength() == 0);
102 this.ingressPoint = null;
103 this.egressPoints = new HashSet();
104 }
105
106 /**
107 * Get the multicast group address.
108 *
109 * @return the multicast group address
110 */
111 @Override
112 public IpPrefix getGaddr() {
113 return gaddr;
114 }
115
116 /**
117 * Get the multicast source address.
118 *
119 * @return the multicast source address
120 */
121 @Override
122 public IpPrefix getSaddr() {
123 return saddr;
124 }
125
126 /**
127 * Is this an IPv4 multicast route.
128 *
129 * @return true if it is an IPv4 route
130 */
131 @Override
132 public boolean isIp4() {
133 return gaddr.isIp4();
134 }
135
136 /**
137 * Is this an IPv6 multicast route.
138 *
139 * @return true if it is an IPv6 route
140 */
141 @Override
142 public boolean isIp6() {
143 return gaddr.isIp6();
144 }
145
146 /**
147 * Is this a multicast group route?
148 *
149 * @return true if it is a multicast group route.
150 */
151 public boolean isGroup() {
152 return isGroup;
153 }
154
155 /**
156 * @return true if this is (S, G) false if it (*, G).
157 */
158 public boolean isSource() {
159 return (!isGroup);
160 }
161
162 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000163 * Get the dirty state.
164 *
165 * @return whether this route is dirty or not.
166 */
167 public boolean getDirty() {
168 return this.dirty;
169 }
170
171 /**
172 * Set the dirty state to indicate that something changed.
173 * This may require an update to the flow tables (intents).
174 *
175 * @param dirty set the dirty bit
176 */
177 public void setDirty(boolean dirty) {
178 this.dirty = dirty;
179 }
180
181 /**
alshabibeff00542015-09-23 13:22:33 -0700182 * Add an ingress point to this route.
183 *
184 * @param ingress incoming connect point
Rusty Eddyddef8932015-09-25 01:15:53 +0000185 * @return whether ingress has been added, only add if ingressPoint is null
alshabibeff00542015-09-23 13:22:33 -0700186 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000187 public boolean addIngressPoint(ConnectPoint ingress) {
188
189 // Do NOT add the ingressPoint if it is not null.
190 if (this.ingressPoint != null) {
191 // TODO: Log an warning.
192 return false;
193 }
194 this.ingressPoint = new McastConnectPoint(checkNotNull(ingress));
195 setDirty(true);
196 return true;
alshabibeff00542015-09-23 13:22:33 -0700197 }
198
199 /**
200 * Add or modify the ingress connect point.
201 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000202 * @param connectPoint string switch device Id
203 * @return whether ingress has been added, only add if ingressPoint is null
alshabibeff00542015-09-23 13:22:33 -0700204 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000205 public boolean addIngressPoint(String connectPoint) {
206
207 if (this.ingressPoint != null) {
208 // TODO: log a warning.
209 return false;
210 }
211 ConnectPoint cp = ConnectPoint.deviceConnectPoint(checkNotNull(connectPoint));
212 return this.addIngressPoint(cp);
alshabibeff00542015-09-23 13:22:33 -0700213 }
214
215 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000216 * Get the ingress McastConnectPoint.
alshabibeff00542015-09-23 13:22:33 -0700217 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000218 * @return the ingress McastConnectPoint
alshabibeff00542015-09-23 13:22:33 -0700219 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000220 public McastConnectPoint getIngressPoint() {
alshabibeff00542015-09-23 13:22:33 -0700221 return this.ingressPoint;
222 }
223
224 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000225 * Add an egress McastConnectPoint.
alshabibeff00542015-09-23 13:22:33 -0700226 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000227 * @param cp egress connect point
228 * @return return the McastConnectPoint
alshabibeff00542015-09-23 13:22:33 -0700229 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000230 public McastConnectPoint addEgressPoint(ConnectPoint cp) {
231 McastConnectPoint mcp = this.findEgressConnectPoint(cp);
232 if (mcp == null) {
233 mcp = new McastConnectPoint(checkNotNull(cp));
234 egressPoints.add(mcp);
235 setDirty(true);
236 }
237 return mcp;
alshabibeff00542015-09-23 13:22:33 -0700238 }
239
240 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000241 * Add an egress connect point from a string.
alshabibeff00542015-09-23 13:22:33 -0700242 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000243 * @param connectPoint string representing a connect point
244 * @return the MulticastConnectPoint
alshabibeff00542015-09-23 13:22:33 -0700245 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000246 public McastConnectPoint addEgressPoint(String connectPoint) {
247 checkNotNull(connectPoint);
248 return this.addEgressPoint(ConnectPoint.deviceConnectPoint(connectPoint));
249 }
250
251 /**
252 * Add an egress McastConnectPoint.
253 *
254 * @param cp the egress connect point
255 * @param interest the source of interest for mcast traffic
256 */
257 public McastConnectPoint addEgressPoint(ConnectPoint cp, McastConnectPoint.JoinSource interest) {
258 checkNotNull(cp);
259 checkNotNull(interest);
260 McastConnectPoint mcp = this.addEgressPoint(cp);
261 if (mcp != null) {
262 mcp.interest.add(interest);
263 setDirty(true);
264 }
265 return mcp;
266 }
267
268 /**
Julian Lawrence14c73182015-10-08 18:31:52 -0700269 * Remove an egress from McastConnectPoint.
270 *
271 * @param connectPoint the egress connect point
272 * @return boolean result of removal
273 */
274 public boolean removeEgressPoint(String connectPoint) {
275 checkNotNull(connectPoint);
276 return this.removeEgressPoint(ConnectPoint.deviceConnectPoint(connectPoint));
277 }
278
279 /**
280 * Remove an egress from McastConnectPoint.
281 *
282 * @param cp the egress connect point
283 * @return boolean result of removal
284 */
285 public boolean removeEgressPoint(ConnectPoint cp) {
286 boolean removed = false;
287 McastConnectPoint mcp = this.findEgressConnectPoint(checkNotNull(cp));
288 if (mcp != null) {
289 removed = egressPoints.remove(mcp);
290 setDirty(true);
291 }
292 return removed;
293 }
294
295 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000296 * Add an egress McastConnectPoint.
297 *
298 * @param cpstr deviceId/port of the connect point
299 */
300 public McastConnectPoint addEgressPoint(String cpstr, McastConnectPoint.JoinSource interest) {
301 checkNotNull(cpstr);
302 checkNotNull(interest);
303 return this.addEgressPoint(ConnectPoint.deviceConnectPoint(cpstr), interest);
alshabibeff00542015-09-23 13:22:33 -0700304 }
305
306 /**
307 * Get egress connect points for the route.
308 *
309 * @return Set of egress connect points
310 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000311 public Set<McastConnectPoint> getEgressPoints() {
alshabibeff00542015-09-23 13:22:33 -0700312 return egressPoints;
313 }
314
315 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000316 * Get egress McastConnectPoints points as ConnectPoints for intent system.
317 *
318 * @return Set of egress ConnectPoints
319 */
320 public Set<ConnectPoint> getEgressConnectPoints() {
Julian Lawrence14c73182015-10-08 18:31:52 -0700321 Set<ConnectPoint> cps = new HashSet<ConnectPoint>();
Rusty Eddyddef8932015-09-25 01:15:53 +0000322
323 for (McastConnectPoint mcp : egressPoints) {
324 cps.add(mcp.getConnectPoint());
325 }
326 return cps;
327 }
328
329 /**
330 * Find the Multicast Connect Point that contains the ConnectPoint.
331 *
332 * @param cp the regular ConnectPoint to match
333 * @return the McastConnectPoint that contains cp or null if not found.
334 */
335 public McastConnectPoint findEgressConnectPoint(ConnectPoint cp) {
336 for (McastConnectPoint mcp : this.egressPoints) {
337 if (mcp.getConnectPoint().equals(cp)) {
338 return mcp;
339 }
340 }
341 return null;
342 }
343
344 /**
345 * Remove specified interest from the given ConnectPoint.
346 *
347 * @param mcp connect point.
348 * @param interest the protocol interested in this multicast stream
349 * @return true if removed, false otherwise
350 */
351 public boolean removeInterest(McastConnectPoint mcp, McastConnectPoint.JoinSource interest) {
352 checkNotNull(mcp);
353 if (mcp.interest.contains(interest)) {
354 mcp.interest.remove(interest);
355 setDirty(true);
356 return true;
357 }
358 return false;
359 }
360
361 /**
alshabibeff00542015-09-23 13:22:33 -0700362 * Get the number of times the packet has been punted.
363 *
364 * @return the punt count
365 */
366 @Override
367 public int getPuntCount() {
368 return puntCount;
369 }
370
371 /**
372 * Increment the punt count.
373 *
374 * TODO: we need to handle wrapping.
375 */
376 @Override
377 public void incrementPuntCount() {
378 puntCount++;
379 }
380
381 /**
382 * Have the McastIntentManager create and set the intent, then save the intent key.
383 *
384 * If we already have an intent, we will first withdraw the existing intent and
385 * replace it with a new one. This will support the case where the ingress connectPoint
386 * or group of egress connectPoints change.
387 */
388 @Override
389 public void setIntent() {
390 if (this.intentKey != null) {
391 this.withdrawIntent();
392 }
393 McastIntentManager im = McastIntentManager.getInstance();
394 SinglePointToMultiPointIntent intent = im.setIntent(this);
395 this.intentKey = intent.key();
396 }
397
398 /**
399 * Set the Intent key.
400 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000401 * @param intent the multicast intent
alshabibeff00542015-09-23 13:22:33 -0700402 */
403 @Override
404 public void setIntent(SinglePointToMultiPointIntent intent) {
405 intentKey = intent.key();
406 }
407
408 /**
409 * Get the intent key represented by this route.
410 *
411 * @return intentKey
412 */
413 @Override
414 public Key getIntentKey() {
415 return this.intentKey;
416 }
417
418
419 /**
420 * Withdraw the intent and set the key to null.
421 */
422 @Override
423 public void withdrawIntent() {
424 if (intentKey == null) {
425 // nothing to withdraw
426 return;
427 }
428 McastIntentManager im = McastIntentManager.getInstance();
429 im.withdrawIntent(this);
430 this.intentKey = null;
431 }
432
433 /**
434 * Pretty Print this Multicast Route. Works for McastRouteSource and McastRouteGroup.
435 *
436 * @return pretty string of the multicast route
437 */
438 @Override
439 public String toString() {
440 String out = String.format("(%s, %s)\n\t",
441 saddr.toString(), gaddr.toString());
442
443 out += "intent: ";
444 out += (intentKey == null) ? "not installed" : this.intentKey.toString();
445 out += "\n\tingress: ";
Julian Lawrence14c73182015-10-08 18:31:52 -0700446 out += (ingressPoint == null) ? "NULL" : ingressPoint.getConnectPoint().toString();
alshabibeff00542015-09-23 13:22:33 -0700447 out += "\n\tegress: {\n";
448 if (egressPoints != null && !egressPoints.isEmpty()) {
Rusty Eddyddef8932015-09-25 01:15:53 +0000449 for (McastConnectPoint eg : egressPoints) {
450 out += "\t\t" + eg.getConnectPoint().toString() + "\n";
alshabibeff00542015-09-23 13:22:33 -0700451 }
452 }
453 out += ("\t}\n");
454 out += ("\tpunted: " + this.getPuntCount() + "\n");
455 return out;
456 }
457}