blob: 730acfa7beb572c6b585435ca8e1c88d758e911b [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
Rusty Eddyddef8932015-09-25 01:15:53 +000020import org.apache.commons.collections.set.ListOrderedSet;
alshabibeff00542015-09-23 13:22:33 -070021import org.onlab.packet.IpPrefix;
22import org.onosproject.net.ConnectPoint;
alshabibeff00542015-09-23 13:22:33 -070023import org.onosproject.net.intent.SinglePointToMultiPointIntent;
24import org.onosproject.net.intent.Key;
25
26import java.util.Set;
27import java.util.HashSet;
28
29/**
30 * McastRouteBase base class for McastRouteGroup and McastRouteSource.
31 */
32public class McastRouteBase implements McastRoute {
33 protected final IpPrefix gaddr;
34 protected final IpPrefix saddr;
35
Rusty Eddyddef8932015-09-25 01:15:53 +000036 protected McastConnectPoint ingressPoint;
37 protected Set<McastConnectPoint> egressPoints;
alshabibeff00542015-09-23 13:22:33 -070038
39 protected boolean isGroup = false;
40
Rusty Eddyddef8932015-09-25 01:15:53 +000041 protected boolean dirty = false;
42
alshabibeff00542015-09-23 13:22:33 -070043 /**
44 * How may times has this packet been punted.
45 */
46 private int puntCount = 0;
47
48 /**
49 * If the intentKey is null that means no intent has
50 * been installed.
51 */
52 protected Key intentKey = null;
53
54 /**
55 * Create a multicast route. This is the parent class for both the Group
56 * and the source.
57 *
58 * @param saddr source address
59 * @param gaddr multicast group address
60 */
61 public McastRouteBase(String saddr, String gaddr) {
62 this.gaddr = IpPrefix.valueOf(checkNotNull(gaddr));
63 if (saddr == null || saddr.equals("*")) {
64 this.saddr = IpPrefix.valueOf(0, 0);
65 } else {
66 this.saddr = IpPrefix.valueOf(checkNotNull(gaddr));
67 }
68 this.init();
69 }
70
71 /**
72 * Create a multicast group table entry.
73 * @param gaddr multicast group address
74 */
75 public McastRouteBase(String gaddr) {
76 this("*", gaddr);
77 }
78
79 /**
80 * Set the source and group address value of a (*, G) group.
81 *
82 * @param gpfx the group prefix address
83 */
84 public McastRouteBase(IpPrefix gpfx) {
85 this(IpPrefix.valueOf(0, 0), gpfx);
86 }
87
88 /**
89 * Create a multicast route constructor.
90 *
91 * @param saddr source address
92 * @param gaddr group address
93 */
94 public McastRouteBase(IpPrefix saddr, IpPrefix gaddr) {
95 this.saddr = checkNotNull(saddr);
96 this.gaddr = checkNotNull(gaddr);
97
98 this.init();
99 }
100
101 private void init() {
102 this.isGroup = (this.saddr.prefixLength() == 0);
103 this.ingressPoint = null;
104 this.egressPoints = new HashSet();
105 }
106
107 /**
108 * Get the multicast group address.
109 *
110 * @return the multicast group address
111 */
112 @Override
113 public IpPrefix getGaddr() {
114 return gaddr;
115 }
116
117 /**
118 * Get the multicast source address.
119 *
120 * @return the multicast source address
121 */
122 @Override
123 public IpPrefix getSaddr() {
124 return saddr;
125 }
126
127 /**
128 * Is this an IPv4 multicast route.
129 *
130 * @return true if it is an IPv4 route
131 */
132 @Override
133 public boolean isIp4() {
134 return gaddr.isIp4();
135 }
136
137 /**
138 * Is this an IPv6 multicast route.
139 *
140 * @return true if it is an IPv6 route
141 */
142 @Override
143 public boolean isIp6() {
144 return gaddr.isIp6();
145 }
146
147 /**
148 * Is this a multicast group route?
149 *
150 * @return true if it is a multicast group route.
151 */
152 public boolean isGroup() {
153 return isGroup;
154 }
155
156 /**
157 * @return true if this is (S, G) false if it (*, G).
158 */
159 public boolean isSource() {
160 return (!isGroup);
161 }
162
163 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000164 * Get the dirty state.
165 *
166 * @return whether this route is dirty or not.
167 */
168 public boolean getDirty() {
169 return this.dirty;
170 }
171
172 /**
173 * Set the dirty state to indicate that something changed.
174 * This may require an update to the flow tables (intents).
175 *
176 * @param dirty set the dirty bit
177 */
178 public void setDirty(boolean dirty) {
179 this.dirty = dirty;
180 }
181
182 /**
alshabibeff00542015-09-23 13:22:33 -0700183 * Add an ingress point to this route.
184 *
185 * @param ingress incoming connect point
Rusty Eddyddef8932015-09-25 01:15:53 +0000186 * @return whether ingress has been added, only add if ingressPoint is null
alshabibeff00542015-09-23 13:22:33 -0700187 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000188 public boolean addIngressPoint(ConnectPoint ingress) {
189
190 // Do NOT add the ingressPoint if it is not null.
191 if (this.ingressPoint != null) {
192 // TODO: Log an warning.
193 return false;
194 }
195 this.ingressPoint = new McastConnectPoint(checkNotNull(ingress));
196 setDirty(true);
197 return true;
alshabibeff00542015-09-23 13:22:33 -0700198 }
199
200 /**
201 * Add or modify the ingress connect point.
202 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000203 * @param connectPoint string switch device Id
204 * @return whether ingress has been added, only add if ingressPoint is null
alshabibeff00542015-09-23 13:22:33 -0700205 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000206 public boolean addIngressPoint(String connectPoint) {
207
208 if (this.ingressPoint != null) {
209 // TODO: log a warning.
210 return false;
211 }
212 ConnectPoint cp = ConnectPoint.deviceConnectPoint(checkNotNull(connectPoint));
213 return this.addIngressPoint(cp);
alshabibeff00542015-09-23 13:22:33 -0700214 }
215
216 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000217 * Get the ingress McastConnectPoint.
alshabibeff00542015-09-23 13:22:33 -0700218 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000219 * @return the ingress McastConnectPoint
alshabibeff00542015-09-23 13:22:33 -0700220 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000221 public McastConnectPoint getIngressPoint() {
alshabibeff00542015-09-23 13:22:33 -0700222 return this.ingressPoint;
223 }
224
225 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000226 * Add an egress McastConnectPoint.
alshabibeff00542015-09-23 13:22:33 -0700227 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000228 * @param cp egress connect point
229 * @return return the McastConnectPoint
alshabibeff00542015-09-23 13:22:33 -0700230 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000231 public McastConnectPoint addEgressPoint(ConnectPoint cp) {
232 McastConnectPoint mcp = this.findEgressConnectPoint(cp);
233 if (mcp == null) {
234 mcp = new McastConnectPoint(checkNotNull(cp));
235 egressPoints.add(mcp);
236 setDirty(true);
237 }
238 return mcp;
alshabibeff00542015-09-23 13:22:33 -0700239 }
240
241 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000242 * Add an egress connect point from a string.
alshabibeff00542015-09-23 13:22:33 -0700243 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000244 * @param connectPoint string representing a connect point
245 * @return the MulticastConnectPoint
alshabibeff00542015-09-23 13:22:33 -0700246 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000247 public McastConnectPoint addEgressPoint(String connectPoint) {
248 checkNotNull(connectPoint);
249 return this.addEgressPoint(ConnectPoint.deviceConnectPoint(connectPoint));
250 }
251
252 /**
253 * Add an egress McastConnectPoint.
254 *
255 * @param cp the egress connect point
256 * @param interest the source of interest for mcast traffic
257 */
258 public McastConnectPoint addEgressPoint(ConnectPoint cp, McastConnectPoint.JoinSource interest) {
259 checkNotNull(cp);
260 checkNotNull(interest);
261 McastConnectPoint mcp = this.addEgressPoint(cp);
262 if (mcp != null) {
263 mcp.interest.add(interest);
264 setDirty(true);
265 }
266 return mcp;
267 }
268
269 /**
270 * Add an egress McastConnectPoint.
271 *
272 * @param cpstr deviceId/port of the connect point
273 */
274 public McastConnectPoint addEgressPoint(String cpstr, McastConnectPoint.JoinSource interest) {
275 checkNotNull(cpstr);
276 checkNotNull(interest);
277 return this.addEgressPoint(ConnectPoint.deviceConnectPoint(cpstr), interest);
alshabibeff00542015-09-23 13:22:33 -0700278 }
279
280 /**
281 * Get egress connect points for the route.
282 *
283 * @return Set of egress connect points
284 */
Rusty Eddyddef8932015-09-25 01:15:53 +0000285 public Set<McastConnectPoint> getEgressPoints() {
alshabibeff00542015-09-23 13:22:33 -0700286 return egressPoints;
287 }
288
289 /**
Rusty Eddyddef8932015-09-25 01:15:53 +0000290 * Get egress McastConnectPoints points as ConnectPoints for intent system.
291 *
292 * @return Set of egress ConnectPoints
293 */
294 public Set<ConnectPoint> getEgressConnectPoints() {
295 Set<ConnectPoint> cps = new ListOrderedSet();
296
297 for (McastConnectPoint mcp : egressPoints) {
298 cps.add(mcp.getConnectPoint());
299 }
300 return cps;
301 }
302
303 /**
304 * Find the Multicast Connect Point that contains the ConnectPoint.
305 *
306 * @param cp the regular ConnectPoint to match
307 * @return the McastConnectPoint that contains cp or null if not found.
308 */
309 public McastConnectPoint findEgressConnectPoint(ConnectPoint cp) {
310 for (McastConnectPoint mcp : this.egressPoints) {
311 if (mcp.getConnectPoint().equals(cp)) {
312 return mcp;
313 }
314 }
315 return null;
316 }
317
318 /**
319 * Remove specified interest from the given ConnectPoint.
320 *
321 * @param mcp connect point.
322 * @param interest the protocol interested in this multicast stream
323 * @return true if removed, false otherwise
324 */
325 public boolean removeInterest(McastConnectPoint mcp, McastConnectPoint.JoinSource interest) {
326 checkNotNull(mcp);
327 if (mcp.interest.contains(interest)) {
328 mcp.interest.remove(interest);
329 setDirty(true);
330 return true;
331 }
332 return false;
333 }
334
335 /**
alshabibeff00542015-09-23 13:22:33 -0700336 * Get the number of times the packet has been punted.
337 *
338 * @return the punt count
339 */
340 @Override
341 public int getPuntCount() {
342 return puntCount;
343 }
344
345 /**
346 * Increment the punt count.
347 *
348 * TODO: we need to handle wrapping.
349 */
350 @Override
351 public void incrementPuntCount() {
352 puntCount++;
353 }
354
355 /**
356 * Have the McastIntentManager create and set the intent, then save the intent key.
357 *
358 * If we already have an intent, we will first withdraw the existing intent and
359 * replace it with a new one. This will support the case where the ingress connectPoint
360 * or group of egress connectPoints change.
361 */
362 @Override
363 public void setIntent() {
364 if (this.intentKey != null) {
365 this.withdrawIntent();
366 }
367 McastIntentManager im = McastIntentManager.getInstance();
368 SinglePointToMultiPointIntent intent = im.setIntent(this);
369 this.intentKey = intent.key();
370 }
371
372 /**
373 * Set the Intent key.
374 *
Rusty Eddyddef8932015-09-25 01:15:53 +0000375 * @param intent the multicast intent
alshabibeff00542015-09-23 13:22:33 -0700376 */
377 @Override
378 public void setIntent(SinglePointToMultiPointIntent intent) {
379 intentKey = intent.key();
380 }
381
382 /**
383 * Get the intent key represented by this route.
384 *
385 * @return intentKey
386 */
387 @Override
388 public Key getIntentKey() {
389 return this.intentKey;
390 }
391
392
393 /**
394 * Withdraw the intent and set the key to null.
395 */
396 @Override
397 public void withdrawIntent() {
398 if (intentKey == null) {
399 // nothing to withdraw
400 return;
401 }
402 McastIntentManager im = McastIntentManager.getInstance();
403 im.withdrawIntent(this);
404 this.intentKey = null;
405 }
406
407 /**
408 * Pretty Print this Multicast Route. Works for McastRouteSource and McastRouteGroup.
409 *
410 * @return pretty string of the multicast route
411 */
412 @Override
413 public String toString() {
414 String out = String.format("(%s, %s)\n\t",
415 saddr.toString(), gaddr.toString());
416
417 out += "intent: ";
418 out += (intentKey == null) ? "not installed" : this.intentKey.toString();
419 out += "\n\tingress: ";
420 out += (ingressPoint == null) ? "NULL" : ingressPoint.toString();
421 out += "\n\tegress: {\n";
422 if (egressPoints != null && !egressPoints.isEmpty()) {
Rusty Eddyddef8932015-09-25 01:15:53 +0000423 for (McastConnectPoint eg : egressPoints) {
424 out += "\t\t" + eg.getConnectPoint().toString() + "\n";
alshabibeff00542015-09-23 13:22:33 -0700425 }
426 }
427 out += ("\t}\n");
428 out += ("\tpunted: " + this.getPuntCount() + "\n");
429 return out;
430 }
431}