Saurav Das
Committed by Gerrit Code Review

CORD-48 Fixing filtering rule bug in multi-instance operation.

Change-Id: Ie91b2efcebff1bdb14357b6720ff8214a712cdc2
...@@ -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())) {
......