CORD-135 Support Multicast Source on a Configured Port
Missing part of gerrit #9230 Forwarding objective need to check the existing VLAN as well Change-Id: I8e9cadc57c332a20567eaeaa2030901fc2dbf5b8
Showing
1 changed file
with
58 additions
and
27 deletions
| ... | @@ -197,7 +197,6 @@ public class McastHandler { | ... | @@ -197,7 +197,6 @@ public class McastHandler { |
| 197 | ConnectPoint source = mcastRouteInfo.source().orElse(null); | 197 | ConnectPoint source = mcastRouteInfo.source().orElse(null); |
| 198 | ConnectPoint sink = mcastRouteInfo.sink().orElse(null); | 198 | ConnectPoint sink = mcastRouteInfo.sink().orElse(null); |
| 199 | IpAddress mcastIp = mcastRouteInfo.route().group(); | 199 | IpAddress mcastIp = mcastRouteInfo.route().group(); |
| 200 | - VlanId assignedVlan = assignedVlan(); | ||
| 201 | 200 | ||
| 202 | // When source and sink are on the same device | 201 | // When source and sink are on the same device |
| 203 | if (source.deviceId().equals(sink.deviceId())) { | 202 | if (source.deviceId().equals(sink.deviceId())) { |
| ... | @@ -206,12 +205,12 @@ public class McastHandler { | ... | @@ -206,12 +205,12 @@ public class McastHandler { |
| 206 | log.warn("Sink is on the same port of source. Abort"); | 205 | log.warn("Sink is on the same port of source. Abort"); |
| 207 | return; | 206 | return; |
| 208 | } | 207 | } |
| 209 | - removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan); | 208 | + removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan(source)); |
| 210 | return; | 209 | return; |
| 211 | } | 210 | } |
| 212 | 211 | ||
| 213 | // Process the egress device | 212 | // Process the egress device |
| 214 | - boolean isLast = removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan); | 213 | + boolean isLast = removePortFromDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan(null)); |
| 215 | if (isLast) { | 214 | if (isLast) { |
| 216 | mcastRoleStore.remove(new McastStoreKey(mcastIp, sink.deviceId())); | 215 | mcastRoleStore.remove(new McastStoreKey(mcastIp, sink.deviceId())); |
| 217 | } | 216 | } |
| ... | @@ -224,7 +223,8 @@ public class McastHandler { | ... | @@ -224,7 +223,8 @@ public class McastHandler { |
| 224 | for (Link link : links) { | 223 | for (Link link : links) { |
| 225 | if (isLast) { | 224 | if (isLast) { |
| 226 | isLast = removePortFromDevice(link.src().deviceId(), link.src().port(), | 225 | isLast = removePortFromDevice(link.src().deviceId(), link.src().port(), |
| 227 | - mcastIp, assignedVlan); | 226 | + mcastIp, |
| 227 | + assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null)); | ||
| 228 | mcastRoleStore.remove(new McastStoreKey(mcastIp, link.src().deviceId())); | 228 | mcastRoleStore.remove(new McastStoreKey(mcastIp, link.src().deviceId())); |
| 229 | } | 229 | } |
| 230 | } | 230 | } |
| ... | @@ -240,10 +240,8 @@ public class McastHandler { | ... | @@ -240,10 +240,8 @@ public class McastHandler { |
| 240 | */ | 240 | */ |
| 241 | private void processSinkAddedInternal(ConnectPoint source, ConnectPoint sink, | 241 | private void processSinkAddedInternal(ConnectPoint source, ConnectPoint sink, |
| 242 | IpAddress mcastIp) { | 242 | IpAddress mcastIp) { |
| 243 | - VlanId assignedVlan = assignedVlan(); | ||
| 244 | - | ||
| 245 | // Process the ingress device | 243 | // Process the ingress device |
| 246 | - addFilterToDevice(source.deviceId(), source.port(), assignedVlan); | 244 | + addFilterToDevice(source.deviceId(), source.port(), assignedVlan(source)); |
| 247 | 245 | ||
| 248 | // When source and sink are on the same device | 246 | // When source and sink are on the same device |
| 249 | if (source.deviceId().equals(sink.deviceId())) { | 247 | if (source.deviceId().equals(sink.deviceId())) { |
| ... | @@ -252,7 +250,7 @@ public class McastHandler { | ... | @@ -252,7 +250,7 @@ public class McastHandler { |
| 252 | log.warn("Sink is on the same port of source. Abort"); | 250 | log.warn("Sink is on the same port of source. Abort"); |
| 253 | return; | 251 | return; |
| 254 | } | 252 | } |
| 255 | - addPortToDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan); | 253 | + addPortToDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan(source)); |
| 256 | mcastRoleStore.put(new McastStoreKey(mcastIp, sink.deviceId()), McastRole.INGRESS); | 254 | mcastRoleStore.put(new McastStoreKey(mcastIp, sink.deviceId()), McastRole.INGRESS); |
| 257 | return; | 255 | return; |
| 258 | } | 256 | } |
| ... | @@ -265,12 +263,13 @@ public class McastHandler { | ... | @@ -265,12 +263,13 @@ public class McastHandler { |
| 265 | "Path in leaf-spine topology should always be two hops: ", links); | 263 | "Path in leaf-spine topology should always be two hops: ", links); |
| 266 | 264 | ||
| 267 | links.forEach(link -> { | 265 | links.forEach(link -> { |
| 268 | - addFilterToDevice(link.dst().deviceId(), link.dst().port(), assignedVlan); | 266 | + addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp, |
| 269 | - addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp, assignedVlan); | 267 | + assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null)); |
| 268 | + addFilterToDevice(link.dst().deviceId(), link.dst().port(), assignedVlan(null)); | ||
| 270 | }); | 269 | }); |
| 271 | 270 | ||
| 272 | // Process the egress device | 271 | // Process the egress device |
| 273 | - addPortToDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan); | 272 | + addPortToDevice(sink.deviceId(), sink.port(), mcastIp, assignedVlan(null)); |
| 274 | 273 | ||
| 275 | // Setup mcast roles | 274 | // Setup mcast roles |
| 276 | mcastRoleStore.put(new McastStoreKey(mcastIp, source.deviceId()), | 275 | mcastRoleStore.put(new McastStoreKey(mcastIp, source.deviceId()), |
| ... | @@ -291,8 +290,6 @@ public class McastHandler { | ... | @@ -291,8 +290,6 @@ public class McastHandler { |
| 291 | * @param affectedLink Link that is going down | 290 | * @param affectedLink Link that is going down |
| 292 | */ | 291 | */ |
| 293 | protected void processLinkDown(Link affectedLink) { | 292 | protected void processLinkDown(Link affectedLink) { |
| 294 | - VlanId assignedVlan = assignedVlan(); | ||
| 295 | - | ||
| 296 | getAffectedGroups(affectedLink).forEach(mcastIp -> { | 293 | getAffectedGroups(affectedLink).forEach(mcastIp -> { |
| 297 | // Find out the ingress, transit and egress device of affected group | 294 | // Find out the ingress, transit and egress device of affected group |
| 298 | DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS) | 295 | DeviceId ingressDevice = getDevice(mcastIp, McastRole.INGRESS) |
| ... | @@ -300,19 +297,23 @@ public class McastHandler { | ... | @@ -300,19 +297,23 @@ public class McastHandler { |
| 300 | DeviceId transitDevice = getDevice(mcastIp, McastRole.TRANSIT) | 297 | DeviceId transitDevice = getDevice(mcastIp, McastRole.TRANSIT) |
| 301 | .stream().findAny().orElse(null); | 298 | .stream().findAny().orElse(null); |
| 302 | Set<DeviceId> egressDevices = getDevice(mcastIp, McastRole.EGRESS); | 299 | Set<DeviceId> egressDevices = getDevice(mcastIp, McastRole.EGRESS); |
| 303 | - if (ingressDevice == null || transitDevice == null || egressDevices == null) { | 300 | + ConnectPoint source = getSource(mcastIp); |
| 304 | - log.warn("Missing ingress {}, transit {}, or egress {} devices", | 301 | + |
| 305 | - ingressDevice, transitDevice, egressDevices); | 302 | + // Do not proceed if any of these info is missing |
| 303 | + if (ingressDevice == null || transitDevice == null | ||
| 304 | + || egressDevices == null || source == null) { | ||
| 305 | + log.warn("Missing ingress {}, transit {}, egress {} devices or source {}", | ||
| 306 | + ingressDevice, transitDevice, egressDevices, source); | ||
| 306 | return; | 307 | return; |
| 307 | } | 308 | } |
| 308 | 309 | ||
| 309 | // Remove entire transit | 310 | // Remove entire transit |
| 310 | - removeGroupFromDevice(transitDevice, mcastIp, assignedVlan); | 311 | + removeGroupFromDevice(transitDevice, mcastIp, assignedVlan(null)); |
| 311 | 312 | ||
| 312 | // Remove transit-facing port on ingress device | 313 | // Remove transit-facing port on ingress device |
| 313 | PortNumber ingressTransitPort = ingressTransitPort(mcastIp); | 314 | PortNumber ingressTransitPort = ingressTransitPort(mcastIp); |
| 314 | if (ingressTransitPort != null) { | 315 | if (ingressTransitPort != null) { |
| 315 | - removePortFromDevice(ingressDevice, ingressTransitPort, mcastIp, assignedVlan); | 316 | + removePortFromDevice(ingressDevice, ingressTransitPort, mcastIp, assignedVlan(source)); |
| 316 | mcastRoleStore.remove(new McastStoreKey(mcastIp, transitDevice)); | 317 | mcastRoleStore.remove(new McastStoreKey(mcastIp, transitDevice)); |
| 317 | } | 318 | } |
| 318 | 319 | ||
| ... | @@ -322,8 +323,9 @@ public class McastHandler { | ... | @@ -322,8 +323,9 @@ public class McastHandler { |
| 322 | if (mcastPath.isPresent()) { | 323 | if (mcastPath.isPresent()) { |
| 323 | List<Link> links = mcastPath.get().links(); | 324 | List<Link> links = mcastPath.get().links(); |
| 324 | links.forEach(link -> { | 325 | links.forEach(link -> { |
| 325 | - addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp, assignedVlan); | 326 | + addPortToDevice(link.src().deviceId(), link.src().port(), mcastIp, |
| 326 | - addFilterToDevice(link.dst().deviceId(), link.dst().port(), assignedVlan); | 327 | + assignedVlan(link.src().deviceId().equals(source.deviceId()) ? source : null)); |
| 328 | + addFilterToDevice(link.dst().deviceId(), link.dst().port(), assignedVlan(null)); | ||
| 327 | }); | 329 | }); |
| 328 | // Setup new transit mcast role | 330 | // Setup new transit mcast role |
| 329 | mcastRoleStore.put(new McastStoreKey(mcastIp, | 331 | mcastRoleStore.put(new McastStoreKey(mcastIp, |
| ... | @@ -331,7 +333,7 @@ public class McastHandler { | ... | @@ -331,7 +333,7 @@ public class McastHandler { |
| 331 | } else { | 333 | } else { |
| 332 | log.warn("Fail to recover egress device {} from link failure {}", | 334 | log.warn("Fail to recover egress device {} from link failure {}", |
| 333 | egressDevice, affectedLink); | 335 | egressDevice, affectedLink); |
| 334 | - removeGroupFromDevice(egressDevice, mcastIp, assignedVlan); | 336 | + removeGroupFromDevice(egressDevice, mcastIp, assignedVlan(null)); |
| 335 | } | 337 | } |
| 336 | }); | 338 | }); |
| 337 | }); | 339 | }); |
| ... | @@ -521,7 +523,9 @@ public class McastHandler { | ... | @@ -521,7 +523,9 @@ public class McastHandler { |
| 521 | while (itNextObj.hasNext()) { | 523 | while (itNextObj.hasNext()) { |
| 522 | Map.Entry<McastStoreKey, Versioned<NextObjective>> entry = itNextObj.next(); | 524 | Map.Entry<McastStoreKey, Versioned<NextObjective>> entry = itNextObj.next(); |
| 523 | if (entry.getKey().deviceId().equals(deviceId)) { | 525 | if (entry.getKey().deviceId().equals(deviceId)) { |
| 524 | - removeGroupFromDevice(entry.getKey().deviceId(), entry.getKey().mcastIp(), assignedVlan()); | 526 | + ConnectPoint source = getSource(entry.getKey().mcastIp()); |
| 527 | + removeGroupFromDevice(entry.getKey().deviceId(), entry.getKey().mcastIp(), | ||
| 528 | + assignedVlan(deviceId.equals(source.deviceId()) ? source : null)); | ||
| 525 | itNextObj.remove(); | 529 | itNextObj.remove(); |
| 526 | } | 530 | } |
| 527 | } | 531 | } |
| ... | @@ -693,6 +697,19 @@ public class McastHandler { | ... | @@ -693,6 +697,19 @@ public class McastHandler { |
| 693 | } | 697 | } |
| 694 | 698 | ||
| 695 | /** | 699 | /** |
| 700 | + * Gets source connect point of given multicast group. | ||
| 701 | + * | ||
| 702 | + * @param mcastIp multicast IP | ||
| 703 | + * @return source connect point or null if not found | ||
| 704 | + */ | ||
| 705 | + private ConnectPoint getSource(IpAddress mcastIp) { | ||
| 706 | + return srManager.multicastRouteService.getRoutes().stream() | ||
| 707 | + .filter(mcastRoute -> mcastRoute.group().equals(mcastIp)) | ||
| 708 | + .map(mcastRoute -> srManager.multicastRouteService.fetchSource(mcastRoute)) | ||
| 709 | + .findAny().orElse(null); | ||
| 710 | + } | ||
| 711 | + | ||
| 712 | + /** | ||
| 696 | * Gets groups which is affected by the link down event. | 713 | * Gets groups which is affected by the link down event. |
| 697 | * | 714 | * |
| 698 | * @param link link going down | 715 | * @param link link going down |
| ... | @@ -721,13 +738,27 @@ public class McastHandler { | ... | @@ -721,13 +738,27 @@ public class McastHandler { |
| 721 | 738 | ||
| 722 | /** | 739 | /** |
| 723 | * Gets assigned VLAN according to the value of egress VLAN. | 740 | * Gets assigned VLAN according to the value of egress VLAN. |
| 741 | + * If connect point is specified, try to reuse the assigned VLAN on the connect point. | ||
| 724 | * | 742 | * |
| 725 | - * @return assigned VLAN | 743 | + * @param cp connect point; Can be null if not specified |
| 744 | + * @return assigned VLAN ID | ||
| 726 | */ | 745 | */ |
| 727 | - private VlanId assignedVlan() { | 746 | + private VlanId assignedVlan(ConnectPoint cp) { |
| 728 | - return (egressVlan().equals(VlanId.NONE)) ? | 747 | + // Use the egressVlan if it is tagged |
| 729 | - VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) : | 748 | + if (!egressVlan().equals(VlanId.NONE)) { |
| 730 | - egressVlan(); | 749 | + return egressVlan(); |
| 750 | + } | ||
| 751 | + // Reuse unicast VLAN if the port has subnet configured | ||
| 752 | + if (cp != null) { | ||
| 753 | + Ip4Prefix portSubnet = srManager.deviceConfiguration | ||
| 754 | + .getPortSubnet(cp.deviceId(), cp.port()); | ||
| 755 | + VlanId unicastVlan = srManager.getSubnetAssignedVlanId(cp.deviceId(), portSubnet); | ||
| 756 | + if (unicastVlan != null) { | ||
| 757 | + return unicastVlan; | ||
| 758 | + } | ||
| 759 | + } | ||
| 760 | + // By default, use VLAN_NO_SUBNET | ||
| 761 | + return VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET); | ||
| 731 | } | 762 | } |
| 732 | 763 | ||
| 733 | /** | 764 | /** | ... | ... |
-
Please register or login to post a comment