Dual-homing probing improvements
(1) Active probing mechanism in the following two scenarios
(1-1) Probe all ports on the pair device within the same vlan (excluding the pair port) when the 1st location of a host is learnt
(1-2) Probe again when a device/port goes down and comes up again
* Introduce HostLocationProvingService
- DISCOVER mode: discover potential new locations
- VERIFY mode: verify old locations
* Can be enabled/disabled via component config
* Improve HostHandlerTest to test the probing behavior
(2) Fix an issue that redirection flow doesn't get installed after device re-connects
(3) Temporarily fix a race condition in HostHandler by adding a little bit delay
Change-Id: I33d3fe94a6ca491a88b8e06f65bef11447ead0bf
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index d57a681..7a17d39 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.segmentrouting;
+
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
@@ -24,6 +25,8 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
@@ -35,6 +38,7 @@
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
+import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
@@ -64,6 +68,7 @@
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostLocationProbingService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intf.Interface;
@@ -106,10 +111,12 @@
import org.onosproject.store.service.EventuallyConsistentMapBuilder;
import org.onosproject.store.service.StorageService;
import org.onosproject.store.service.WallClockTimestamp;
+import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
+import java.util.Dictionary;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -158,6 +165,9 @@
HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ HostLocationProbingService probingService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -187,6 +197,10 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
public InterfaceService interfaceService;
+ @Property(name = "activeProbing", boolValue = true,
+ label = "Enable active probing to discover dual-homed hosts.")
+ boolean activeProbing = true;
+
ArpHandler arpHandler = null;
IcmpHandler icmpHandler = null;
IpHandler ipHandler = null;
@@ -226,19 +240,19 @@
* Per device next objective ID store with (device id + destination set) as key.
* Used to keep track on MPLS group information.
*/
- EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
+ private EventuallyConsistentMap<DestinationSetNextObjectiveStoreKey, NextNeighbors>
dsNextObjStore = null;
/**
* Per device next objective ID store with (device id + vlanid) as key.
* Used to keep track on L2 flood group information.
*/
- EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
+ private EventuallyConsistentMap<VlanNextObjectiveStoreKey, Integer>
vlanNextObjStore = null;
/**
* Per device next objective ID store with (device id + port + treatment + meta) as key.
* Used to keep track on L2 interface group and L3 unicast group information.
*/
- EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
+ private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
portNextObjStore = null;
// Local store for all links seen and their present status, used for
@@ -323,7 +337,7 @@
public static final VlanId INTERNAL_VLAN = VlanId.vlanId((short) 4094);
@Activate
- protected void activate() {
+ protected void activate(ComponentContext context) {
appId = coreService.registerApplication(APP_NAME);
log.debug("Creating EC map nsnextobjectivestore");
@@ -392,6 +406,8 @@
"staleLinkAge", "15000");
compCfgService.preSetProperty("org.onosproject.net.host.impl.HostManager",
"allowDuplicateIps", "false");
+ compCfgService.registerProperties(getClass());
+ modified(context);
processor = new InternalPacketProcessor();
linkListener = new InternalLinkListener();
@@ -449,6 +465,7 @@
cfgService.unregisterConfigFactory(xConnectConfigFactory);
cfgService.unregisterConfigFactory(mcastConfigFactory);
cfgService.unregisterConfigFactory(pwaasConfigFactory);
+ compCfgService.unregisterProperties(getClass(), false);
hostService.removeListener(hostListener);
packetService.removeProcessor(processor);
@@ -472,6 +489,22 @@
log.info("Stopped");
}
+ @Modified
+ private void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ if (properties == null) {
+ return;
+ }
+
+ String strActiveProving = Tools.get(properties, "activeProbing");
+ boolean expectActiveProbing = Boolean.parseBoolean(strActiveProving);
+
+ if (expectActiveProbing != activeProbing) {
+ activeProbing = expectActiveProbing;
+ log.info("{} active probing", activeProbing ? "Enabling" : "Disabling");
+ }
+ }
+
@Override
public List<Tunnel> getTunnels() {
return tunnelHandler.getTunnels();
@@ -922,7 +955,7 @@
* true if the seen-link is up;
* false if the seen-link is down
*/
- Boolean isSeenLinkUp(Link link) {
+ private Boolean isSeenLinkUp(Link link) {
return seenLinks.get(link);
}
@@ -970,7 +1003,7 @@
* @return true if another unidirectional link exists in the reverse direction,
* has been seen-before and is up
*/
- public boolean isBidirectional(Link link) {
+ boolean isBidirectional(Link link) {
Link reverseLink = linkService.getLink(link.dst(), link.src());
if (reverseLink == null) {
return false;
@@ -989,7 +1022,7 @@
* @param link the infrastructure link being queried
* @return true if link should be avoided
*/
- public boolean avoidLink(Link link) {
+ boolean avoidLink(Link link) {
// XXX currently only avoids all pair-links. In the future can be
// extended to avoid any generic link
DeviceId src = link.src().deviceId();
@@ -1012,12 +1045,9 @@
return false;
}
- if (srcPort.equals(pairLocalPort) &&
+ return srcPort.equals(pairLocalPort) &&
link.dst().deviceId().equals(pairDev) &&
- link.dst().port().equals(pairRemotePort)) {
- return true;
- }
- return false;
+ link.dst().port().equals(pairRemotePort);
}
private class InternalPacketProcessor implements PacketProcessor {
@@ -1374,9 +1404,7 @@
private void processDeviceRemoved(Device device) {
dsNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
- .forEach(entry -> {
- dsNextObjStore.remove(entry.getKey());
- });
+ .forEach(entry -> dsNextObjStore.remove(entry.getKey()));
vlanNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
.forEach(entry -> vlanNextObjStore.remove(entry.getKey()));
@@ -1456,6 +1484,7 @@
if (portUp) {
log.info("Device:EdgePort {}:{} is enabled in vlan: {}", device.id(),
port.number(), vlanId);
+ hostHandler.processPortUp(new ConnectPoint(device.id(), port.number()));
} else {
log.info("Device:EdgePort {}:{} is disabled in vlan: {}", device.id(),
port.number(), vlanId);
@@ -1509,7 +1538,7 @@
/**
* Reads network config and initializes related data structure accordingly.
*/
- public void configureNetwork() {
+ void configureNetwork() {
createOrUpdateDeviceConfiguration();
arpHandler = new ArpHandler(srManager);