Committed by
Gerrit Code Review
CORD-48 Fixing filtering rule bug in multi-instance operation.
Change-Id: Ie91b2efcebff1bdb14357b6720ff8214a712cdc2
Showing
5 changed files
with
54 additions
and
28 deletions
... | @@ -35,7 +35,8 @@ import org.slf4j.Logger; | ... | @@ -35,7 +35,8 @@ import org.slf4j.Logger; |
35 | import org.slf4j.LoggerFactory; | 35 | import org.slf4j.LoggerFactory; |
36 | 36 | ||
37 | import java.nio.ByteBuffer; | 37 | import java.nio.ByteBuffer; |
38 | -import java.util.List; | 38 | +import java.util.Set; |
39 | + | ||
39 | import static com.google.common.base.Preconditions.checkNotNull; | 40 | import static com.google.common.base.Preconditions.checkNotNull; |
40 | 41 | ||
41 | public class ArpHandler { | 42 | public class ArpHandler { |
... | @@ -112,7 +113,7 @@ public class ArpHandler { | ... | @@ -112,7 +113,7 @@ public class ArpHandler { |
112 | 113 | ||
113 | 114 | ||
114 | private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { | 115 | private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) { |
115 | - List<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); | 116 | + Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); |
116 | if (gatewayIpAddresses != null) { | 117 | if (gatewayIpAddresses != null) { |
117 | Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest | 118 | Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest |
118 | .getTargetProtocolAddress()); | 119 | .getTargetProtocolAddress()); | ... | ... |
... | @@ -312,14 +312,14 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -312,14 +312,14 @@ public class DeviceConfiguration implements DeviceProperties { |
312 | * on those ports. | 312 | * on those ports. |
313 | * | 313 | * |
314 | * @param deviceId device identifier | 314 | * @param deviceId device identifier |
315 | - * @return list of ip addresses configured on the ports or null if not found | 315 | + * @return immutable set of ip addresses configured on the ports or null if not found |
316 | */ | 316 | */ |
317 | - public List<Ip4Address> getPortIPs(DeviceId deviceId) { | 317 | + public Set<Ip4Address> getPortIPs(DeviceId deviceId) { |
318 | SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); | 318 | SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId); |
319 | if (srinfo != null) { | 319 | if (srinfo != null) { |
320 | log.trace("getSubnetGatewayIps for device{} is {}", deviceId, | 320 | log.trace("getSubnetGatewayIps for device{} is {}", deviceId, |
321 | srinfo.gatewayIps.values()); | 321 | srinfo.gatewayIps.values()); |
322 | - return new ArrayList<>(srinfo.gatewayIps.values()); | 322 | + return ImmutableSet.copyOf(srinfo.gatewayIps.values()); |
323 | } | 323 | } |
324 | return null; | 324 | return null; |
325 | } | 325 | } | ... | ... |
... | @@ -32,7 +32,7 @@ import org.slf4j.Logger; | ... | @@ -32,7 +32,7 @@ import org.slf4j.Logger; |
32 | import org.slf4j.LoggerFactory; | 32 | import org.slf4j.LoggerFactory; |
33 | 33 | ||
34 | import java.nio.ByteBuffer; | 34 | import java.nio.ByteBuffer; |
35 | -import java.util.List; | 35 | +import java.util.Set; |
36 | 36 | ||
37 | import static com.google.common.base.Preconditions.checkNotNull; | 37 | import static com.google.common.base.Preconditions.checkNotNull; |
38 | 38 | ||
... | @@ -70,7 +70,7 @@ public class IcmpHandler { | ... | @@ -70,7 +70,7 @@ public class IcmpHandler { |
70 | DeviceId deviceId = connectPoint.deviceId(); | 70 | DeviceId deviceId = connectPoint.deviceId(); |
71 | Ip4Address destinationAddress = | 71 | Ip4Address destinationAddress = |
72 | Ip4Address.valueOf(ipv4.getDestinationAddress()); | 72 | Ip4Address.valueOf(ipv4.getDestinationAddress()); |
73 | - List<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); | 73 | + Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId); |
74 | Ip4Address routerIp = config.getRouterIp(deviceId); | 74 | Ip4Address routerIp = config.getRouterIp(deviceId); |
75 | IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); | 75 | IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH); |
76 | Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); | 76 | Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address(); | ... | ... |
... | @@ -45,6 +45,7 @@ import org.slf4j.Logger; | ... | @@ -45,6 +45,7 @@ import org.slf4j.Logger; |
45 | import org.slf4j.LoggerFactory; | 45 | import org.slf4j.LoggerFactory; |
46 | 46 | ||
47 | import java.util.ArrayList; | 47 | import java.util.ArrayList; |
48 | +import java.util.HashSet; | ||
48 | import java.util.List; | 49 | import java.util.List; |
49 | import java.util.Set; | 50 | import java.util.Set; |
50 | import java.util.concurrent.atomic.AtomicLong; | 51 | import java.util.concurrent.atomic.AtomicLong; |
... | @@ -361,6 +362,10 @@ public class RoutingRulePopulator { | ... | @@ -361,6 +362,10 @@ public class RoutingRulePopulator { |
361 | * dstMac corresponding to the router's MAC address. For those pipelines | 362 | * dstMac corresponding to the router's MAC address. For those pipelines |
362 | * that need to internally assign vlans to untagged packets, this method | 363 | * that need to internally assign vlans to untagged packets, this method |
363 | * provides per-subnet vlan-ids as metadata. | 364 | * provides per-subnet vlan-ids as metadata. |
365 | + * <p> | ||
366 | + * Note that the vlan assignment is only done by the master-instance for a switch. | ||
367 | + * However we send the filtering objective from slave-instances as well, so | ||
368 | + * that drivers can obtain other information (like Router MAC and IP). | ||
364 | * | 369 | * |
365 | * @param deviceId the switch dpid for the router | 370 | * @param deviceId the switch dpid for the router |
366 | */ | 371 | */ |
... | @@ -373,16 +378,16 @@ public class RoutingRulePopulator { | ... | @@ -373,16 +378,16 @@ public class RoutingRulePopulator { |
373 | VlanId assignedVlan = (portSubnet == null) | 378 | VlanId assignedVlan = (portSubnet == null) |
374 | ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) | 379 | ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET) |
375 | : srManager.getSubnetAssignedVlanId(deviceId, portSubnet); | 380 | : srManager.getSubnetAssignedVlanId(deviceId, portSubnet); |
376 | - TrafficTreatment tt = DefaultTrafficTreatment.builder() | ||
377 | - .pushVlan().setVlanId(assignedVlan).build(); | ||
378 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 381 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
379 | fob.withKey(Criteria.matchInPort(port.number())) | 382 | fob.withKey(Criteria.matchInPort(port.number())) |
380 | .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId))) | 383 | .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId))) |
381 | - .addCondition(Criteria.matchVlanId(VlanId.NONE)) | 384 | + .addCondition(Criteria.matchVlanId(VlanId.NONE)); |
382 | - .setMeta(tt) | 385 | + // vlan assignment is valid only if this instance is master |
383 | - .addCondition(Criteria.matchIPDst(IpPrefix.valueOf( | 386 | + if (srManager.mastershipService.isLocalMaster(deviceId)) { |
384 | - config.getRouterIp(deviceId), | 387 | + TrafficTreatment tt = DefaultTrafficTreatment.builder() |
385 | - IpPrefix.MAX_INET_MASK_LENGTH))); | 388 | + .pushVlan().setVlanId(assignedVlan).build(); |
389 | + fob.setMeta(tt); | ||
390 | + } | ||
386 | fob.permit().fromApp(srManager.appId); | 391 | fob.permit().fromApp(srManager.appId); |
387 | srManager.flowObjectiveService. | 392 | srManager.flowObjectiveService. |
388 | filter(deviceId, fob.add(new SRObjectiveContext(deviceId, | 393 | filter(deviceId, fob.add(new SRObjectiveContext(deviceId, |
... | @@ -393,16 +398,22 @@ public class RoutingRulePopulator { | ... | @@ -393,16 +398,22 @@ public class RoutingRulePopulator { |
393 | 398 | ||
394 | /** | 399 | /** |
395 | * Creates a forwarding objective to punt all IP packets, destined to the | 400 | * Creates a forwarding objective to punt all IP packets, destined to the |
396 | - * router's port IP addresses, to the controller. Note that it the input | 401 | + * router's port IP addresses, to the controller. Note that the input |
397 | * port should not be matched on, as these packets can come from any input. | 402 | * port should not be matched on, as these packets can come from any input. |
403 | + * Furthermore, these are applied only by the master instance. | ||
398 | * | 404 | * |
399 | * @param deviceId the switch dpid for the router | 405 | * @param deviceId the switch dpid for the router |
400 | */ | 406 | */ |
401 | public void populateRouterIpPunts(DeviceId deviceId) { | 407 | public void populateRouterIpPunts(DeviceId deviceId) { |
408 | + if (!srManager.mastershipService.isLocalMaster(deviceId)) { | ||
409 | + log.debug("Not installing port-IP punts - not the master for dev:{} ", | ||
410 | + deviceId); | ||
411 | + return; | ||
412 | + } | ||
402 | ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder(); | 413 | ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder(); |
403 | - | 414 | + Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId)); |
404 | - List<Ip4Address> gws = config.getPortIPs(deviceId); | 415 | + allIps.add(config.getRouterIp(deviceId)); |
405 | - for (Ip4Address ipaddr : gws) { | 416 | + for (Ip4Address ipaddr : allIps) { |
406 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 417 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
407 | TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); | 418 | TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); |
408 | selector.matchEthType(Ethernet.TYPE_IPV4); | 419 | selector.matchEthType(Ethernet.TYPE_IPV4); | ... | ... |
... | @@ -533,6 +533,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -533,6 +533,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
533 | event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED || | 533 | event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED || |
534 | event.type() == DeviceEvent.Type.DEVICE_UPDATED) { | 534 | event.type() == DeviceEvent.Type.DEVICE_UPDATED) { |
535 | if (deviceService.isAvailable(((Device) event.subject()).id())) { | 535 | if (deviceService.isAvailable(((Device) event.subject()).id())) { |
536 | + log.info("Processing device event {} for available device {}", | ||
537 | + event.type(), ((Device) event.subject()).id()); | ||
536 | processDeviceAdded((Device) event.subject()); | 538 | processDeviceAdded((Device) event.subject()); |
537 | } | 539 | } |
538 | } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) { | 540 | } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) { |
... | @@ -594,11 +596,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -594,11 +596,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
594 | 596 | ||
595 | private void processDeviceAdded(Device device) { | 597 | private void processDeviceAdded(Device device) { |
596 | log.debug("A new device with ID {} was added", device.id()); | 598 | log.debug("A new device with ID {} was added", device.id()); |
597 | - //Irrespective whether the local is a MASTER or not for this device, | 599 | + // Irrespective of whether the local is a MASTER or not for this device, |
598 | - //create group handler instance and push default TTP flow rules. | 600 | + // we need to create a SR-group-handler instance. This is because in a |
599 | - //Because in a multi-instance setup, instances can initiate | 601 | + // multi-instance setup, any instance can initiate forwarding/next-objectives |
600 | - //groups for any devices. Also the default TTP rules are needed | 602 | + // for any switch (even if this instance is a SLAVE or not even connected |
601 | - //to be pushed before inserting any IP table entries for any device | 603 | + // to the switch). To handle this, a default-group-handler instance is necessary |
604 | + // per switch. | ||
602 | DefaultGroupHandler groupHandler = DefaultGroupHandler. | 605 | DefaultGroupHandler groupHandler = DefaultGroupHandler. |
603 | createGroupHandler(device.id(), | 606 | createGroupHandler(device.id(), |
604 | appId, | 607 | appId, |
... | @@ -608,6 +611,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -608,6 +611,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
608 | nsNextObjStore, | 611 | nsNextObjStore, |
609 | subnetNextObjStore); | 612 | subnetNextObjStore); |
610 | groupHandlerMap.put(device.id(), groupHandler); | 613 | groupHandlerMap.put(device.id(), groupHandler); |
614 | + | ||
615 | + // Also, in some cases, drivers may need extra | ||
616 | + // information to process rules (eg. Router IP/MAC); and so, we send | ||
617 | + // port addressing rules to the driver as well irrespective of whether | ||
618 | + // this instance is the master or not. | ||
611 | defaultRoutingHandler.populatePortAddressingRules(device.id()); | 619 | defaultRoutingHandler.populatePortAddressingRules(device.id()); |
612 | 620 | ||
613 | if (mastershipService.isLocalMaster(device.id())) { | 621 | if (mastershipService.isLocalMaster(device.id())) { |
... | @@ -646,11 +654,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -646,11 +654,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
646 | tunnelHandler, policyStore); | 654 | tunnelHandler, policyStore); |
647 | 655 | ||
648 | for (Device device : deviceService.getDevices()) { | 656 | for (Device device : deviceService.getDevices()) { |
649 | - //Irrespective whether the local is a MASTER or not for this device, | 657 | + // Irrespective of whether the local is a MASTER or not for this device, |
650 | - //create group handler instance and push default TTP flow rules. | 658 | + // we need to create a SR-group-handler instance. This is because in a |
651 | - //Because in a multi-instance setup, instances can initiate | 659 | + // multi-instance setup, any instance can initiate forwarding/next-objectives |
652 | - //groups for any devices. Also the default TTP rules are needed | 660 | + // for any switch (even if this instance is a SLAVE or not even connected |
653 | - //to be pushed before inserting any IP table entries for any device | 661 | + // to the switch). To handle this, a default-group-handler instance is necessary |
662 | + // per switch. | ||
654 | DefaultGroupHandler groupHandler = DefaultGroupHandler | 663 | DefaultGroupHandler groupHandler = DefaultGroupHandler |
655 | .createGroupHandler(device.id(), appId, | 664 | .createGroupHandler(device.id(), appId, |
656 | deviceConfiguration, linkService, | 665 | deviceConfiguration, linkService, |
... | @@ -658,6 +667,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -658,6 +667,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
658 | nsNextObjStore, | 667 | nsNextObjStore, |
659 | subnetNextObjStore); | 668 | subnetNextObjStore); |
660 | groupHandlerMap.put(device.id(), groupHandler); | 669 | groupHandlerMap.put(device.id(), groupHandler); |
670 | + | ||
671 | + // Also, in some cases, drivers may need extra | ||
672 | + // information to process rules (eg. Router IP/MAC); and so, we send | ||
673 | + // port addressing rules to the driver as well, irrespective of whether | ||
674 | + // this instance is the master or not. | ||
661 | defaultRoutingHandler.populatePortAddressingRules(device.id()); | 675 | defaultRoutingHandler.populatePortAddressingRules(device.id()); |
662 | 676 | ||
663 | if (mastershipService.isLocalMaster(device.id())) { | 677 | if (mastershipService.isLocalMaster(device.id())) { | ... | ... |
-
Please register or login to post a comment