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