blob: 13a13d70fbf9505c6b07c49599990dd4cd141d61 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.host.impl;
tomdb0d03f2014-08-27 16:34:15 -070017
Pier Luigi9b1d6262017-02-02 22:31:34 -080018import org.onlab.packet.Ip6Address;
Simon Huntff663742015-05-14 13:33:05 -070019import org.onlab.packet.IpAddress;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
soumya3e6f05e2016-08-05 15:11:11 -070022import org.onlab.util.Tools;
23import org.onosproject.cfg.ComponentConfigService;
Charles Chan888e20a2017-05-01 15:44:23 -070024import org.onosproject.net.ConnectPoint;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.Host;
27import org.onosproject.net.HostId;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070028import org.onosproject.net.HostLocation;
29import org.onosproject.net.config.NetworkConfigEvent;
30import org.onosproject.net.config.NetworkConfigListener;
31import org.onosproject.net.config.NetworkConfigService;
32import org.onosproject.net.config.basics.BasicHostConfig;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.device.DeviceService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070034import org.onosproject.net.edge.EdgePortService;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.host.HostAdminService;
36import org.onosproject.net.host.HostDescription;
37import org.onosproject.net.host.HostEvent;
38import org.onosproject.net.host.HostListener;
39import org.onosproject.net.host.HostProvider;
40import org.onosproject.net.host.HostProviderRegistry;
41import org.onosproject.net.host.HostProviderService;
42import org.onosproject.net.host.HostService;
43import org.onosproject.net.host.HostStore;
44import org.onosproject.net.host.HostStoreDelegate;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070045import org.onosproject.net.intf.Interface;
46import org.onosproject.net.intf.InterfaceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080047import org.onosproject.net.packet.PacketService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070048import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.provider.AbstractProviderService;
soumya3e6f05e2016-08-05 15:11:11 -070050import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070051import org.osgi.service.component.annotations.Activate;
52import org.osgi.service.component.annotations.Component;
53import org.osgi.service.component.annotations.Deactivate;
54import org.osgi.service.component.annotations.Modified;
55import org.osgi.service.component.annotations.Reference;
56import org.osgi.service.component.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070057import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070058
soumya3e6f05e2016-08-05 15:11:11 -070059import java.util.Dictionary;
Simon Huntff663742015-05-14 13:33:05 -070060import java.util.Set;
61
62import static com.google.common.base.Preconditions.checkNotNull;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070063import static com.google.common.base.Preconditions.checkState;
Pier Luigi9b1d6262017-02-02 22:31:34 -080064import static org.onlab.packet.IPv6.getLinkLocalAddress;
Ray Milkeyd04e2272018-10-16 18:20:18 -070065import static org.onosproject.net.OsgiPropertyConstants.HM_ALLOW_DUPLICATE_IPS;
66import static org.onosproject.net.OsgiPropertyConstants.HM_ALLOW_DUPLICATE_IPS_DEFAULT;
67import static org.onosproject.net.OsgiPropertyConstants.HM_GREEDY_LEARNING_IPV6;
68import static org.onosproject.net.OsgiPropertyConstants.HM_GREEDY_LEARNING_IPV6_DEFAULT;
69import static org.onosproject.net.OsgiPropertyConstants.HM_MONITOR_HOSTS;
70import static org.onosproject.net.OsgiPropertyConstants.HM_MONITOR_HOSTS_DEFAULT;
71import static org.onosproject.net.OsgiPropertyConstants.HM_PROBE_RATE;
72import static org.onosproject.net.OsgiPropertyConstants.HM_PROBE_RATE_DEFAULT;
Changhoon Yoon541ef712015-05-23 17:18:34 +090073import static org.onosproject.security.AppGuard.checkPermission;
Simon Huntffbad3b2017-05-16 15:37:51 -070074import static org.onosproject.security.AppPermission.Type.HOST_EVENT;
75import static org.onosproject.security.AppPermission.Type.HOST_READ;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070076import static org.slf4j.LoggerFactory.getLogger;
Simon Huntff663742015-05-14 13:33:05 -070077
tomdb0d03f2014-08-27 16:34:15 -070078/**
79 * Provides basic implementation of the host SB & NB APIs.
80 */
Ray Milkeyd04e2272018-10-16 18:20:18 -070081@Component(
82 immediate = true,
83 service = {
84 HostService.class,
85 HostAdminService.class,
86 HostProviderRegistry.class
87 },
88 property = {
Ray Milkey2d7bca12018-10-17 14:51:52 -070089 HM_ALLOW_DUPLICATE_IPS + ":Boolean=" + HM_ALLOW_DUPLICATE_IPS_DEFAULT,
90 HM_MONITOR_HOSTS + ":Boolean=" + HM_MONITOR_HOSTS_DEFAULT,
91 HM_PROBE_RATE + ":Integer=" + HM_PROBE_RATE_DEFAULT,
92 HM_GREEDY_LEARNING_IPV6 + ":Boolean=" + HM_GREEDY_LEARNING_IPV6_DEFAULT
Ray Milkeyd04e2272018-10-16 18:20:18 -070093 }
94)
tom202175a2014-09-19 19:00:11 -070095public class HostManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070096 extends AbstractListenerProviderRegistry<HostEvent, HostListener, HostProvider, HostProviderService>
tom89b63c52014-09-16 09:19:51 -070097 implements HostService, HostAdminService, HostProviderRegistry {
tomdb0d03f2014-08-27 16:34:15 -070098
tom5f38b3a2014-08-27 23:50:54 -070099 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -0700100
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700101 public static final String HOST_ID_NULL = "Host ID cannot be null";
tom5f38b3a2014-08-27 23:50:54 -0700102
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700103 private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
104
tomc78acee2014-09-24 15:16:55 -0700105 private HostStoreDelegate delegate = new InternalStoreDelegate();
106
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700107 @Reference(cardinality = ReferenceCardinality.MANDATORY)
tom5bcc9462014-09-19 10:11:31 -0700108 protected HostStore store;
tom7869ad92014-09-09 14:32:08 -0700109
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700110 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart70da5122014-10-01 16:37:42 -0700111 protected DeviceService deviceService;
112
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700113 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart70da5122014-10-01 16:37:42 -0700114 protected PacketService packetService;
115
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700117 protected NetworkConfigService networkConfigService;
118
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart4cb39882015-08-12 23:50:55 -0400120 protected InterfaceService interfaceService;
121
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200123 protected EdgePortService edgePortService;
124
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
soumya3e6f05e2016-08-05 15:11:11 -0700126 protected ComponentConfigService cfgService;
127
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700128 //@Property(name = "allowDuplicateIps", boolValue = true,
129 // label = "Enable removal of duplicate ip address")
Ray Milkeyd04e2272018-10-16 18:20:18 -0700130 private boolean allowDuplicateIps = HM_ALLOW_DUPLICATE_IPS_DEFAULT;
sdn94b00152016-08-30 02:12:32 -0700131
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700132 //@Property(name = "monitorHosts", boolValue = false,
133 // label = "Enable/Disable monitoring of hosts")
Ray Milkeyd04e2272018-10-16 18:20:18 -0700134 private boolean monitorHosts = HM_MONITOR_HOSTS_DEFAULT;
sdn94b00152016-08-30 02:12:32 -0700135
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700136 //@Property(name = "probeRate", longValue = 30000,
137 // label = "Set the probe Rate in milli seconds")
Ray Milkeyd04e2272018-10-16 18:20:18 -0700138 private long probeRate = HM_PROBE_RATE_DEFAULT;
sdn94b00152016-08-30 02:12:32 -0700139
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700140 //@Property(name = "greedyLearningIpv6", boolValue = false,
141 // label = "Enable/Disable greedy learning of IPv6 link local address")
Ray Milkeyd04e2272018-10-16 18:20:18 -0700142 private boolean greedyLearningIpv6 = HM_GREEDY_LEARNING_IPV6_DEFAULT;
Pier Luigi9b1d6262017-02-02 22:31:34 -0800143
Jonathan Hart70da5122014-10-01 16:37:42 -0700144 private HostMonitor monitor;
tomdb0d03f2014-08-27 16:34:15 -0700145
soumya3e6f05e2016-08-05 15:11:11 -0700146
tomdb0d03f2014-08-27 16:34:15 -0700147 @Activate
soumya3e6f05e2016-08-05 15:11:11 -0700148 public void activate(ComponentContext context) {
tomc78acee2014-09-24 15:16:55 -0700149 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -0700150 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
soumya3e6f05e2016-08-05 15:11:11 -0700151 cfgService.registerProperties(getClass());
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700152 networkConfigService.addListener(networkConfigListener);
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200153 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
sdn94b00152016-08-30 02:12:32 -0700154 monitor.setProbeRate(probeRate);
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700155 monitor.start();
sdn94b00152016-08-30 02:12:32 -0700156 modified(context);
157 cfgService.registerProperties(getClass());
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700158 log.info("Started");
tomdb0d03f2014-08-27 16:34:15 -0700159 }
160
sdn94b00152016-08-30 02:12:32 -0700161 @Deactivate
162 public void deactivate() {
163 store.unsetDelegate(delegate);
164 eventDispatcher.removeSink(HostEvent.class);
165 networkConfigService.removeListener(networkConfigListener);
166 cfgService.unregisterProperties(getClass(), false);
167 monitor.shutdown();
168 log.info("Stopped");
169 }
170
soumya3e6f05e2016-08-05 15:11:11 -0700171 @Modified
Simon Huntffbad3b2017-05-16 15:37:51 -0700172 public void modified(ComponentContext context) {
sdn94b00152016-08-30 02:12:32 -0700173 boolean oldValue = monitorHosts;
174 readComponentConfiguration(context);
175 if (probeRate > 0) {
176 monitor.setProbeRate(probeRate);
177 } else {
178 log.warn("probeRate cannot be lessthan 0");
179 }
180
181 if (oldValue != monitorHosts) {
182 if (monitorHosts) {
183 startMonitoring();
184 } else {
185 stopMonitoring();
186 }
187 }
188 }
189
190 /**
191 * Extracts properties from the component configuration context.
192 *
193 * @param context the component context
194 */
195 private void readComponentConfiguration(ComponentContext context) {
soumya3e6f05e2016-08-05 15:11:11 -0700196 Dictionary<?, ?> properties = context.getProperties();
197 Boolean flag;
sdn94b00152016-08-30 02:12:32 -0700198
199 flag = Tools.isPropertyEnabled(properties, "monitorHosts");
200 if (flag == null) {
201 log.info("monitorHosts is not enabled " +
202 "using current value of {}", monitorHosts);
203 } else {
204 monitorHosts = flag;
205 log.info("Configured. monitorHosts {}",
Simon Huntffbad3b2017-05-16 15:37:51 -0700206 monitorHosts ? "enabled" : "disabled");
sdn94b00152016-08-30 02:12:32 -0700207 }
208
209 Long longValue = Tools.getLongProperty(properties, "probeRate");
210 if (longValue == null || longValue == 0) {
211 log.info("probeRate is not set sing default value of {}", probeRate);
212 } else {
213 probeRate = longValue;
214 log.info("Configured. probeRate {}", probeRate);
215 }
216
soumya3e6f05e2016-08-05 15:11:11 -0700217 flag = Tools.isPropertyEnabled(properties, "allowDuplicateIps");
218 if (flag == null) {
219 log.info("Removal of duplicate ip address is not configured");
220 } else {
221 allowDuplicateIps = flag;
222 log.info("Removal of duplicate ip address is {}",
223 allowDuplicateIps ? "disabled" : "enabled");
224 }
sdn94b00152016-08-30 02:12:32 -0700225
Pier Luigi9b1d6262017-02-02 22:31:34 -0800226 flag = Tools.isPropertyEnabled(properties, "greedyLearningIpv6");
227 if (flag == null) {
228 log.info("greedy learning is not enabled " +
229 "using current value of {}", greedyLearningIpv6);
230 } else {
231 greedyLearningIpv6 = flag;
232 log.info("Configured. greedyLearningIpv6 {}",
233 greedyLearningIpv6 ? "enabled" : "disabled");
234 }
235
soumya3e6f05e2016-08-05 15:11:11 -0700236 }
237
sdn94b00152016-08-30 02:12:32 -0700238 /**
239 * Starts monitoring the hosts by IP Address.
sdn94b00152016-08-30 02:12:32 -0700240 */
241 private void startMonitoring() {
242 store.getHosts().forEach(host -> {
Simon Huntffbad3b2017-05-16 15:37:51 -0700243 host.ipAddresses().forEach(ip -> {
244 monitor.addMonitoringFor(ip);
sdn94b00152016-08-30 02:12:32 -0700245 });
246 });
247 }
248
249 /**
250 * Stops monitoring the hosts by IP Address.
sdn94b00152016-08-30 02:12:32 -0700251 */
252 private void stopMonitoring() {
253 store.getHosts().forEach(host -> {
Simon Huntffbad3b2017-05-16 15:37:51 -0700254 host.ipAddresses().forEach(ip -> {
255 monitor.stopMonitoring(ip);
sdn94b00152016-08-30 02:12:32 -0700256 });
257 });
tomdb0d03f2014-08-27 16:34:15 -0700258 }
259
260 @Override
tom5f38b3a2014-08-27 23:50:54 -0700261 protected HostProviderService createProviderService(HostProvider provider) {
Jonathan Hart70da5122014-10-01 16:37:42 -0700262 monitor.registerHostProvider(provider);
tom5f38b3a2014-08-27 23:50:54 -0700263 return new InternalHostProviderService(provider);
tomdb0d03f2014-08-27 16:34:15 -0700264 }
265
tom7869ad92014-09-09 14:32:08 -0700266 @Override
267 public int getHostCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900268 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700269 return store.getHostCount();
270 }
271
272 @Override
273 public Iterable<Host> getHosts() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900274 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700275 return store.getHosts();
276 }
277
278 @Override
279 public Host getHost(HostId hostId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900280 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700281 checkNotNull(hostId, HOST_ID_NULL);
282 return store.getHost(hostId);
283 }
284
285 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700286 public Set<Host> getHostsByVlan(VlanId vlanId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900287 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700288 return store.getHosts(vlanId);
289 }
290
291 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700292 public Set<Host> getHostsByMac(MacAddress mac) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900293 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700294 checkNotNull(mac, "MAC address cannot be null");
295 return store.getHosts(mac);
296 }
297
298 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700299 public Set<Host> getHostsByIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900300 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700301 checkNotNull(ip, "IP address cannot be null");
302 return store.getHosts(ip);
303 }
304
305 @Override
306 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900307 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700308 checkNotNull(connectPoint, "Connection point cannot be null");
309 return store.getConnectedHosts(connectPoint);
310 }
311
312 @Override
313 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900314 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700315 checkNotNull(deviceId, "Device ID cannot be null");
316 return store.getConnectedHosts(deviceId);
317 }
318
319 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700320 public void startMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900321 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700322 monitor.addMonitoringFor(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700323 }
324
325 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700326 public void stopMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900327 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700328 monitor.stopMonitoring(ip);
Jonathan Hartac60c082014-09-23 08:55:17 -0700329 }
330
331 @Override
332 public void requestMac(IpAddress ip) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700333 // FIXME!!!! Auto-generated method stub
tom7869ad92014-09-09 14:32:08 -0700334 }
335
tom89b63c52014-09-16 09:19:51 -0700336 @Override
337 public void removeHost(HostId hostId) {
338 checkNotNull(hostId, HOST_ID_NULL);
Charles Chan009c3082015-11-10 14:18:04 -0800339 store.removeHost(hostId);
tom89b63c52014-09-16 09:19:51 -0700340 }
341
tomdb0d03f2014-08-27 16:34:15 -0700342 // Personalized host provider service issued to the supplied provider.
tom7869ad92014-09-09 14:32:08 -0700343 private class InternalHostProviderService
344 extends AbstractProviderService<HostProvider>
tomdb0d03f2014-08-27 16:34:15 -0700345 implements HostProviderService {
tomcfde0622014-09-09 11:02:42 -0700346 InternalHostProviderService(HostProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700347 super(provider);
348 }
349
350 @Override
Brian O'Connorf107bd72015-09-21 15:31:03 -0700351 public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
tom7869ad92014-09-09 14:32:08 -0700352 checkNotNull(hostId, HOST_ID_NULL);
353 checkValidity();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700354 hostDescription = validateHost(hostDescription, hostId);
soumya3e6f05e2016-08-05 15:11:11 -0700355
356 if (!allowDuplicateIps) {
357 removeDuplicates(hostId, hostDescription);
358 }
Charles Chan009c3082015-11-10 14:18:04 -0800359 store.createOrUpdateHost(provider().id(), hostId,
soumya3e6f05e2016-08-05 15:11:11 -0700360 hostDescription, replaceIps);
sdn94b00152016-08-30 02:12:32 -0700361
362 if (monitorHosts) {
363 hostDescription.ipAddress().forEach(ip -> {
364 monitor.addMonitoringFor(ip);
365 });
366 }
Pier Luigi9b1d6262017-02-02 22:31:34 -0800367
368 // Greedy learning of IPv6 host. We have to disable the greedy
369 // learning of configured hosts. Validate hosts each time will
Charles Chan82fac582017-09-12 12:09:22 -0700370 // overwrite the learnt information with the configured information.
Pier Luigi9b1d6262017-02-02 22:31:34 -0800371 if (greedyLearningIpv6) {
372 // Auto-generation of the IPv6 link local address
373 // using the mac address
374 Ip6Address targetIp6Address = Ip6Address.valueOf(
375 getLinkLocalAddress(hostId.mac().toBytes())
376 );
377 // If we already know this guy we don't need to do other
378 if (!hostDescription.ipAddress().contains(targetIp6Address)) {
379 Host host = store.getHost(hostId);
380 // Configured host, skip it.
381 if (host != null && host.configured()) {
382 return;
383 }
384 // Host does not exist in the store or the target is not known
385 if ((host == null || !host.ipAddresses().contains(targetIp6Address))) {
Charles Chan82fac582017-09-12 12:09:22 -0700386 // Use DAD to probe if interface MAC is not specified
387 MacAddress probeMac = interfaceService.getInterfacesByPort(hostDescription.location())
388 .stream().map(Interface::mac).findFirst().orElse(MacAddress.ONOS);
389 Ip6Address probeIp = !probeMac.equals(MacAddress.ONOS) ?
390 Ip6Address.valueOf(getLinkLocalAddress(probeMac.toBytes())) :
391 Ip6Address.ZERO;
Pier Luigi9b1d6262017-02-02 22:31:34 -0800392 // We send a probe using the monitoring service
393 monitor.sendProbe(
394 hostDescription.location(),
395 targetIp6Address,
Charles Chan82fac582017-09-12 12:09:22 -0700396 probeIp,
397 probeMac,
Pier Luigi9b1d6262017-02-02 22:31:34 -0800398 hostId.vlanId()
399 );
400 }
401 }
402 }
tomdb0d03f2014-08-27 16:34:15 -0700403 }
404
soumya3e6f05e2016-08-05 15:11:11 -0700405 // When a new IP is detected, remove that IP on other hosts if it exists
406 public void removeDuplicates(HostId hostId, HostDescription desc) {
407 desc.ipAddress().forEach(ip -> {
408 Set<Host> allHosts = store.getHosts(ip);
409 allHosts.forEach(eachHost -> {
410 if (!(eachHost.id().equals(hostId))) {
411 log.info("Duplicate ip {} found on host {} and {}", ip,
412 hostId.toString(), eachHost.id().toString());
413 store.removeIp(eachHost.id(), ip);
414 }
415 });
416 });
Jonathan Hart38feb6e2016-08-29 22:54:16 +0000417 }
418
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700419 // returns a HostDescription made from the union of the BasicHostConfig
420 // annotations if it exists
421 private HostDescription validateHost(HostDescription hostDescription, HostId hostId) {
422 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
423 checkState(cfg == null || cfg.isAllowed(), "Host {} is not allowed", hostId);
Ayaka Koshibe5373e762015-08-06 12:31:44 -0700424
425 return BasicHostOperator.combine(cfg, hostDescription);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700426 }
427
tomdb0d03f2014-08-27 16:34:15 -0700428 @Override
tom7869ad92014-09-09 14:32:08 -0700429 public void hostVanished(HostId hostId) {
430 checkNotNull(hostId, HOST_ID_NULL);
431 checkValidity();
sdn94b00152016-08-30 02:12:32 -0700432 Host host = store.getHost(hostId);
Charles Chan29ecdee2017-02-22 18:46:56 -0800433
Charles Chan888e20a2017-05-01 15:44:23 -0700434 if (!allowedToChange(hostId)) {
435 log.info("Request to remove {} is ignored due to provider mismatch", hostId);
Charles Chan29ecdee2017-02-22 18:46:56 -0800436 return;
437 }
438
sdn94b00152016-08-30 02:12:32 -0700439 if (monitorHosts) {
440 host.ipAddresses().forEach(ip -> {
441 monitor.stopMonitoring(ip);
442 });
443 }
Charles Chan009c3082015-11-10 14:18:04 -0800444 store.removeHost(hostId);
tomdb0d03f2014-08-27 16:34:15 -0700445 }
samanwita palc40e5ed2015-09-24 11:01:51 -0700446
447 @Override
448 public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
449 checkNotNull(hostId, HOST_ID_NULL);
450 checkValidity();
Charles Chan888e20a2017-05-01 15:44:23 -0700451
452 if (!allowedToChange(hostId)) {
453 log.info("Request to remove {} from {} is ignored due to provider mismatch",
454 ipAddress, hostId);
455 return;
456 }
457
Charles Chan009c3082015-11-10 14:18:04 -0800458 store.removeIp(hostId, ipAddress);
samanwita palc40e5ed2015-09-24 11:01:51 -0700459 }
Charles Chan888e20a2017-05-01 15:44:23 -0700460
461 @Override
Charles Chanff79dd92018-06-01 16:33:48 -0700462 public void addLocationToHost(HostId hostId, HostLocation location) {
463 checkNotNull(hostId, HOST_ID_NULL);
464 checkValidity();
465
466 if (!allowedToChange(hostId)) {
Charles Chanb928b3f2018-07-23 15:37:08 -0700467 log.info("Request to add {} to {} is ignored due to provider mismatch",
Charles Chanff79dd92018-06-01 16:33:48 -0700468 location, hostId);
469 return;
470 }
471
472 store.appendLocation(hostId, location);
473 }
474
475 @Override
Charles Chan888e20a2017-05-01 15:44:23 -0700476 public void removeLocationFromHost(HostId hostId, HostLocation location) {
477 checkNotNull(hostId, HOST_ID_NULL);
478 checkValidity();
479
480 if (!allowedToChange(hostId)) {
481 log.info("Request to remove {} from {} is ignored due to provider mismatch",
482 location, hostId);
483 return;
484 }
485
486 store.removeLocation(hostId, location);
487 }
488
Charles Chand0c147a2017-09-14 14:00:10 -0700489 /**
490 * Providers should only be able to remove a host that is provided by itself,
491 * or a host that is not configured.
492 */
Charles Chan888e20a2017-05-01 15:44:23 -0700493 private boolean allowedToChange(HostId hostId) {
Charles Chan888e20a2017-05-01 15:44:23 -0700494 Host host = store.getHost(hostId);
Charles Chand0c147a2017-09-14 14:00:10 -0700495 return host == null || !host.configured() || host.providerId().equals(provider().id());
Charles Chan888e20a2017-05-01 15:44:23 -0700496 }
tomdb0d03f2014-08-27 16:34:15 -0700497 }
tom7869ad92014-09-09 14:32:08 -0700498
tomc78acee2014-09-24 15:16:55 -0700499 // Store delegate to re-post events emitted from the store.
500 private class InternalStoreDelegate implements HostStoreDelegate {
501 @Override
502 public void notify(HostEvent event) {
503 post(event);
504 }
505 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700506
507 // listens for NetworkConfigEvents of type BasicHostConfig and removes
508 // links that the config does not allow
509 private class InternalNetworkConfigListener implements NetworkConfigListener {
510 @Override
Simon Huntffbad3b2017-05-16 15:37:51 -0700511 public boolean isRelevant(NetworkConfigEvent event) {
512 return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
513 || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)
514 && (event.configClass().equals(BasicHostConfig.class));
515 }
516
517 @Override
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700518 public void event(NetworkConfigEvent event) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700519 log.debug("Detected host network config event {}", event.type());
520 HostEvent he = null;
521
522 HostId hostId = (HostId) event.subject();
523 BasicHostConfig cfg =
524 networkConfigService.getConfig(hostId, BasicHostConfig.class);
525
526 if (!isAllowed(cfg)) {
527 kickOutBadHost(hostId);
528 } else {
529 Host host = getHost(hostId);
530 HostDescription desc =
531 (host == null) ? null : BasicHostOperator.descriptionOf(host);
532 desc = BasicHostOperator.combine(cfg, desc);
533 if (desc != null) {
534 he = store.createOrUpdateHost(host.providerId(), hostId, desc, false);
535 }
536 }
537
538 if (he != null) {
539 post(he);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700540 }
541 }
542 }
543
Simon Huntffbad3b2017-05-16 15:37:51 -0700544 // by default allowed, otherwise check flag
545 private boolean isAllowed(BasicHostConfig cfg) {
546 return (cfg == null || cfg.isAllowed());
547 }
548
549 // removes the specified host, if it exists
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700550 private void kickOutBadHost(HostId hostId) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700551 Host badHost = getHost(hostId);
552 if (badHost != null) {
553 removeHost(hostId);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700554 }
555 }
tomdb0d03f2014-08-27 16:34:15 -0700556}