sdn
Committed by Gerrit Code Review

Fix for ONOS-5034

Change-Id: I61158511680851be375b93c365fc32c0573e9edc
...@@ -12,6 +12,7 @@ TEST_DEPS = [ ...@@ -12,6 +12,7 @@ TEST_DEPS = [
12 '//core/common:onos-core-common', 12 '//core/common:onos-core-common',
13 '//core/store/dist:onos-core-dist', 13 '//core/store/dist:onos-core-dist',
14 '//core/store/dist:onos-core-dist-tests', 14 '//core/store/dist:onos-core-dist-tests',
15 + '//utils/osgi:onlab-osgi-tests',
15 ] 16 ]
16 17
17 osgi_jar_with_tests ( 18 osgi_jar_with_tests (
......
...@@ -125,6 +125,13 @@ ...@@ -125,6 +125,13 @@
125 <groupId>org.onosproject</groupId> 125 <groupId>org.onosproject</groupId>
126 <artifactId>onos-incubator-net</artifactId> 126 <artifactId>onos-incubator-net</artifactId>
127 </dependency> 127 </dependency>
128 + <dependency>
129 + <groupId>org.onosproject</groupId>
130 + <artifactId>onlab-osgi</artifactId>
131 + <version>${project.version}</version>
132 + <classifier>tests</classifier>
133 + <scope>test</scope>
134 + </dependency>
128 </dependencies> 135 </dependencies>
129 136
130 </project> 137 </project>
......
...@@ -106,6 +106,15 @@ public class HostManager ...@@ -106,6 +106,15 @@ public class HostManager
106 label = "Enable removal of duplicate ip address") 106 label = "Enable removal of duplicate ip address")
107 107
108 private boolean allowDuplicateIps = true; 108 private boolean allowDuplicateIps = true;
109 +
110 + @Property(name = "monitorHosts", boolValue = false,
111 + label = "Enable/Disable monitoring of hosts")
112 + private boolean monitorHosts = false;
113 +
114 + @Property(name = "probeRate", longValue = 30000,
115 + label = "Set the probe Rate in milli seconds")
116 + private long probeRate = 30000;
117 +
109 private HostMonitor monitor; 118 private HostMonitor monitor;
110 119
111 120
...@@ -114,17 +123,71 @@ public class HostManager ...@@ -114,17 +123,71 @@ public class HostManager
114 store.setDelegate(delegate); 123 store.setDelegate(delegate);
115 eventDispatcher.addSink(HostEvent.class, listenerRegistry); 124 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
116 cfgService.registerProperties(getClass()); 125 cfgService.registerProperties(getClass());
117 - modified(context);
118 networkConfigService.addListener(networkConfigListener); 126 networkConfigService.addListener(networkConfigListener);
119 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService); 127 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
128 + monitor.setProbeRate(probeRate);
120 monitor.start(); 129 monitor.start();
130 + modified(context);
131 + cfgService.registerProperties(getClass());
121 log.info("Started"); 132 log.info("Started");
122 } 133 }
123 134
135 + @Deactivate
136 + public void deactivate() {
137 + store.unsetDelegate(delegate);
138 + eventDispatcher.removeSink(HostEvent.class);
139 + networkConfigService.removeListener(networkConfigListener);
140 + cfgService.unregisterProperties(getClass(), false);
141 + monitor.shutdown();
142 + log.info("Stopped");
143 + }
144 +
124 @Modified 145 @Modified
125 - public void modified(ComponentContext context) { 146 + public void modified(ComponentContext context) {
147 + boolean oldValue = monitorHosts;
148 + readComponentConfiguration(context);
149 + if (probeRate > 0) {
150 + monitor.setProbeRate(probeRate);
151 + } else {
152 + log.warn("probeRate cannot be lessthan 0");
153 + }
154 +
155 + if (oldValue != monitorHosts) {
156 + if (monitorHosts) {
157 + startMonitoring();
158 + } else {
159 + stopMonitoring();
160 + }
161 + }
162 + }
163 +
164 + /**
165 + * Extracts properties from the component configuration context.
166 + *
167 + * @param context the component context
168 + */
169 + private void readComponentConfiguration(ComponentContext context) {
126 Dictionary<?, ?> properties = context.getProperties(); 170 Dictionary<?, ?> properties = context.getProperties();
127 Boolean flag; 171 Boolean flag;
172 +
173 + flag = Tools.isPropertyEnabled(properties, "monitorHosts");
174 + if (flag == null) {
175 + log.info("monitorHosts is not enabled " +
176 + "using current value of {}", monitorHosts);
177 + } else {
178 + monitorHosts = flag;
179 + log.info("Configured. monitorHosts {}",
180 + monitorHosts ? "enabled" : "disabled");
181 + }
182 +
183 + Long longValue = Tools.getLongProperty(properties, "probeRate");
184 + if (longValue == null || longValue == 0) {
185 + log.info("probeRate is not set sing default value of {}", probeRate);
186 + } else {
187 + probeRate = longValue;
188 + log.info("Configured. probeRate {}", probeRate);
189 + }
190 +
128 flag = Tools.isPropertyEnabled(properties, "allowDuplicateIps"); 191 flag = Tools.isPropertyEnabled(properties, "allowDuplicateIps");
129 if (flag == null) { 192 if (flag == null) {
130 log.info("Removal of duplicate ip address is not configured"); 193 log.info("Removal of duplicate ip address is not configured");
...@@ -133,14 +196,31 @@ public class HostManager ...@@ -133,14 +196,31 @@ public class HostManager
133 log.info("Removal of duplicate ip address is {}", 196 log.info("Removal of duplicate ip address is {}",
134 allowDuplicateIps ? "disabled" : "enabled"); 197 allowDuplicateIps ? "disabled" : "enabled");
135 } 198 }
199 +
136 } 200 }
137 201
138 - @Deactivate 202 + /**
139 - public void deactivate() { 203 + * Starts monitoring the hosts by IP Address.
140 - store.unsetDelegate(delegate); 204 + *
141 - eventDispatcher.removeSink(HostEvent.class); 205 + */
142 - networkConfigService.removeListener(networkConfigListener); 206 + private void startMonitoring() {
143 - log.info("Stopped"); 207 + store.getHosts().forEach(host -> {
208 + host.ipAddresses().forEach(ip -> {
209 + monitor.addMonitoringFor(ip);
210 + });
211 + });
212 + }
213 +
214 + /**
215 + * Stops monitoring the hosts by IP Address.
216 + *
217 + */
218 + private void stopMonitoring() {
219 + store.getHosts().forEach(host -> {
220 + host.ipAddresses().forEach(ip -> {
221 + monitor.stopMonitoring(ip);
222 + });
223 + });
144 } 224 }
145 225
146 @Override 226 @Override
...@@ -244,6 +324,12 @@ public class HostManager ...@@ -244,6 +324,12 @@ public class HostManager
244 } 324 }
245 store.createOrUpdateHost(provider().id(), hostId, 325 store.createOrUpdateHost(provider().id(), hostId,
246 hostDescription, replaceIps); 326 hostDescription, replaceIps);
327 +
328 + if (monitorHosts) {
329 + hostDescription.ipAddress().forEach(ip -> {
330 + monitor.addMonitoringFor(ip);
331 + });
332 + }
247 } 333 }
248 334
249 // When a new IP is detected, remove that IP on other hosts if it exists 335 // When a new IP is detected, remove that IP on other hosts if it exists
...@@ -276,6 +362,12 @@ public class HostManager ...@@ -276,6 +362,12 @@ public class HostManager
276 public void hostVanished(HostId hostId) { 362 public void hostVanished(HostId hostId) {
277 checkNotNull(hostId, HOST_ID_NULL); 363 checkNotNull(hostId, HOST_ID_NULL);
278 checkValidity(); 364 checkValidity();
365 + Host host = store.getHost(hostId);
366 + if (monitorHosts) {
367 + host.ipAddresses().forEach(ip -> {
368 + monitor.stopMonitoring(ip);
369 + });
370 + }
279 store.removeHost(hostId); 371 store.removeHost(hostId);
280 } 372 }
281 373
......
...@@ -140,6 +140,13 @@ public class HostMonitor implements TimerTask { ...@@ -140,6 +140,13 @@ public class HostMonitor implements TimerTask {
140 } 140 }
141 } 141 }
142 142
143 + /*
144 + * Sets the probe rate.
145 + */
146 + void setProbeRate(long probeRate) {
147 + this.probeRate = probeRate;
148 + }
149 +
143 /** 150 /**
144 * Registers a host provider with the host monitor. The monitor can use the 151 * Registers a host provider with the host monitor. The monitor can use the
145 * provider to probe hosts. 152 * provider to probe hosts.
......
...@@ -91,6 +91,17 @@ public class HostManagerTest { ...@@ -91,6 +91,17 @@ public class HostManagerTest {
91 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); 91 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
92 private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L); 92 private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L);
93 93
94 + public static final ComponentContextAdapter REMOVE_DUPS_MONITOR = new ComponentContextAdapter() {
95 + @Override
96 + public Dictionary getProperties() {
97 + Hashtable<String, String> props = new Hashtable<String, String>();
98 + props.put("allowDuplicateIps", "true");
99 + props.put("monitorHosts", "true");
100 + props.put("probeRate", "40000");
101 + return props;
102 + }
103 + };
104 +
94 private HostManager mgr; 105 private HostManager mgr;
95 106
96 protected TestListener listener = new TestListener(); 107 protected TestListener listener = new TestListener();
...@@ -98,16 +109,6 @@ public class HostManagerTest { ...@@ -98,16 +109,6 @@ public class HostManagerTest {
98 protected TestHostProvider provider; 109 protected TestHostProvider provider;
99 protected HostProviderService providerService; 110 protected HostProviderService providerService;
100 111
101 - private static final ComponentContextAdapter REMOVE_DUPS =
102 - new ComponentContextAdapter() {
103 - @Override
104 - public Dictionary getProperties() {
105 - Hashtable<String, String> props = new Hashtable<>();
106 - props.put("allowDuplicateIps", "true");
107 - return props;
108 - }
109 - };
110 -
111 @Before 112 @Before
112 public void setUp() { 113 public void setUp() {
113 mgr = new HostManager(); 114 mgr = new HostManager();
...@@ -116,7 +117,9 @@ public class HostManagerTest { ...@@ -116,7 +117,9 @@ public class HostManagerTest {
116 registry = mgr; 117 registry = mgr;
117 mgr.networkConfigService = new TestNetworkConfigService(); 118 mgr.networkConfigService = new TestNetworkConfigService();
118 mgr.cfgService = new ComponentConfigAdapter(); 119 mgr.cfgService = new ComponentConfigAdapter();
119 - mgr.activate(REMOVE_DUPS); 120 +
121 + mgr.activate(REMOVE_DUPS_MONITOR);
122 +
120 mgr.addListener(listener); 123 mgr.addListener(listener);
121 124
122 provider = new TestHostProvider(); 125 provider = new TestHostProvider();
......
...@@ -44,17 +44,22 @@ import org.onosproject.net.Device; ...@@ -44,17 +44,22 @@ import org.onosproject.net.Device;
44 import org.onosproject.net.Host; 44 import org.onosproject.net.Host;
45 import org.onosproject.net.HostId; 45 import org.onosproject.net.HostId;
46 import org.onosproject.net.HostLocation; 46 import org.onosproject.net.HostLocation;
47 +import org.onosproject.net.MastershipRole;
47 import org.onosproject.net.device.DeviceEvent; 48 import org.onosproject.net.device.DeviceEvent;
48 import org.onosproject.net.device.DeviceListener; 49 import org.onosproject.net.device.DeviceListener;
49 import org.onosproject.net.device.DeviceService; 50 import org.onosproject.net.device.DeviceService;
50 import org.onosproject.net.flow.DefaultTrafficSelector; 51 import org.onosproject.net.flow.DefaultTrafficSelector;
52 +import org.onosproject.net.flow.DefaultTrafficTreatment;
51 import org.onosproject.net.flow.TrafficSelector; 53 import org.onosproject.net.flow.TrafficSelector;
54 +import org.onosproject.net.flow.TrafficTreatment;
52 import org.onosproject.net.host.DefaultHostDescription; 55 import org.onosproject.net.host.DefaultHostDescription;
53 import org.onosproject.net.host.HostDescription; 56 import org.onosproject.net.host.HostDescription;
54 import org.onosproject.net.host.HostProvider; 57 import org.onosproject.net.host.HostProvider;
55 import org.onosproject.net.host.HostProviderRegistry; 58 import org.onosproject.net.host.HostProviderRegistry;
56 import org.onosproject.net.host.HostProviderService; 59 import org.onosproject.net.host.HostProviderService;
57 import org.onosproject.net.host.HostService; 60 import org.onosproject.net.host.HostService;
61 +import org.onosproject.net.packet.DefaultOutboundPacket;
62 +import org.onosproject.net.packet.OutboundPacket;
58 import org.onosproject.net.packet.PacketContext; 63 import org.onosproject.net.packet.PacketContext;
59 import org.onosproject.net.packet.PacketPriority; 64 import org.onosproject.net.packet.PacketPriority;
60 import org.onosproject.net.packet.PacketProcessor; 65 import org.onosproject.net.packet.PacketProcessor;
...@@ -66,6 +71,7 @@ import org.onosproject.net.topology.TopologyService; ...@@ -66,6 +71,7 @@ import org.onosproject.net.topology.TopologyService;
66 import org.osgi.service.component.ComponentContext; 71 import org.osgi.service.component.ComponentContext;
67 import org.slf4j.Logger; 72 import org.slf4j.Logger;
68 73
74 +import java.nio.ByteBuffer;
69 import java.util.Dictionary; 75 import java.util.Dictionary;
70 import java.util.Set; 76 import java.util.Set;
71 import java.util.concurrent.ExecutorService; 77 import java.util.concurrent.ExecutorService;
...@@ -126,6 +132,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -126,6 +132,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
126 132
127 protected ExecutorService eventHandler; 133 protected ExecutorService eventHandler;
128 134
135 + private static final byte[] SENDER_ADDRESS = IpAddress.valueOf("0.0.0.0").toOctets();
136 +
129 /** 137 /**
130 * Creates an OpenFlow host provider. 138 * Creates an OpenFlow host provider.
131 */ 139 */
...@@ -261,7 +269,60 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -261,7 +269,60 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
261 269
262 @Override 270 @Override
263 public void triggerProbe(Host host) { 271 public void triggerProbe(Host host) {
264 - log.info("Triggering probe on device {}", host); 272 + log.info("Triggering probe on device {} ", host);
273 + MastershipRole role = deviceService.getRole(host.location().deviceId());
274 + if (role.equals(MastershipRole.MASTER)) {
275 + host.ipAddresses().forEach(ip -> {
276 + sendProbe(host, ip);
277 + });
278 + } else {
279 + log.info("not the master, master will probe {}");
280 + }
281 + }
282 +
283 + private void sendProbe(Host host, IpAddress targetIp) {
284 + Ethernet probePacket = null;
285 + if (targetIp.isIp4()) {
286 + // IPv4: Use ARP
287 + probePacket = buildArpRequest(targetIp, host);
288 + } else {
289 + // IPv6: Use Neighbor Discovery
290 + //FIX ME need to implement ndp probe
291 + log.info("Triggering probe on device {} ", host);
292 + }
293 +
294 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(host.location().port()).build();
295 +
296 + OutboundPacket outboundPacket = new DefaultOutboundPacket(host.location().deviceId(), treatment,
297 + ByteBuffer.wrap(probePacket.serialize()));
298 +
299 + packetService.emit(outboundPacket);
300 + }
301 +
302 + /*
303 + * This method is using source ip as 0.0.0.0 , to receive the reply even from the sub net hosts.
304 + */
305 + private Ethernet buildArpRequest(IpAddress targetIp, Host host) {
306 +
307 + ARP arp = new ARP();
308 + arp.setHardwareType(ARP.HW_TYPE_ETHERNET)
309 + .setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH)
310 + .setProtocolType(ARP.PROTO_TYPE_IP)
311 + .setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH)
312 + .setOpCode(ARP.OP_REQUEST);
313 +
314 + arp.setSenderHardwareAddress(MacAddress.BROADCAST.toBytes())
315 + .setSenderProtocolAddress(SENDER_ADDRESS)
316 + .setTargetHardwareAddress(MacAddress.BROADCAST.toBytes())
317 + .setTargetProtocolAddress(targetIp.toOctets());
318 +
319 + Ethernet ethernet = new Ethernet();
320 + ethernet.setEtherType(Ethernet.TYPE_ARP)
321 + .setDestinationMACAddress(MacAddress.BROADCAST)
322 + .setSourceMACAddress(MacAddress.BROADCAST).setPayload(arp);
323 +
324 + ethernet.setPad(true);
325 + return ethernet;
265 } 326 }
266 327
267 private class InternalHostProvider implements PacketProcessor { 328 private class InternalHostProvider implements PacketProcessor {
......
...@@ -364,6 +364,26 @@ public abstract class Tools { ...@@ -364,6 +364,26 @@ public abstract class Tools {
364 } 364 }
365 365
366 /** 366 /**
367 + * Get Long property from the propertyName
368 + * Return null if propertyName is not found.
369 + *
370 + * @param properties properties to be looked up
371 + * @param propertyName the name of the property to look up
372 + * @return value when the propertyName is defined or return null
373 + */
374 + public static Long getLongProperty(Dictionary<?, ?> properties,
375 + String propertyName) {
376 + Long value;
377 + try {
378 + String s = get(properties, propertyName);
379 + value = Strings.isNullOrEmpty(s) ? null : Long.valueOf(s);
380 + } catch (NumberFormatException | ClassCastException e) {
381 + value = null;
382 + }
383 + return value;
384 + }
385 +
386 + /**
367 * Returns a function that retries execution on failure. 387 * Returns a function that retries execution on failure.
368 * @param base base function 388 * @param base base function
369 * @param exceptionClass type of exception for which to retry 389 * @param exceptionClass type of exception for which to retry
......