Fix for ONOS-5034
Change-Id: I61158511680851be375b93c365fc32c0573e9edc
diff --git a/core/net/BUCK b/core/net/BUCK
index 73bbe7d..773b20a 100644
--- a/core/net/BUCK
+++ b/core/net/BUCK
@@ -12,6 +12,7 @@
'//core/common:onos-core-common',
'//core/store/dist:onos-core-dist',
'//core/store/dist:onos-core-dist-tests',
+ '//utils/osgi:onlab-osgi-tests',
]
osgi_jar_with_tests (
diff --git a/core/net/pom.xml b/core/net/pom.xml
index d30f7a6..57a39e8 100644
--- a/core/net/pom.xml
+++ b/core/net/pom.xml
@@ -125,6 +125,13 @@
<groupId>org.onosproject</groupId>
<artifactId>onos-incubator-net</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
index bdb5e43..a18d4ad 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
@@ -106,6 +106,15 @@
label = "Enable removal of duplicate ip address")
private boolean allowDuplicateIps = true;
+
+ @Property(name = "monitorHosts", boolValue = false,
+ label = "Enable/Disable monitoring of hosts")
+ private boolean monitorHosts = false;
+
+ @Property(name = "probeRate", longValue = 30000,
+ label = "Set the probe Rate in milli seconds")
+ private long probeRate = 30000;
+
private HostMonitor monitor;
@@ -114,17 +123,71 @@
store.setDelegate(delegate);
eventDispatcher.addSink(HostEvent.class, listenerRegistry);
cfgService.registerProperties(getClass());
- modified(context);
networkConfigService.addListener(networkConfigListener);
monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
+ monitor.setProbeRate(probeRate);
monitor.start();
+ modified(context);
+ cfgService.registerProperties(getClass());
log.info("Started");
}
+ @Deactivate
+ public void deactivate() {
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(HostEvent.class);
+ networkConfigService.removeListener(networkConfigListener);
+ cfgService.unregisterProperties(getClass(), false);
+ monitor.shutdown();
+ log.info("Stopped");
+ }
+
@Modified
- public void modified(ComponentContext context) {
+ public void modified(ComponentContext context) {
+ boolean oldValue = monitorHosts;
+ readComponentConfiguration(context);
+ if (probeRate > 0) {
+ monitor.setProbeRate(probeRate);
+ } else {
+ log.warn("probeRate cannot be lessthan 0");
+ }
+
+ if (oldValue != monitorHosts) {
+ if (monitorHosts) {
+ startMonitoring();
+ } else {
+ stopMonitoring();
+ }
+ }
+ }
+
+ /**
+ * Extracts properties from the component configuration context.
+ *
+ * @param context the component context
+ */
+ private void readComponentConfiguration(ComponentContext context) {
Dictionary<?, ?> properties = context.getProperties();
Boolean flag;
+
+ flag = Tools.isPropertyEnabled(properties, "monitorHosts");
+ if (flag == null) {
+ log.info("monitorHosts is not enabled " +
+ "using current value of {}", monitorHosts);
+ } else {
+ monitorHosts = flag;
+ log.info("Configured. monitorHosts {}",
+ monitorHosts ? "enabled" : "disabled");
+ }
+
+ Long longValue = Tools.getLongProperty(properties, "probeRate");
+ if (longValue == null || longValue == 0) {
+ log.info("probeRate is not set sing default value of {}", probeRate);
+ } else {
+ probeRate = longValue;
+ log.info("Configured. probeRate {}", probeRate);
+ }
+
flag = Tools.isPropertyEnabled(properties, "allowDuplicateIps");
if (flag == null) {
log.info("Removal of duplicate ip address is not configured");
@@ -133,14 +196,31 @@
log.info("Removal of duplicate ip address is {}",
allowDuplicateIps ? "disabled" : "enabled");
}
+
}
- @Deactivate
- public void deactivate() {
- store.unsetDelegate(delegate);
- eventDispatcher.removeSink(HostEvent.class);
- networkConfigService.removeListener(networkConfigListener);
- log.info("Stopped");
+ /**
+ * Starts monitoring the hosts by IP Address.
+ *
+ */
+ private void startMonitoring() {
+ store.getHosts().forEach(host -> {
+ host.ipAddresses().forEach(ip -> {
+ monitor.addMonitoringFor(ip);
+ });
+ });
+ }
+
+ /**
+ * Stops monitoring the hosts by IP Address.
+ *
+ */
+ private void stopMonitoring() {
+ store.getHosts().forEach(host -> {
+ host.ipAddresses().forEach(ip -> {
+ monitor.stopMonitoring(ip);
+ });
+ });
}
@Override
@@ -244,6 +324,12 @@
}
store.createOrUpdateHost(provider().id(), hostId,
hostDescription, replaceIps);
+
+ if (monitorHosts) {
+ hostDescription.ipAddress().forEach(ip -> {
+ monitor.addMonitoringFor(ip);
+ });
+ }
}
// When a new IP is detected, remove that IP on other hosts if it exists
@@ -276,6 +362,12 @@
public void hostVanished(HostId hostId) {
checkNotNull(hostId, HOST_ID_NULL);
checkValidity();
+ Host host = store.getHost(hostId);
+ if (monitorHosts) {
+ host.ipAddresses().forEach(ip -> {
+ monitor.stopMonitoring(ip);
+ });
+ }
store.removeHost(hostId);
}
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
index c2bac09..9206176 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
@@ -140,6 +140,13 @@
}
}
+ /*
+ * Sets the probe rate.
+ */
+ void setProbeRate(long probeRate) {
+ this.probeRate = probeRate;
+ }
+
/**
* Registers a host provider with the host monitor. The monitor can use the
* provider to probe hosts.
diff --git a/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java b/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java
index 1eb014f..6a71f43 100644
--- a/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/host/impl/HostManagerTest.java
@@ -91,6 +91,17 @@
private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L);
+ public static final ComponentContextAdapter REMOVE_DUPS_MONITOR = new ComponentContextAdapter() {
+ @Override
+ public Dictionary getProperties() {
+ Hashtable<String, String> props = new Hashtable<String, String>();
+ props.put("allowDuplicateIps", "true");
+ props.put("monitorHosts", "true");
+ props.put("probeRate", "40000");
+ return props;
+ }
+ };
+
private HostManager mgr;
protected TestListener listener = new TestListener();
@@ -98,16 +109,6 @@
protected TestHostProvider provider;
protected HostProviderService providerService;
- private static final ComponentContextAdapter REMOVE_DUPS =
- new ComponentContextAdapter() {
- @Override
- public Dictionary getProperties() {
- Hashtable<String, String> props = new Hashtable<>();
- props.put("allowDuplicateIps", "true");
- return props;
- }
- };
-
@Before
public void setUp() {
mgr = new HostManager();
@@ -116,7 +117,9 @@
registry = mgr;
mgr.networkConfigService = new TestNetworkConfigService();
mgr.cfgService = new ComponentConfigAdapter();
- mgr.activate(REMOVE_DUPS);
+
+ mgr.activate(REMOVE_DUPS_MONITOR);
+
mgr.addListener(listener);
provider = new TestHostProvider();
diff --git a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
index 46b7d88..daf7134 100644
--- a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
+++ b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
@@ -44,17 +44,22 @@
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
+import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostDescription;
import org.onosproject.net.host.HostProvider;
import org.onosproject.net.host.HostProviderRegistry;
import org.onosproject.net.host.HostProviderService;
import org.onosproject.net.host.HostService;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
@@ -66,6 +71,7 @@
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
+import java.nio.ByteBuffer;
import java.util.Dictionary;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -126,6 +132,8 @@
protected ExecutorService eventHandler;
+ private static final byte[] SENDER_ADDRESS = IpAddress.valueOf("0.0.0.0").toOctets();
+
/**
* Creates an OpenFlow host provider.
*/
@@ -261,7 +269,60 @@
@Override
public void triggerProbe(Host host) {
- log.info("Triggering probe on device {}", host);
+ log.info("Triggering probe on device {} ", host);
+ MastershipRole role = deviceService.getRole(host.location().deviceId());
+ if (role.equals(MastershipRole.MASTER)) {
+ host.ipAddresses().forEach(ip -> {
+ sendProbe(host, ip);
+ });
+ } else {
+ log.info("not the master, master will probe {}");
+ }
+ }
+
+ private void sendProbe(Host host, IpAddress targetIp) {
+ Ethernet probePacket = null;
+ if (targetIp.isIp4()) {
+ // IPv4: Use ARP
+ probePacket = buildArpRequest(targetIp, host);
+ } else {
+ // IPv6: Use Neighbor Discovery
+ //FIX ME need to implement ndp probe
+ log.info("Triggering probe on device {} ", host);
+ }
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(host.location().port()).build();
+
+ OutboundPacket outboundPacket = new DefaultOutboundPacket(host.location().deviceId(), treatment,
+ ByteBuffer.wrap(probePacket.serialize()));
+
+ packetService.emit(outboundPacket);
+ }
+
+ /*
+ * This method is using source ip as 0.0.0.0 , to receive the reply even from the sub net hosts.
+ */
+ private Ethernet buildArpRequest(IpAddress targetIp, Host host) {
+
+ ARP arp = new ARP();
+ arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
+ .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
+ .setProtocolType(ARP.PROTO_TYPE_IP)
+ .setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH)
+ .setOpCode(ARP.OP_REQUEST);
+
+ arp.setSenderHardwareAddress(MacAddress.BROADCAST.toBytes())
+ .setSenderProtocolAddress(SENDER_ADDRESS)
+ .setTargetHardwareAddress(MacAddress.BROADCAST.toBytes())
+ .setTargetProtocolAddress(targetIp.toOctets());
+
+ Ethernet ethernet = new Ethernet();
+ ethernet.setEtherType(Ethernet.TYPE_ARP)
+ .setDestinationMACAddress(MacAddress.BROADCAST)
+ .setSourceMACAddress(MacAddress.BROADCAST).setPayload(arp);
+
+ ethernet.setPad(true);
+ return ethernet;
}
private class InternalHostProvider implements PacketProcessor {
diff --git a/utils/misc/src/main/java/org/onlab/util/Tools.java b/utils/misc/src/main/java/org/onlab/util/Tools.java
index 60a80c1..25c0213 100644
--- a/utils/misc/src/main/java/org/onlab/util/Tools.java
+++ b/utils/misc/src/main/java/org/onlab/util/Tools.java
@@ -364,6 +364,26 @@
}
/**
+ * Get Long property from the propertyName
+ * Return null if propertyName is not found.
+ *
+ * @param properties properties to be looked up
+ * @param propertyName the name of the property to look up
+ * @return value when the propertyName is defined or return null
+ */
+ public static Long getLongProperty(Dictionary<?, ?> properties,
+ String propertyName) {
+ Long value;
+ try {
+ String s = get(properties, propertyName);
+ value = Strings.isNullOrEmpty(s) ? null : Long.valueOf(s);
+ } catch (NumberFormatException | ClassCastException e) {
+ value = null;
+ }
+ return value;
+ }
+
+ /**
* Returns a function that retries execution on failure.
* @param base base function
* @param exceptionClass type of exception for which to retry