blob: df25281e684637ee8d981af9d0994973a624f3e7 [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;
Rafał Szaleckide5cf842018-11-17 13:30:01 +010029import org.onosproject.net.config.Config;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070030import org.onosproject.net.config.NetworkConfigEvent;
31import org.onosproject.net.config.NetworkConfigListener;
32import org.onosproject.net.config.NetworkConfigService;
33import org.onosproject.net.config.basics.BasicHostConfig;
Rafał Szaleckide5cf842018-11-17 13:30:01 +010034import org.onosproject.net.config.basics.HostAnnotationConfig;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.device.DeviceService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070036import org.onosproject.net.edge.EdgePortService;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.host.HostAdminService;
38import org.onosproject.net.host.HostDescription;
39import org.onosproject.net.host.HostEvent;
40import org.onosproject.net.host.HostListener;
41import org.onosproject.net.host.HostProvider;
42import org.onosproject.net.host.HostProviderRegistry;
43import org.onosproject.net.host.HostProviderService;
44import org.onosproject.net.host.HostService;
45import org.onosproject.net.host.HostStore;
46import org.onosproject.net.host.HostStoreDelegate;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070047import org.onosproject.net.intf.Interface;
48import org.onosproject.net.intf.InterfaceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.packet.PacketService;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070050import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Brian O'Connorabafb502014-12-02 22:26:20 -080051import org.onosproject.net.provider.AbstractProviderService;
soumya3e6f05e2016-08-05 15:11:11 -070052import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070053import org.osgi.service.component.annotations.Activate;
54import org.osgi.service.component.annotations.Component;
55import org.osgi.service.component.annotations.Deactivate;
56import org.osgi.service.component.annotations.Modified;
57import org.osgi.service.component.annotations.Reference;
58import org.osgi.service.component.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070059import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070060
soumya3e6f05e2016-08-05 15:11:11 -070061import java.util.Dictionary;
Rafał Szaleckide5cf842018-11-17 13:30:01 +010062import java.util.Optional;
Simon Huntff663742015-05-14 13:33:05 -070063import java.util.Set;
64
65import static com.google.common.base.Preconditions.checkNotNull;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070066import static com.google.common.base.Preconditions.checkState;
Pier Luigi9b1d6262017-02-02 22:31:34 -080067import static org.onlab.packet.IPv6.getLinkLocalAddress;
Ray Milkeyd04e2272018-10-16 18:20:18 -070068import static org.onosproject.net.OsgiPropertyConstants.HM_ALLOW_DUPLICATE_IPS;
69import static org.onosproject.net.OsgiPropertyConstants.HM_ALLOW_DUPLICATE_IPS_DEFAULT;
70import static org.onosproject.net.OsgiPropertyConstants.HM_GREEDY_LEARNING_IPV6;
71import static org.onosproject.net.OsgiPropertyConstants.HM_GREEDY_LEARNING_IPV6_DEFAULT;
72import static org.onosproject.net.OsgiPropertyConstants.HM_MONITOR_HOSTS;
73import static org.onosproject.net.OsgiPropertyConstants.HM_MONITOR_HOSTS_DEFAULT;
74import static org.onosproject.net.OsgiPropertyConstants.HM_PROBE_RATE;
75import static org.onosproject.net.OsgiPropertyConstants.HM_PROBE_RATE_DEFAULT;
Changhoon Yoon541ef712015-05-23 17:18:34 +090076import static org.onosproject.security.AppGuard.checkPermission;
Simon Huntffbad3b2017-05-16 15:37:51 -070077import static org.onosproject.security.AppPermission.Type.HOST_EVENT;
78import static org.onosproject.security.AppPermission.Type.HOST_READ;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070079import static org.slf4j.LoggerFactory.getLogger;
Simon Huntff663742015-05-14 13:33:05 -070080
tomdb0d03f2014-08-27 16:34:15 -070081/**
82 * Provides basic implementation of the host SB & NB APIs.
83 */
Ray Milkeyd04e2272018-10-16 18:20:18 -070084@Component(
85 immediate = true,
86 service = {
87 HostService.class,
88 HostAdminService.class,
89 HostProviderRegistry.class
90 },
91 property = {
Ray Milkey2d7bca12018-10-17 14:51:52 -070092 HM_ALLOW_DUPLICATE_IPS + ":Boolean=" + HM_ALLOW_DUPLICATE_IPS_DEFAULT,
93 HM_MONITOR_HOSTS + ":Boolean=" + HM_MONITOR_HOSTS_DEFAULT,
94 HM_PROBE_RATE + ":Integer=" + HM_PROBE_RATE_DEFAULT,
95 HM_GREEDY_LEARNING_IPV6 + ":Boolean=" + HM_GREEDY_LEARNING_IPV6_DEFAULT
Ray Milkeyd04e2272018-10-16 18:20:18 -070096 }
97)
tom202175a2014-09-19 19:00:11 -070098public class HostManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070099 extends AbstractListenerProviderRegistry<HostEvent, HostListener, HostProvider, HostProviderService>
tom89b63c52014-09-16 09:19:51 -0700100 implements HostService, HostAdminService, HostProviderRegistry {
tomdb0d03f2014-08-27 16:34:15 -0700101
tom5f38b3a2014-08-27 23:50:54 -0700102 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -0700103
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700104 public static final String HOST_ID_NULL = "Host ID cannot be null";
tom5f38b3a2014-08-27 23:50:54 -0700105
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700106 private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
107
tomc78acee2014-09-24 15:16:55 -0700108 private HostStoreDelegate delegate = new InternalStoreDelegate();
109
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700110 @Reference(cardinality = ReferenceCardinality.MANDATORY)
tom5bcc9462014-09-19 10:11:31 -0700111 protected HostStore store;
tom7869ad92014-09-09 14:32:08 -0700112
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700113 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart70da5122014-10-01 16:37:42 -0700114 protected DeviceService deviceService;
115
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700116 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart70da5122014-10-01 16:37:42 -0700117 protected PacketService packetService;
118
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700119 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700120 protected NetworkConfigService networkConfigService;
121
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700122 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hart4cb39882015-08-12 23:50:55 -0400123 protected InterfaceService interfaceService;
124
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700125 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200126 protected EdgePortService edgePortService;
127
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
soumya3e6f05e2016-08-05 15:11:11 -0700129 protected ComponentConfigService cfgService;
130
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700131 /** Enable removal of duplicate ip address. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700132 private boolean allowDuplicateIps = HM_ALLOW_DUPLICATE_IPS_DEFAULT;
sdn94b00152016-08-30 02:12:32 -0700133
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700134 /** Enable/Disable monitoring of hosts. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700135 private boolean monitorHosts = HM_MONITOR_HOSTS_DEFAULT;
sdn94b00152016-08-30 02:12:32 -0700136
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700137 /** 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
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700140 /** Enable/Disable greedy learning of IPv6 link local address. */
Ray Milkeyd04e2272018-10-16 18:20:18 -0700141 private boolean greedyLearningIpv6 = HM_GREEDY_LEARNING_IPV6_DEFAULT;
Pier Luigi9b1d6262017-02-02 22:31:34 -0800142
Jonathan Hart70da5122014-10-01 16:37:42 -0700143 private HostMonitor monitor;
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100144 private HostAnnotationOperator hostAnnotationOperator;
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) {
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100149 hostAnnotationOperator = new HostAnnotationOperator(networkConfigService);
tomc78acee2014-09-24 15:16:55 -0700150 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -0700151 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
soumya3e6f05e2016-08-05 15:11:11 -0700152 cfgService.registerProperties(getClass());
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700153 networkConfigService.addListener(networkConfigListener);
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200154 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
sdn94b00152016-08-30 02:12:32 -0700155 monitor.setProbeRate(probeRate);
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700156 monitor.start();
sdn94b00152016-08-30 02:12:32 -0700157 modified(context);
158 cfgService.registerProperties(getClass());
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700159 log.info("Started");
tomdb0d03f2014-08-27 16:34:15 -0700160 }
161
sdn94b00152016-08-30 02:12:32 -0700162 @Deactivate
163 public void deactivate() {
164 store.unsetDelegate(delegate);
165 eventDispatcher.removeSink(HostEvent.class);
166 networkConfigService.removeListener(networkConfigListener);
167 cfgService.unregisterProperties(getClass(), false);
168 monitor.shutdown();
169 log.info("Stopped");
170 }
171
soumya3e6f05e2016-08-05 15:11:11 -0700172 @Modified
Simon Huntffbad3b2017-05-16 15:37:51 -0700173 public void modified(ComponentContext context) {
sdn94b00152016-08-30 02:12:32 -0700174 boolean oldValue = monitorHosts;
175 readComponentConfiguration(context);
176 if (probeRate > 0) {
177 monitor.setProbeRate(probeRate);
178 } else {
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700179 log.warn("ProbeRate cannot be less than 0");
sdn94b00152016-08-30 02:12:32 -0700180 }
181
182 if (oldValue != monitorHosts) {
183 if (monitorHosts) {
184 startMonitoring();
185 } else {
186 stopMonitoring();
187 }
188 }
189 }
190
191 /**
192 * Extracts properties from the component configuration context.
193 *
194 * @param context the component context
195 */
196 private void readComponentConfiguration(ComponentContext context) {
soumya3e6f05e2016-08-05 15:11:11 -0700197 Dictionary<?, ?> properties = context.getProperties();
198 Boolean flag;
sdn94b00152016-08-30 02:12:32 -0700199
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700200 flag = Tools.isPropertyEnabled(properties, HM_MONITOR_HOSTS);
sdn94b00152016-08-30 02:12:32 -0700201 if (flag == null) {
202 log.info("monitorHosts is not enabled " +
203 "using current value of {}", monitorHosts);
204 } else {
205 monitorHosts = flag;
206 log.info("Configured. monitorHosts {}",
Simon Huntffbad3b2017-05-16 15:37:51 -0700207 monitorHosts ? "enabled" : "disabled");
sdn94b00152016-08-30 02:12:32 -0700208 }
209
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700210 Long longValue = Tools.getLongProperty(properties, HM_PROBE_RATE);
sdn94b00152016-08-30 02:12:32 -0700211 if (longValue == null || longValue == 0) {
212 log.info("probeRate is not set sing default value of {}", probeRate);
213 } else {
214 probeRate = longValue;
215 log.info("Configured. probeRate {}", probeRate);
216 }
217
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700218 flag = Tools.isPropertyEnabled(properties, HM_ALLOW_DUPLICATE_IPS);
soumya3e6f05e2016-08-05 15:11:11 -0700219 if (flag == null) {
220 log.info("Removal of duplicate ip address is not configured");
221 } else {
222 allowDuplicateIps = flag;
223 log.info("Removal of duplicate ip address is {}",
224 allowDuplicateIps ? "disabled" : "enabled");
225 }
sdn94b00152016-08-30 02:12:32 -0700226
Thomas Vachuskaf566fa22018-10-30 14:03:36 -0700227 flag = Tools.isPropertyEnabled(properties, HM_GREEDY_LEARNING_IPV6);
Pier Luigi9b1d6262017-02-02 22:31:34 -0800228 if (flag == null) {
229 log.info("greedy learning is not enabled " +
230 "using current value of {}", greedyLearningIpv6);
231 } else {
232 greedyLearningIpv6 = flag;
233 log.info("Configured. greedyLearningIpv6 {}",
234 greedyLearningIpv6 ? "enabled" : "disabled");
235 }
236
soumya3e6f05e2016-08-05 15:11:11 -0700237 }
238
sdn94b00152016-08-30 02:12:32 -0700239 /**
240 * Starts monitoring the hosts by IP Address.
sdn94b00152016-08-30 02:12:32 -0700241 */
242 private void startMonitoring() {
243 store.getHosts().forEach(host -> {
Simon Huntffbad3b2017-05-16 15:37:51 -0700244 host.ipAddresses().forEach(ip -> {
245 monitor.addMonitoringFor(ip);
sdn94b00152016-08-30 02:12:32 -0700246 });
247 });
248 }
249
250 /**
251 * Stops monitoring the hosts by IP Address.
sdn94b00152016-08-30 02:12:32 -0700252 */
253 private void stopMonitoring() {
254 store.getHosts().forEach(host -> {
Simon Huntffbad3b2017-05-16 15:37:51 -0700255 host.ipAddresses().forEach(ip -> {
256 monitor.stopMonitoring(ip);
sdn94b00152016-08-30 02:12:32 -0700257 });
258 });
tomdb0d03f2014-08-27 16:34:15 -0700259 }
260
261 @Override
tom5f38b3a2014-08-27 23:50:54 -0700262 protected HostProviderService createProviderService(HostProvider provider) {
Jonathan Hart70da5122014-10-01 16:37:42 -0700263 monitor.registerHostProvider(provider);
tom5f38b3a2014-08-27 23:50:54 -0700264 return new InternalHostProviderService(provider);
tomdb0d03f2014-08-27 16:34:15 -0700265 }
266
tom7869ad92014-09-09 14:32:08 -0700267 @Override
268 public int getHostCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900269 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700270 return store.getHostCount();
271 }
272
273 @Override
274 public Iterable<Host> getHosts() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900275 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700276 return store.getHosts();
277 }
278
279 @Override
280 public Host getHost(HostId hostId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900281 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700282 checkNotNull(hostId, HOST_ID_NULL);
283 return store.getHost(hostId);
284 }
285
286 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700287 public Set<Host> getHostsByVlan(VlanId vlanId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900288 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700289 return store.getHosts(vlanId);
290 }
291
292 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700293 public Set<Host> getHostsByMac(MacAddress mac) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900294 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700295 checkNotNull(mac, "MAC address cannot be null");
296 return store.getHosts(mac);
297 }
298
299 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700300 public Set<Host> getHostsByIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900301 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700302 checkNotNull(ip, "IP address cannot be null");
303 return store.getHosts(ip);
304 }
305
306 @Override
307 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900308 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700309 checkNotNull(connectPoint, "Connection point cannot be null");
310 return store.getConnectedHosts(connectPoint);
311 }
312
313 @Override
314 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900315 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700316 checkNotNull(deviceId, "Device ID cannot be null");
317 return store.getConnectedHosts(deviceId);
318 }
319
320 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700321 public void startMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900322 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700323 monitor.addMonitoringFor(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700324 }
325
326 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700327 public void stopMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900328 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700329 monitor.stopMonitoring(ip);
Jonathan Hartac60c082014-09-23 08:55:17 -0700330 }
331
332 @Override
333 public void requestMac(IpAddress ip) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700334 // FIXME!!!! Auto-generated method stub
tom7869ad92014-09-09 14:32:08 -0700335 }
336
tom89b63c52014-09-16 09:19:51 -0700337 @Override
338 public void removeHost(HostId hostId) {
339 checkNotNull(hostId, HOST_ID_NULL);
Charles Chan009c3082015-11-10 14:18:04 -0800340 store.removeHost(hostId);
tom89b63c52014-09-16 09:19:51 -0700341 }
342
tomdb0d03f2014-08-27 16:34:15 -0700343 // Personalized host provider service issued to the supplied provider.
tom7869ad92014-09-09 14:32:08 -0700344 private class InternalHostProviderService
345 extends AbstractProviderService<HostProvider>
tomdb0d03f2014-08-27 16:34:15 -0700346 implements HostProviderService {
tomcfde0622014-09-09 11:02:42 -0700347 InternalHostProviderService(HostProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700348 super(provider);
349 }
350
351 @Override
Ray Milkey718e4382018-12-05 09:08:01 -0800352 public void hostDetected(HostId hostId, HostDescription initialHostDescription, boolean replaceIps) {
353 HostDescription hostDescription = initialHostDescription;
tom7869ad92014-09-09 14:32:08 -0700354 checkNotNull(hostId, HOST_ID_NULL);
355 checkValidity();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700356 hostDescription = validateHost(hostDescription, hostId);
soumya3e6f05e2016-08-05 15:11:11 -0700357
358 if (!allowDuplicateIps) {
359 removeDuplicates(hostId, hostDescription);
360 }
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100361
362 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
363 if (!isAllowed(cfg)) {
364 log.warn("Host {} is not allowed to be added into the contol domain", hostId);
365 return;
366 }
367
Ray Milkey718e4382018-12-05 09:08:01 -0800368 hostDescription = BasicHostOperator.combine(cfg, initialHostDescription);
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100369 HostAnnotationConfig annoConfig = networkConfigService.getConfig(hostId, HostAnnotationConfig.class);
370 if (annoConfig != null) {
371 hostDescription = hostAnnotationOperator.combine(hostId, hostDescription, Optional.of(annoConfig));
372 }
373
Charles Chan009c3082015-11-10 14:18:04 -0800374 store.createOrUpdateHost(provider().id(), hostId,
soumya3e6f05e2016-08-05 15:11:11 -0700375 hostDescription, replaceIps);
sdn94b00152016-08-30 02:12:32 -0700376
377 if (monitorHosts) {
378 hostDescription.ipAddress().forEach(ip -> {
379 monitor.addMonitoringFor(ip);
380 });
381 }
Pier Luigi9b1d6262017-02-02 22:31:34 -0800382
383 // Greedy learning of IPv6 host. We have to disable the greedy
384 // learning of configured hosts. Validate hosts each time will
Charles Chan82fac582017-09-12 12:09:22 -0700385 // overwrite the learnt information with the configured information.
Pier Luigi9b1d6262017-02-02 22:31:34 -0800386 if (greedyLearningIpv6) {
387 // Auto-generation of the IPv6 link local address
388 // using the mac address
389 Ip6Address targetIp6Address = Ip6Address.valueOf(
390 getLinkLocalAddress(hostId.mac().toBytes())
391 );
392 // If we already know this guy we don't need to do other
393 if (!hostDescription.ipAddress().contains(targetIp6Address)) {
394 Host host = store.getHost(hostId);
395 // Configured host, skip it.
396 if (host != null && host.configured()) {
397 return;
398 }
399 // Host does not exist in the store or the target is not known
400 if ((host == null || !host.ipAddresses().contains(targetIp6Address))) {
Charles Chan82fac582017-09-12 12:09:22 -0700401 // Use DAD to probe if interface MAC is not specified
402 MacAddress probeMac = interfaceService.getInterfacesByPort(hostDescription.location())
403 .stream().map(Interface::mac).findFirst().orElse(MacAddress.ONOS);
404 Ip6Address probeIp = !probeMac.equals(MacAddress.ONOS) ?
405 Ip6Address.valueOf(getLinkLocalAddress(probeMac.toBytes())) :
406 Ip6Address.ZERO;
Pier Luigi9b1d6262017-02-02 22:31:34 -0800407 // We send a probe using the monitoring service
408 monitor.sendProbe(
409 hostDescription.location(),
410 targetIp6Address,
Charles Chan82fac582017-09-12 12:09:22 -0700411 probeIp,
412 probeMac,
Pier Luigi9b1d6262017-02-02 22:31:34 -0800413 hostId.vlanId()
414 );
415 }
416 }
417 }
tomdb0d03f2014-08-27 16:34:15 -0700418 }
419
soumya3e6f05e2016-08-05 15:11:11 -0700420 // When a new IP is detected, remove that IP on other hosts if it exists
421 public void removeDuplicates(HostId hostId, HostDescription desc) {
422 desc.ipAddress().forEach(ip -> {
423 Set<Host> allHosts = store.getHosts(ip);
424 allHosts.forEach(eachHost -> {
425 if (!(eachHost.id().equals(hostId))) {
426 log.info("Duplicate ip {} found on host {} and {}", ip,
427 hostId.toString(), eachHost.id().toString());
428 store.removeIp(eachHost.id(), ip);
429 }
430 });
431 });
Jonathan Hart38feb6e2016-08-29 22:54:16 +0000432 }
433
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700434 // returns a HostDescription made from the union of the BasicHostConfig
435 // annotations if it exists
436 private HostDescription validateHost(HostDescription hostDescription, HostId hostId) {
437 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
438 checkState(cfg == null || cfg.isAllowed(), "Host {} is not allowed", hostId);
Ayaka Koshibe5373e762015-08-06 12:31:44 -0700439
440 return BasicHostOperator.combine(cfg, hostDescription);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700441 }
442
tomdb0d03f2014-08-27 16:34:15 -0700443 @Override
tom7869ad92014-09-09 14:32:08 -0700444 public void hostVanished(HostId hostId) {
445 checkNotNull(hostId, HOST_ID_NULL);
446 checkValidity();
sdn94b00152016-08-30 02:12:32 -0700447 Host host = store.getHost(hostId);
Charles Chan29ecdee2017-02-22 18:46:56 -0800448
Charles Chan888e20a2017-05-01 15:44:23 -0700449 if (!allowedToChange(hostId)) {
450 log.info("Request to remove {} is ignored due to provider mismatch", hostId);
Charles Chan29ecdee2017-02-22 18:46:56 -0800451 return;
452 }
453
sdn94b00152016-08-30 02:12:32 -0700454 if (monitorHosts) {
455 host.ipAddresses().forEach(ip -> {
456 monitor.stopMonitoring(ip);
457 });
458 }
Charles Chan009c3082015-11-10 14:18:04 -0800459 store.removeHost(hostId);
tomdb0d03f2014-08-27 16:34:15 -0700460 }
samanwita palc40e5ed2015-09-24 11:01:51 -0700461
462 @Override
463 public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
464 checkNotNull(hostId, HOST_ID_NULL);
465 checkValidity();
Charles Chan888e20a2017-05-01 15:44:23 -0700466
467 if (!allowedToChange(hostId)) {
468 log.info("Request to remove {} from {} is ignored due to provider mismatch",
469 ipAddress, hostId);
470 return;
471 }
472
Charles Chan009c3082015-11-10 14:18:04 -0800473 store.removeIp(hostId, ipAddress);
samanwita palc40e5ed2015-09-24 11:01:51 -0700474 }
Charles Chan888e20a2017-05-01 15:44:23 -0700475
476 @Override
Charles Chanff79dd92018-06-01 16:33:48 -0700477 public void addLocationToHost(HostId hostId, HostLocation location) {
478 checkNotNull(hostId, HOST_ID_NULL);
479 checkValidity();
480
481 if (!allowedToChange(hostId)) {
Charles Chanb928b3f2018-07-23 15:37:08 -0700482 log.info("Request to add {} to {} is ignored due to provider mismatch",
Charles Chanff79dd92018-06-01 16:33:48 -0700483 location, hostId);
484 return;
485 }
486
487 store.appendLocation(hostId, location);
488 }
489
490 @Override
Charles Chan888e20a2017-05-01 15:44:23 -0700491 public void removeLocationFromHost(HostId hostId, HostLocation location) {
492 checkNotNull(hostId, HOST_ID_NULL);
493 checkValidity();
494
495 if (!allowedToChange(hostId)) {
496 log.info("Request to remove {} from {} is ignored due to provider mismatch",
497 location, hostId);
498 return;
499 }
500
501 store.removeLocation(hostId, location);
502 }
503
Charles Chand0c147a2017-09-14 14:00:10 -0700504 /**
505 * Providers should only be able to remove a host that is provided by itself,
506 * or a host that is not configured.
507 */
Charles Chan888e20a2017-05-01 15:44:23 -0700508 private boolean allowedToChange(HostId hostId) {
Charles Chan888e20a2017-05-01 15:44:23 -0700509 Host host = store.getHost(hostId);
Charles Chand0c147a2017-09-14 14:00:10 -0700510 return host == null || !host.configured() || host.providerId().equals(provider().id());
Charles Chan888e20a2017-05-01 15:44:23 -0700511 }
tomdb0d03f2014-08-27 16:34:15 -0700512 }
tom7869ad92014-09-09 14:32:08 -0700513
tomc78acee2014-09-24 15:16:55 -0700514 // Store delegate to re-post events emitted from the store.
515 private class InternalStoreDelegate implements HostStoreDelegate {
516 @Override
517 public void notify(HostEvent event) {
518 post(event);
519 }
520 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700521
522 // listens for NetworkConfigEvents of type BasicHostConfig and removes
523 // links that the config does not allow
524 private class InternalNetworkConfigListener implements NetworkConfigListener {
525 @Override
Simon Huntffbad3b2017-05-16 15:37:51 -0700526 public boolean isRelevant(NetworkConfigEvent event) {
527 return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
528 || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100529 && (event.configClass().equals(BasicHostConfig.class)
530 || event.configClass().equals(HostAnnotationConfig.class));
Simon Huntffbad3b2017-05-16 15:37:51 -0700531 }
532
533 @Override
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700534 public void event(NetworkConfigEvent event) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700535 log.debug("Detected host network config event {}", event.type());
536 HostEvent he = null;
537
538 HostId hostId = (HostId) event.subject();
539 BasicHostConfig cfg =
540 networkConfigService.getConfig(hostId, BasicHostConfig.class);
541
542 if (!isAllowed(cfg)) {
543 kickOutBadHost(hostId);
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100544 } else if (event.configClass().equals(BasicHostConfig.class)) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700545 Host host = getHost(hostId);
546 HostDescription desc =
547 (host == null) ? null : BasicHostOperator.descriptionOf(host);
548 desc = BasicHostOperator.combine(cfg, desc);
549 if (desc != null) {
550 he = store.createOrUpdateHost(host.providerId(), hostId, desc, false);
551 }
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100552 } else if (event.configClass().equals(HostAnnotationConfig.class)) {
553 Host host = getHost(hostId);
Ray Milkey718e4382018-12-05 09:08:01 -0800554 HostProvider hp = (host == null) ? null : getProvider(host.providerId());
Rafał Szaleckide5cf842018-11-17 13:30:01 +0100555 HostDescription desc = (host == null) ? null : BasicHostOperator.descriptionOf(host);
556 Optional<Config> prevConfig = event.prevConfig();
557 log.debug("Host annotations: {} prevconfig {} desc {}", hostId, prevConfig, desc);
558 desc = hostAnnotationOperator.combine(hostId, desc, prevConfig);
559 if (desc != null && hp != null) {
560 log.debug("Host annotations update - updated host description :{}", desc.toString());
561 he = store.createOrUpdateHost(hp.id(), hostId, desc, false);
562 if (he != null && he.subject() != null) {
563 log.debug("Host annotations update - Host Event : {}", he.subject().annotations());
564 }
565 }
Simon Huntffbad3b2017-05-16 15:37:51 -0700566 }
567
568 if (he != null) {
569 post(he);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700570 }
571 }
572 }
573
Simon Huntffbad3b2017-05-16 15:37:51 -0700574 // by default allowed, otherwise check flag
575 private boolean isAllowed(BasicHostConfig cfg) {
576 return (cfg == null || cfg.isAllowed());
577 }
578
579 // removes the specified host, if it exists
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700580 private void kickOutBadHost(HostId hostId) {
Simon Huntffbad3b2017-05-16 15:37:51 -0700581 Host badHost = getHost(hostId);
582 if (badHost != null) {
583 removeHost(hostId);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700584 }
585 }
tomdb0d03f2014-08-27 16:34:15 -0700586}