Jonathan Hart
Committed by Gerrit Code Review

Support source-specific IGMP joins.

Change-Id: I422f54f908998460ceff994f9b3bfbf3d2f81a56
...@@ -320,32 +320,57 @@ public class IgmpSnoop { ...@@ -320,32 +320,57 @@ public class IgmpSnoop {
320 320
321 IGMPMembership membership = (IGMPMembership) group; 321 IGMPMembership membership = (IGMPMembership) group;
322 322
323 - // TODO allow pulling source from IGMP packet 323 + IpAddress groupAddress = membership.getGaddr();
324 - IpAddress source = ssmTranslateTable.get(group.getGaddr());
325 - if (source == null) {
326 - log.warn("No source found in SSM translate table for {}", group.getGaddr());
327 - return;
328 - }
329 -
330 - McastRoute route = new McastRoute(source,
331 - group.getGaddr(),
332 - McastRoute.Type.IGMP);
333 324
334 if (membership.getRecordType() == IGMPMembership.MODE_IS_INCLUDE || 325 if (membership.getRecordType() == IGMPMembership.MODE_IS_INCLUDE ||
335 membership.getRecordType() == IGMPMembership.CHANGE_TO_INCLUDE_MODE) { 326 membership.getRecordType() == IGMPMembership.CHANGE_TO_INCLUDE_MODE) {
336 327
337 - multicastService.removeSink(route, location); 328 + if (membership.getSources().isEmpty()) {
338 - // TODO remove route if all sinks are gone 329 + McastRoute route = ssmTranslateRoute(groupAddress);
330 + if (route != null) {
331 + removeRoute(route, location);
332 + }
333 + } else {
334 + membership.getSources().stream()
335 + .map(source -> new McastRoute(source, groupAddress, McastRoute.Type.IGMP))
336 + .forEach(route -> addRoute(route, location));
337 + }
339 } else if (membership.getRecordType() == IGMPMembership.MODE_IS_EXCLUDE || 338 } else if (membership.getRecordType() == IGMPMembership.MODE_IS_EXCLUDE ||
340 membership.getRecordType() == IGMPMembership.CHANGE_TO_EXCLUDE_MODE) { 339 membership.getRecordType() == IGMPMembership.CHANGE_TO_EXCLUDE_MODE) {
341 340
342 - multicastService.add(route); 341 + if (membership.getSources().isEmpty()) {
343 - multicastService.addSink(route, location); 342 + McastRoute route = ssmTranslateRoute(groupAddress);
343 + if (route != null) {
344 + addRoute(route, location);
345 + }
346 + } else {
347 + membership.getSources().stream()
348 + .map(source -> new McastRoute(source, groupAddress, McastRoute.Type.IGMP))
349 + .forEach(route -> removeRoute(route, location));
350 + }
344 } 351 }
345 -
346 }); 352 });
347 } 353 }
348 354
355 + private McastRoute ssmTranslateRoute(IpAddress group) {
356 + IpAddress source = ssmTranslateTable.get(group);
357 + if (source == null) {
358 + log.warn("No SSM translate source found for group {}", group);
359 + return null;
360 + }
361 + return new McastRoute(source, group, McastRoute.Type.IGMP);
362 + }
363 +
364 + private void addRoute(McastRoute route, ConnectPoint location) {
365 + multicastService.add(route);
366 + multicastService.addSink(route, location);
367 + }
368 +
369 + private void removeRoute(McastRoute route, ConnectPoint location) {
370 + multicastService.removeSink(route, location);
371 + // TODO remove route if all sinks are gone
372 + }
373 +
349 private ByteBuffer buildQueryPacket() { 374 private ByteBuffer buildQueryPacket() {
350 IGMP igmp = new IGMP(); 375 IGMP igmp = new IGMP();
351 igmp.setIgmpType(IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY); 376 igmp.setIgmpType(IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY);
......