Deepa Vaddireddy
Committed by Gerrit Code Review

Fix for ONOS-5032 and ONOS-5034

Change-Id: Ib964252dd05754ce7069a7a82ccb1d1c29bfa978
...@@ -24,6 +24,7 @@ import org.onosproject.cli.AbstractShellCommand; ...@@ -24,6 +24,7 @@ import org.onosproject.cli.AbstractShellCommand;
24 import org.onosproject.net.Host; 24 import org.onosproject.net.Host;
25 import org.onosproject.net.host.HostService; 25 import org.onosproject.net.host.HostService;
26 import org.onosproject.utils.Comparators; 26 import org.onosproject.utils.Comparators;
27 +import org.onlab.util.Tools;
27 28
28 import java.util.Collections; 29 import java.util.Collections;
29 import java.util.List; 30 import java.util.List;
...@@ -38,7 +39,7 @@ import static com.google.common.collect.Lists.newArrayList; ...@@ -38,7 +39,7 @@ import static com.google.common.collect.Lists.newArrayList;
38 public class HostsListCommand extends AbstractShellCommand { 39 public class HostsListCommand extends AbstractShellCommand {
39 40
40 private static final String FMT = 41 private static final String FMT =
41 - "id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s%s"; 42 + "id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s%s, last seen time=%s";
42 43
43 private static final String FMT_SHORT = 44 private static final String FMT_SHORT =
44 "id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s"; 45 "id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s";
...@@ -93,7 +94,9 @@ public class HostsListCommand extends AbstractShellCommand { ...@@ -93,7 +94,9 @@ public class HostsListCommand extends AbstractShellCommand {
93 } else { 94 } else {
94 print(FMT, host.id(), host.mac(), 95 print(FMT, host.id(), host.mac(),
95 host.location().deviceId(), host.location().port(), 96 host.location().deviceId(), host.location().port(),
96 - host.vlan(), host.ipAddresses(), annotations(host.annotations())); 97 + host.vlan(), host.ipAddresses(), annotations(host.annotations()),
98 + Tools.timeAgo(host.timestamp().unixTimestamp()));
97 } 99 }
98 } 100 }
99 } 101 }
102 +
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.net; 16 package org.onosproject.net;
17 17
18 import org.onosproject.net.provider.ProviderId; 18 import org.onosproject.net.provider.ProviderId;
19 +import org.onosproject.store.service.WallClockTimestamp;
19 import org.onlab.packet.IpAddress; 20 import org.onlab.packet.IpAddress;
20 import org.onlab.packet.MacAddress; 21 import org.onlab.packet.MacAddress;
21 import org.onlab.packet.VlanId; 22 import org.onlab.packet.VlanId;
...@@ -36,6 +37,7 @@ public class DefaultHost extends AbstractElement implements Host { ...@@ -36,6 +37,7 @@ public class DefaultHost extends AbstractElement implements Host {
36 private final VlanId vlan; 37 private final VlanId vlan;
37 private final HostLocation location; 38 private final HostLocation location;
38 private final Set<IpAddress> ips; 39 private final Set<IpAddress> ips;
40 + private final WallClockTimestamp timestamp;
39 41
40 /** 42 /**
41 * Creates an end-station host using the supplied information. 43 * Creates an end-station host using the supplied information.
...@@ -51,10 +53,29 @@ public class DefaultHost extends AbstractElement implements Host { ...@@ -51,10 +53,29 @@ public class DefaultHost extends AbstractElement implements Host {
51 public DefaultHost(ProviderId providerId, HostId id, MacAddress mac, 53 public DefaultHost(ProviderId providerId, HostId id, MacAddress mac,
52 VlanId vlan, HostLocation location, Set<IpAddress> ips, 54 VlanId vlan, HostLocation location, Set<IpAddress> ips,
53 Annotations... annotations) { 55 Annotations... annotations) {
56 + this(providerId, id, mac, vlan, location, ips, new WallClockTimestamp(), annotations);
57 + }
58 +
59 + /**
60 + * Creates an end-station host using the supplied information.
61 + *
62 + * @param providerId provider identity
63 + * @param id host identifier
64 + * @param mac host MAC address
65 + * @param vlan host VLAN identifier
66 + * @param location host location
67 + * @param ips host IP addresses
68 + * @param timestamp last host updated time
69 + * @param annotations optional key/value annotations
70 + */
71 + public DefaultHost(ProviderId providerId, HostId id, MacAddress mac,
72 + VlanId vlan, HostLocation location, Set<IpAddress> ips,
73 + WallClockTimestamp timestamp, Annotations... annotations) {
54 super(providerId, id, annotations); 74 super(providerId, id, annotations);
55 this.mac = mac; 75 this.mac = mac;
56 this.vlan = vlan; 76 this.vlan = vlan;
57 this.location = location; 77 this.location = location;
78 + this.timestamp = timestamp;
58 this.ips = new HashSet<>(ips); 79 this.ips = new HashSet<>(ips);
59 } 80 }
60 81
...@@ -84,6 +105,11 @@ public class DefaultHost extends AbstractElement implements Host { ...@@ -84,6 +105,11 @@ public class DefaultHost extends AbstractElement implements Host {
84 } 105 }
85 106
86 @Override 107 @Override
108 + public WallClockTimestamp timestamp() {
109 + return timestamp;
110 + }
111 +
112 + @Override
87 public int hashCode() { 113 public int hashCode() {
88 return Objects.hash(id, mac, vlan, location); 114 return Objects.hash(id, mac, vlan, location);
89 } 115 }
...@@ -114,6 +140,7 @@ public class DefaultHost extends AbstractElement implements Host { ...@@ -114,6 +140,7 @@ public class DefaultHost extends AbstractElement implements Host {
114 .add("location", location()) 140 .add("location", location())
115 .add("ipAddresses", ipAddresses()) 141 .add("ipAddresses", ipAddresses())
116 .add("annotations", annotations()) 142 .add("annotations", annotations())
143 + .add("timestamp", timestamp())
117 .toString(); 144 .toString();
118 } 145 }
119 146
......
...@@ -18,6 +18,7 @@ package org.onosproject.net; ...@@ -18,6 +18,7 @@ package org.onosproject.net;
18 import org.onlab.packet.IpAddress; 18 import org.onlab.packet.IpAddress;
19 import org.onlab.packet.MacAddress; 19 import org.onlab.packet.MacAddress;
20 import org.onlab.packet.VlanId; 20 import org.onlab.packet.VlanId;
21 +import org.onosproject.store.service.WallClockTimestamp;
21 22
22 import java.util.Set; 23 import java.util.Set;
23 24
...@@ -63,6 +64,14 @@ public interface Host extends Element { ...@@ -63,6 +64,14 @@ public interface Host extends Element {
63 */ 64 */
64 HostLocation location(); 65 HostLocation location();
65 66
67 + /**
68 + * Returns the host recent time.
69 + * @return host last updated time
70 + */
71 + default WallClockTimestamp timestamp() {
72 + return null;
73 + }
66 // TODO: explore capturing list of recent locations to aid in mobility 74 // TODO: explore capturing list of recent locations to aid in mobility
67 75
68 } 76 }
77 +
......
...@@ -21,6 +21,7 @@ import java.util.Set; ...@@ -21,6 +21,7 @@ import java.util.Set;
21 import org.onosproject.net.AbstractDescription; 21 import org.onosproject.net.AbstractDescription;
22 import org.onosproject.net.HostLocation; 22 import org.onosproject.net.HostLocation;
23 import org.onosproject.net.SparseAnnotations; 23 import org.onosproject.net.SparseAnnotations;
24 +import org.onosproject.store.service.WallClockTimestamp;
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;
...@@ -40,6 +41,7 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -40,6 +41,7 @@ public class DefaultHostDescription extends AbstractDescription
40 private final VlanId vlan; 41 private final VlanId vlan;
41 private final HostLocation location; 42 private final HostLocation location;
42 private final Set<IpAddress> ip; 43 private final Set<IpAddress> ip;
44 + private final WallClockTimestamp timestamp;
43 45
44 /** 46 /**
45 * Creates a host description using the supplied information. 47 * Creates a host description using the supplied information.
...@@ -83,11 +85,28 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -83,11 +85,28 @@ public class DefaultHostDescription extends AbstractDescription
83 public DefaultHostDescription(MacAddress mac, VlanId vlan, 85 public DefaultHostDescription(MacAddress mac, VlanId vlan,
84 HostLocation location, Set<IpAddress> ip, 86 HostLocation location, Set<IpAddress> ip,
85 SparseAnnotations... annotations) { 87 SparseAnnotations... annotations) {
88 + this(mac, vlan, location, ip, new WallClockTimestamp(), annotations);
89 + }
90 +
91 + /**
92 + * Creates a host description using the supplied information.
93 + *
94 + * @param mac host MAC address
95 + * @param vlan host VLAN identifier
96 + * @param location host location
97 + * @param ip host IP addresses
98 + * @param timestamp host recent updated time
99 + * @param annotations optional key/value annotations map
100 + */
101 + public DefaultHostDescription(MacAddress mac, VlanId vlan,
102 + HostLocation location, Set<IpAddress> ip,
103 + WallClockTimestamp timestamp, SparseAnnotations... annotations) {
86 super(annotations); 104 super(annotations);
87 this.mac = mac; 105 this.mac = mac;
88 this.vlan = vlan; 106 this.vlan = vlan;
89 this.location = location; 107 this.location = location;
90 this.ip = ImmutableSet.copyOf(ip); 108 this.ip = ImmutableSet.copyOf(ip);
109 + this.timestamp = timestamp;
91 } 110 }
92 111
93 @Override 112 @Override
...@@ -111,12 +130,18 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -111,12 +130,18 @@ public class DefaultHostDescription extends AbstractDescription
111 } 130 }
112 131
113 @Override 132 @Override
133 + public WallClockTimestamp timestamp() {
134 + return timestamp;
135 + }
136 +
137 + @Override
114 public String toString() { 138 public String toString() {
115 return toStringHelper(this) 139 return toStringHelper(this)
116 .add("mac", mac) 140 .add("mac", mac)
117 .add("vlan", vlan) 141 .add("vlan", vlan)
118 .add("location", location) 142 .add("location", location)
119 .add("ipAddress", ip) 143 .add("ipAddress", ip)
144 + .add("timestamp", timestamp)
120 .toString(); 145 .toString();
121 } 146 }
122 147
...@@ -139,5 +164,4 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -139,5 +164,4 @@ public class DefaultHostDescription extends AbstractDescription
139 } 164 }
140 return false; 165 return false;
141 } 166 }
142 -
143 } 167 }
......
...@@ -22,6 +22,7 @@ import org.onosproject.net.HostLocation; ...@@ -22,6 +22,7 @@ import org.onosproject.net.HostLocation;
22 import org.onlab.packet.IpAddress; 22 import org.onlab.packet.IpAddress;
23 import org.onlab.packet.MacAddress; 23 import org.onlab.packet.MacAddress;
24 import org.onlab.packet.VlanId; 24 import org.onlab.packet.VlanId;
25 +import org.onosproject.store.service.WallClockTimestamp;
25 26
26 /** 27 /**
27 * Information describing host and its location. 28 * Information describing host and its location.
...@@ -55,4 +56,12 @@ public interface HostDescription extends Description { ...@@ -55,4 +56,12 @@ public interface HostDescription extends Description {
55 * @return host IP address 56 * @return host IP address
56 */ 57 */
57 Set<IpAddress> ipAddress(); 58 Set<IpAddress> ipAddress();
59 +
60 + /**
61 + * Returns the host recent updated Time.
62 + * @return host last updated time.
63 + */
64 + default WallClockTimestamp timestamp() {
65 + return null;
66 + }
58 } 67 }
......
...@@ -39,7 +39,8 @@ public final class HostCodec extends AnnotatedCodec<Host> { ...@@ -39,7 +39,8 @@ public final class HostCodec extends AnnotatedCodec<Host> {
39 final ObjectNode result = context.mapper().createObjectNode() 39 final ObjectNode result = context.mapper().createObjectNode()
40 .put("id", host.id().toString()) 40 .put("id", host.id().toString())
41 .put("mac", host.mac().toString()) 41 .put("mac", host.mac().toString())
42 - .put("vlan", host.vlan().toString()); 42 + .put("vlan", host.vlan().toString())
43 + .put("timestamp", host.timestamp().unixTimestamp());
43 44
44 final ArrayNode jsonIpAddresses = result.putArray("ipAddresses"); 45 final ArrayNode jsonIpAddresses = result.putArray("ipAddresses");
45 for (final IpAddress ipAddress : host.ipAddresses()) { 46 for (final IpAddress ipAddress : host.ipAddresses()) {
......
...@@ -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
...@@ -273,3 +377,4 @@ public class HostManager ...@@ -273,3 +377,4 @@ public class HostManager
273 } 377 }
274 } 378 }
275 } 379 }
380 +
......
...@@ -149,6 +149,13 @@ public class HostMonitor implements TimerTask { ...@@ -149,6 +149,13 @@ public class HostMonitor implements TimerTask {
149 hostProviders.put(provider.id(), provider); 149 hostProviders.put(provider.id(), provider);
150 } 150 }
151 151
152 + /*
153 + * Sets the probe rate.
154 + */
155 + void setProbeRate(long probeRate) {
156 + this.probeRate = probeRate;
157 + }
158 +
152 @Override 159 @Override
153 public void run(Timeout timeout) throws Exception { 160 public void run(Timeout timeout) throws Exception {
154 for (IpAddress ip : monitoredAddresses) { 161 for (IpAddress ip : monitoredAddresses) {
......
...@@ -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,29 +115,27 @@ public class HostManagerTest { ...@@ -101,29 +115,27 @@ 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
108 provider = new TestHostProvider(); 123 provider = new TestHostProvider();
109 providerService = registry.register(provider); 124 providerService = registry.register(provider);
110 - assertTrue("provider should be registered", 125 + assertTrue("provider should be registered", registry.getProviders().contains(provider.id()));
111 - registry.getProviders().contains(provider.id()));
112 } 126 }
113 127
114 @After 128 @After
115 public void tearDown() { 129 public void tearDown() {
116 registry.unregister(provider); 130 registry.unregister(provider);
117 - assertFalse("provider should not be registered", 131 + assertFalse("provider should not be registered", registry.getProviders().contains(provider.id()));
118 - registry.getProviders().contains(provider.id()));
119 132
120 mgr.removeListener(listener); 133 mgr.removeListener(listener);
121 mgr.deactivate(); 134 mgr.deactivate();
122 injectEventDispatcher(mgr, null); 135 injectEventDispatcher(mgr, null);
123 } 136 }
124 137
125 - private void detect(HostId hid, MacAddress mac, VlanId vlan, 138 + private void detect(HostId hid, MacAddress mac, VlanId vlan, HostLocation loc, IpAddress ip) {
126 - HostLocation loc, IpAddress ip) {
127 HostDescription descr = new DefaultHostDescription(mac, vlan, loc, ip); 139 HostDescription descr = new DefaultHostDescription(mac, vlan, loc, ip);
128 providerService.hostDetected(hid, descr, false); 140 providerService.hostDetected(hid, descr, false);
129 assertNotNull("host should be found", mgr.getHost(hid)); 141 assertNotNull("host should be found", mgr.getHost(hid));
...@@ -203,8 +215,7 @@ public class HostManagerTest { ...@@ -203,8 +215,7 @@ public class HostManagerTest {
203 assertNull("host should have been removed", mgr.getHost(HID3)); 215 assertNull("host should have been removed", mgr.getHost(HID3));
204 } 216 }
205 217
206 - private void validateHosts( 218 + private void validateHosts(String msg, Iterable<Host> hosts, HostId... ids) {
207 - String msg, Iterable<Host> hosts, HostId... ids) {
208 Set<HostId> hids = Sets.newHashSet(ids); 219 Set<HostId> hids = Sets.newHashSet(ids);
209 for (Host h : hosts) { 220 for (Host h : hosts) {
210 assertTrue(msg, hids.remove(h.id())); 221 assertTrue(msg, hids.remove(h.id()));
...@@ -238,8 +249,7 @@ public class HostManagerTest { ...@@ -238,8 +249,7 @@ public class HostManagerTest {
238 assertTrue("incorrect host location", mgr.getConnectedHosts(DID2).isEmpty()); 249 assertTrue("incorrect host location", mgr.getConnectedHosts(DID2).isEmpty());
239 } 250 }
240 251
241 - private static class TestHostProvider extends AbstractProvider 252 + private static class TestHostProvider extends AbstractProvider implements HostProvider {
242 - implements HostProvider {
243 253
244 protected TestHostProvider() { 254 protected TestHostProvider() {
245 super(PID); 255 super(PID);
...@@ -270,3 +280,4 @@ public class HostManagerTest { ...@@ -270,3 +280,4 @@ public class HostManagerTest {
270 private class TestNetworkConfigService extends NetworkConfigServiceAdapter { 280 private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
271 } 281 }
272 } 282 }
283 +
......
...@@ -48,6 +48,7 @@ import org.onosproject.store.service.MapEvent; ...@@ -48,6 +48,7 @@ import org.onosproject.store.service.MapEvent;
48 import org.onosproject.store.service.MapEventListener; 48 import org.onosproject.store.service.MapEventListener;
49 import org.onosproject.store.service.Serializer; 49 import org.onosproject.store.service.Serializer;
50 import org.onosproject.store.service.StorageService; 50 import org.onosproject.store.service.StorageService;
51 +import org.onosproject.store.service.WallClockTimestamp;
51 import org.slf4j.Logger; 52 import org.slf4j.Logger;
52 53
53 import java.util.Collection; 54 import java.util.Collection;
...@@ -91,7 +92,8 @@ public class DistributedHostStore ...@@ -91,7 +92,8 @@ public class DistributedHostStore
91 @Activate 92 @Activate
92 public void activate() { 93 public void activate() {
93 KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder() 94 KryoNamespace.Builder hostSerializer = KryoNamespace.newBuilder()
94 - .register(KryoNamespaces.API); 95 + .register(KryoNamespaces.API)
96 + .register(WallClockTimestamp.class);
95 97
96 hostsConsistentMap = storageService.<HostId, DefaultHost>consistentMapBuilder() 98 hostsConsistentMap = storageService.<HostId, DefaultHost>consistentMapBuilder()
97 .withName("onos-hosts") 99 .withName("onos-hosts")
...@@ -128,7 +130,9 @@ public class DistributedHostStore ...@@ -128,7 +130,9 @@ public class DistributedHostStore
128 if (!Objects.equals(existingHost.providerId(), providerId) || 130 if (!Objects.equals(existingHost.providerId(), providerId) ||
129 !Objects.equals(existingHost.mac(), hostDescription.hwAddress()) || 131 !Objects.equals(existingHost.mac(), hostDescription.hwAddress()) ||
130 !Objects.equals(existingHost.vlan(), hostDescription.vlan()) || 132 !Objects.equals(existingHost.vlan(), hostDescription.vlan()) ||
131 - !Objects.equals(existingHost.location(), hostDescription.location())) { 133 + !Objects.equals(existingHost.location(), hostDescription.location()) ||
134 + hostDescription.timestamp() == null ||
135 + hostDescription.timestamp().isNewerThan(existingHost.timestamp())) {
132 return true; 136 return true;
133 } 137 }
134 138
...@@ -179,13 +183,13 @@ public class DistributedHostStore ...@@ -179,13 +183,13 @@ public class DistributedHostStore
179 } else { 183 } else {
180 annotations = hostDescription.annotations(); 184 annotations = hostDescription.annotations();
181 } 185 }
182 -
183 return new DefaultHost(providerId, 186 return new DefaultHost(providerId,
184 hostId, 187 hostId,
185 hostDescription.hwAddress(), 188 hostDescription.hwAddress(),
186 hostDescription.vlan(), 189 hostDescription.vlan(),
187 location, 190 location,
188 addresses, 191 addresses,
192 + hostDescription.timestamp(),
189 annotations); 193 annotations);
190 }); 194 });
191 return null; 195 return null;
...@@ -307,3 +311,4 @@ public class DistributedHostStore ...@@ -307,3 +311,4 @@ public class DistributedHostStore
307 } 311 }
308 } 312 }
309 } 313 }
314 +
......
...@@ -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 {
...@@ -449,3 +510,4 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -449,3 +510,4 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
449 } 510 }
450 511
451 } 512 }
513 +
......
...@@ -348,6 +348,26 @@ public abstract class Tools { ...@@ -348,6 +348,26 @@ public abstract class Tools {
348 } 348 }
349 349
350 /** 350 /**
351 + * Get Long property from the propertyName
352 + * Return null if propertyName is not found.
353 + *
354 + * @param properties properties to be looked up
355 + * @param propertyName the name of the property to look up
356 + * @return value when the propertyName is defined or return null
357 + */
358 + public static Long getLongProperty(Dictionary<?, ?> properties,
359 + String propertyName) {
360 + Long value;
361 + try {
362 + String s = get(properties, propertyName);
363 + value = Strings.isNullOrEmpty(s) ? null : Long.valueOf(s);
364 + } catch (NumberFormatException | ClassCastException e) {
365 + value = null;
366 + }
367 + return value;
368 + }
369 +
370 + /**
351 * Suspends the current thread for a specified number of millis. 371 * Suspends the current thread for a specified number of millis.
352 * 372 *
353 * @param ms number of millis 373 * @param ms number of millis
......
...@@ -198,7 +198,7 @@ public class HostResourceTest extends ResourceTest { ...@@ -198,7 +198,7 @@ public class HostResourceTest extends ResourceTest {
198 @Override 198 @Override
199 public boolean matchesSafely(JsonArray json) { 199 public boolean matchesSafely(JsonArray json) {
200 boolean hostFound = false; 200 boolean hostFound = false;
201 - final int expectedAttributes = 5; 201 + final int expectedAttributes = 6;
202 for (int jsonHostIndex = 0; jsonHostIndex < json.size(); 202 for (int jsonHostIndex = 0; jsonHostIndex < json.size();
203 jsonHostIndex++) { 203 jsonHostIndex++) {
204 204
......