sdn
Committed by Gerrit Code Review

Fix for ONOS-5034

Change-Id: I61158511680851be375b93c365fc32c0573e9edc
...@@ -8,6 +8,7 @@ TEST_DEPS = [ ...@@ -8,6 +8,7 @@ TEST_DEPS = [
8 '//core/common:onos-core-common', 8 '//core/common:onos-core-common',
9 '//core/store/dist:onos-core-dist', 9 '//core/store/dist:onos-core-dist',
10 '//core/store/dist:onos-core-dist-tests', 10 '//core/store/dist:onos-core-dist-tests',
11 + '//utils/osgi:onlab-osgi-tests',
11 ] 12 ]
12 13
13 osgi_jar_with_tests ( 14 osgi_jar_with_tests (
...@@ -15,4 +16,4 @@ osgi_jar_with_tests ( ...@@ -15,4 +16,4 @@ osgi_jar_with_tests (
15 deps = COMPILE_DEPS, 16 deps = COMPILE_DEPS,
16 test_deps = TEST_DEPS, 17 test_deps = TEST_DEPS,
17 visibility = ['PUBLIC'], 18 visibility = ['PUBLIC'],
18 -)
...\ No newline at end of file ...\ No newline at end of file
19 +)
......
...@@ -110,6 +110,13 @@ ...@@ -110,6 +110,13 @@
110 <groupId>org.apache.felix</groupId> 110 <groupId>org.apache.felix</groupId>
111 <artifactId>org.apache.felix.scr</artifactId> 111 <artifactId>org.apache.felix.scr</artifactId>
112 </dependency> 112 </dependency>
113 + <dependency>
114 + <groupId>org.onosproject</groupId>
115 + <artifactId>onlab-osgi</artifactId>
116 + <version>${project.version}</version>
117 + <classifier>tests</classifier>
118 + <scope>test</scope>
119 + </dependency>
113 </dependencies> 120 </dependencies>
114 121
115 </project> 122 </project>
......
...@@ -18,12 +18,16 @@ package org.onosproject.net.host.impl; ...@@ -18,12 +18,16 @@ package org.onosproject.net.host.impl;
18 import org.apache.felix.scr.annotations.Activate; 18 import org.apache.felix.scr.annotations.Activate;
19 import org.apache.felix.scr.annotations.Component; 19 import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Deactivate; 20 import org.apache.felix.scr.annotations.Deactivate;
21 +import org.apache.felix.scr.annotations.Modified;
22 +import org.apache.felix.scr.annotations.Property;
21 import org.apache.felix.scr.annotations.Reference; 23 import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 24 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.apache.felix.scr.annotations.Service; 25 import org.apache.felix.scr.annotations.Service;
24 import org.onlab.packet.IpAddress; 26 import org.onlab.packet.IpAddress;
25 import org.onlab.packet.MacAddress; 27 import org.onlab.packet.MacAddress;
26 import org.onlab.packet.VlanId; 28 import org.onlab.packet.VlanId;
29 +import org.onlab.util.Tools;
30 +import org.onosproject.cfg.ComponentConfigService;
27 import org.onosproject.incubator.net.intf.InterfaceService; 31 import org.onosproject.incubator.net.intf.InterfaceService;
28 import org.onosproject.net.edge.EdgePortService; 32 import org.onosproject.net.edge.EdgePortService;
29 import org.onosproject.net.provider.AbstractListenerProviderRegistry; 33 import org.onosproject.net.provider.AbstractListenerProviderRegistry;
...@@ -48,8 +52,10 @@ import org.onosproject.net.host.HostStore; ...@@ -48,8 +52,10 @@ import org.onosproject.net.host.HostStore;
48 import org.onosproject.net.host.HostStoreDelegate; 52 import org.onosproject.net.host.HostStoreDelegate;
49 import org.onosproject.net.packet.PacketService; 53 import org.onosproject.net.packet.PacketService;
50 import org.onosproject.net.provider.AbstractProviderService; 54 import org.onosproject.net.provider.AbstractProviderService;
55 +import org.osgi.service.component.ComponentContext;
51 import org.slf4j.Logger; 56 import org.slf4j.Logger;
52 57
58 +import java.util.Dictionary;
53 import java.util.Set; 59 import java.util.Set;
54 60
55 import static com.google.common.base.Preconditions.checkNotNull; 61 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -93,15 +99,29 @@ public class HostManager ...@@ -93,15 +99,29 @@ public class HostManager
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected EdgePortService edgePortService; 100 protected EdgePortService edgePortService;
95 101
102 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 + protected ComponentConfigService cfgService;
104 +
105 + @Property(name = "monitorHosts", boolValue = false,
106 + label = "Enable/Disable monitoring of hosts")
107 + private boolean monitorHosts = false;
108 +
109 + @Property(name = "probeRate", longValue = 30000,
110 + label = "Set the probe Rate in milli seconds")
111 + private long probeRate = 30000;
112 +
96 private HostMonitor monitor; 113 private HostMonitor monitor;
97 114
98 @Activate 115 @Activate
99 - public void activate() { 116 + public void activate(ComponentContext context) {
100 store.setDelegate(delegate); 117 store.setDelegate(delegate);
101 eventDispatcher.addSink(HostEvent.class, listenerRegistry); 118 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
102 networkConfigService.addListener(networkConfigListener); 119 networkConfigService.addListener(networkConfigListener);
103 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService); 120 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
121 + monitor.setProbeRate(probeRate);
104 monitor.start(); 122 monitor.start();
123 + modified(context);
124 + cfgService.registerProperties(getClass());
105 log.info("Started"); 125 log.info("Started");
106 } 126 }
107 127
...@@ -110,9 +130,82 @@ public class HostManager ...@@ -110,9 +130,82 @@ public class HostManager
110 store.unsetDelegate(delegate); 130 store.unsetDelegate(delegate);
111 eventDispatcher.removeSink(HostEvent.class); 131 eventDispatcher.removeSink(HostEvent.class);
112 networkConfigService.removeListener(networkConfigListener); 132 networkConfigService.removeListener(networkConfigListener);
133 + cfgService.unregisterProperties(getClass(), false);
134 + monitor.shutdown();
113 log.info("Stopped"); 135 log.info("Stopped");
114 } 136 }
115 137
138 + @Modified
139 + public void modified(ComponentContext context) {
140 + boolean oldValue = monitorHosts;
141 + readComponentConfiguration(context);
142 + if (probeRate > 0) {
143 + monitor.setProbeRate(probeRate);
144 + } else {
145 + log.warn("probeRate cannot be lessthan 0");
146 + }
147 + if (oldValue != monitorHosts) {
148 + if (monitorHosts) {
149 + startMonitoring();
150 + } else {
151 + stopMonitoring();
152 + }
153 + }
154 + }
155 +
156 + /**
157 + * Extracts properties from the component configuration context.
158 + *
159 + * @param context the component context
160 + */
161 + private void readComponentConfiguration(ComponentContext context) {
162 + Dictionary<?, ?> properties = context.getProperties();
163 + Boolean flag;
164 +
165 + flag = Tools.isPropertyEnabled(properties, "monitorHosts");
166 + if (flag == null) {
167 + log.info("monitorHosts is not enabled " +
168 + "using current value of {}", monitorHosts);
169 + } else {
170 + monitorHosts = flag;
171 + log.info("Configured. monitorHosts {}",
172 + monitorHosts ? "enabled" : "disabled");
173 + }
174 +
175 + Long longValue = Tools.getLongProperty(properties, "probeRate");
176 + if (longValue == null || longValue == 0) {
177 + log.info("probeRate is not set sing default value of {}", probeRate);
178 + } else {
179 + probeRate = longValue;
180 + log.info("Configured. probeRate {}", probeRate);
181 + }
182 +
183 + }
184 +
185 + /**
186 + * Starts monitoring the hosts by IP Address.
187 + *
188 + */
189 + private void startMonitoring() {
190 + store.getHosts().forEach(host -> {
191 + host.ipAddresses().forEach(ip -> {
192 + monitor.addMonitoringFor(ip);
193 + });
194 + });
195 + }
196 +
197 + /**
198 + * Stops monitoring the hosts by IP Address.
199 + *
200 + */
201 + private void stopMonitoring() {
202 + store.getHosts().forEach(host -> {
203 + host.ipAddresses().forEach(ip -> {
204 + monitor.stopMonitoring(ip);
205 + });
206 + });
207 + }
208 +
116 @Override 209 @Override
117 protected HostProviderService createProviderService(HostProvider provider) { 210 protected HostProviderService createProviderService(HostProvider provider) {
118 monitor.registerHostProvider(provider); 211 monitor.registerHostProvider(provider);
...@@ -211,6 +304,11 @@ public class HostManager ...@@ -211,6 +304,11 @@ public class HostManager
211 hostDescription = validateHost(hostDescription, hostId); 304 hostDescription = validateHost(hostDescription, hostId);
212 store.createOrUpdateHost(provider().id(), hostId, 305 store.createOrUpdateHost(provider().id(), hostId,
213 hostDescription, replaceIps); 306 hostDescription, replaceIps);
307 + if (monitorHosts) {
308 + hostDescription.ipAddress().forEach(ip -> {
309 + monitor.addMonitoringFor(ip);
310 + });
311 + }
214 } 312 }
215 313
216 // returns a HostDescription made from the union of the BasicHostConfig 314 // returns a HostDescription made from the union of the BasicHostConfig
...@@ -226,6 +324,12 @@ public class HostManager ...@@ -226,6 +324,12 @@ public class HostManager
226 public void hostVanished(HostId hostId) { 324 public void hostVanished(HostId hostId) {
227 checkNotNull(hostId, HOST_ID_NULL); 325 checkNotNull(hostId, HOST_ID_NULL);
228 checkValidity(); 326 checkValidity();
327 + Host host = store.getHost(hostId);
328 + if (monitorHosts) {
329 + host.ipAddresses().forEach(ip -> {
330 + monitor.stopMonitoring(ip);
331 + });
332 + }
229 store.removeHost(hostId); 333 store.removeHost(hostId);
230 } 334 }
231 335
......
...@@ -139,6 +139,13 @@ public class HostMonitor implements TimerTask { ...@@ -139,6 +139,13 @@ public class HostMonitor implements TimerTask {
139 } 139 }
140 } 140 }
141 141
142 + /*
143 + * Sets the probe rate.
144 + */
145 + void setProbeRate(long probeRate) {
146 + this.probeRate = probeRate;
147 + }
148 +
142 /** 149 /**
143 * Registers a host provider with the host monitor. The monitor can use the 150 * Registers a host provider with the host monitor. The monitor can use the
144 * provider to probe hosts. 151 * provider to probe hosts.
......
...@@ -21,9 +21,11 @@ import org.junit.After; ...@@ -21,9 +21,11 @@ import org.junit.After;
21 import org.junit.Before; 21 import org.junit.Before;
22 import org.junit.Test; 22 import org.junit.Test;
23 import org.onlab.junit.TestTools; 23 import org.onlab.junit.TestTools;
24 +import org.onlab.osgi.ComponentContextAdapter;
24 import org.onlab.packet.IpAddress; 25 import org.onlab.packet.IpAddress;
25 import org.onlab.packet.MacAddress; 26 import org.onlab.packet.MacAddress;
26 import org.onlab.packet.VlanId; 27 import org.onlab.packet.VlanId;
28 +import org.onosproject.cfg.ComponentConfigAdapter;
27 import org.onosproject.common.event.impl.TestEventDispatcher; 29 import org.onosproject.common.event.impl.TestEventDispatcher;
28 import org.onosproject.event.Event; 30 import org.onosproject.event.Event;
29 import org.onosproject.net.DeviceId; 31 import org.onosproject.net.DeviceId;
...@@ -43,6 +45,8 @@ import org.onosproject.net.provider.AbstractProvider; ...@@ -43,6 +45,8 @@ import org.onosproject.net.provider.AbstractProvider;
43 import org.onosproject.net.provider.ProviderId; 45 import org.onosproject.net.provider.ProviderId;
44 import org.onosproject.store.trivial.SimpleHostStore; 46 import org.onosproject.store.trivial.SimpleHostStore;
45 47
48 +import java.util.Dictionary;
49 +import java.util.Hashtable;
46 import java.util.List; 50 import java.util.List;
47 import java.util.Set; 51 import java.util.Set;
48 52
...@@ -87,6 +91,16 @@ public class HostManagerTest { ...@@ -87,6 +91,16 @@ public class HostManagerTest {
87 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); 91 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
88 private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L); 92 private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L);
89 93
94 + public static final ComponentContextAdapter CTX_FOR_MONITOR = new ComponentContextAdapter() {
95 + @Override
96 + public Dictionary getProperties() {
97 + Hashtable<String, String> props = new Hashtable<String, String>();
98 + props.put("monitorHosts", "true");
99 + props.put("probeRate", "40000");
100 + return props;
101 + }
102 + };
103 +
90 private HostManager mgr; 104 private HostManager mgr;
91 105
92 protected TestListener listener = new TestListener(); 106 protected TestListener listener = new TestListener();
...@@ -101,7 +115,8 @@ public class HostManagerTest { ...@@ -101,7 +115,8 @@ public class HostManagerTest {
101 injectEventDispatcher(mgr, new TestEventDispatcher()); 115 injectEventDispatcher(mgr, new TestEventDispatcher());
102 registry = mgr; 116 registry = mgr;
103 mgr.networkConfigService = new TestNetworkConfigService(); 117 mgr.networkConfigService = new TestNetworkConfigService();
104 - mgr.activate(); 118 + mgr.cfgService = new ComponentConfigAdapter();
119 + mgr.activate(CTX_FOR_MONITOR);
105 120
106 mgr.addListener(listener); 121 mgr.addListener(listener);
107 122
......
...@@ -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 {
......
...@@ -361,6 +361,26 @@ public abstract class Tools { ...@@ -361,6 +361,26 @@ public abstract class Tools {
361 } 361 }
362 362
363 /** 363 /**
364 + * Get Long property from the propertyName
365 + * Return null if propertyName is not found.
366 + *
367 + * @param properties properties to be looked up
368 + * @param propertyName the name of the property to look up
369 + * @return value when the propertyName is defined or return null
370 + */
371 + public static Long getLongProperty(Dictionary<?, ?> properties,
372 + String propertyName) {
373 + Long value;
374 + try {
375 + String s = get(properties, propertyName);
376 + value = Strings.isNullOrEmpty(s) ? null : Long.valueOf(s);
377 + } catch (NumberFormatException | ClassCastException e) {
378 + value = null;
379 + }
380 + return value;
381 + }
382 +
383 + /**
364 * Returns a function that retries execution on failure. 384 * Returns a function that retries execution on failure.
365 * @param base base function 385 * @param base base function
366 * @param exceptionClass type of exception for which to retry 386 * @param exceptionClass type of exception for which to retry
......