blob: 27b9b7af72a9f5b8fba58132439ba696dd285c81 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
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
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
soumya3e6f05e2016-08-05 15:11:11 -070021import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
tom5f38b3a2014-08-27 23:50:54 -070023import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070025import org.apache.felix.scr.annotations.Service;
Simon Huntff663742015-05-14 13:33:05 -070026import org.onlab.packet.IpAddress;
27import org.onlab.packet.MacAddress;
28import org.onlab.packet.VlanId;
soumya3e6f05e2016-08-05 15:11:11 -070029import org.onlab.util.Tools;
30import org.onosproject.cfg.ComponentConfigService;
Jonathan Hart4cb39882015-08-12 23:50:55 -040031import org.onosproject.incubator.net.intf.InterfaceService;
Jonathan Hartfb32a6e2015-09-01 12:12:14 +020032import org.onosproject.net.edge.EdgePortService;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070033import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Ray Milkeya4122362015-08-18 15:19:08 -070034import org.onosproject.net.config.NetworkConfigEvent;
35import org.onosproject.net.config.NetworkConfigListener;
36import org.onosproject.net.config.NetworkConfigService;
Thomas Vachuska4998caa2015-08-26 13:28:38 -070037import org.onosproject.net.config.basics.BasicHostConfig;
Brian O'Connorabafb502014-12-02 22:26:20 -080038import org.onosproject.net.ConnectPoint;
39import org.onosproject.net.DeviceId;
40import org.onosproject.net.Host;
41import org.onosproject.net.HostId;
42import org.onosproject.net.device.DeviceService;
43import org.onosproject.net.host.HostAdminService;
44import org.onosproject.net.host.HostDescription;
45import org.onosproject.net.host.HostEvent;
46import org.onosproject.net.host.HostListener;
47import org.onosproject.net.host.HostProvider;
48import org.onosproject.net.host.HostProviderRegistry;
49import org.onosproject.net.host.HostProviderService;
50import org.onosproject.net.host.HostService;
51import org.onosproject.net.host.HostStore;
52import org.onosproject.net.host.HostStoreDelegate;
Brian O'Connorabafb502014-12-02 22:26:20 -080053import org.onosproject.net.packet.PacketService;
Brian O'Connorabafb502014-12-02 22:26:20 -080054import org.onosproject.net.provider.AbstractProviderService;
soumya3e6f05e2016-08-05 15:11:11 -070055import org.osgi.service.component.ComponentContext;
tomdb0d03f2014-08-27 16:34:15 -070056import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070057
soumya3e6f05e2016-08-05 15:11:11 -070058import java.util.Dictionary;
Simon Huntff663742015-05-14 13:33:05 -070059import java.util.Set;
60
61import static com.google.common.base.Preconditions.checkNotNull;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070062import static com.google.common.base.Preconditions.checkState;
Changhoon Yoon541ef712015-05-23 17:18:34 +090063import static org.onosproject.security.AppGuard.checkPermission;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070064import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoonb856b812015-08-10 03:47:19 +090065import static org.onosproject.security.AppPermission.Type.*;
Simon Huntff663742015-05-14 13:33:05 -070066
tomdb0d03f2014-08-27 16:34:15 -070067/**
68 * Provides basic implementation of the host SB & NB APIs.
69 */
70@Component(immediate = true)
71@Service
tom202175a2014-09-19 19:00:11 -070072public class HostManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070073 extends AbstractListenerProviderRegistry<HostEvent, HostListener, HostProvider, HostProviderService>
tom89b63c52014-09-16 09:19:51 -070074 implements HostService, HostAdminService, HostProviderRegistry {
tomdb0d03f2014-08-27 16:34:15 -070075
tom5f38b3a2014-08-27 23:50:54 -070076 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -070077
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070078 public static final String HOST_ID_NULL = "Host ID cannot be null";
tom5f38b3a2014-08-27 23:50:54 -070079
Sahil Lele3a0cdd52015-07-21 14:16:31 -070080 private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
81
tomc78acee2014-09-24 15:16:55 -070082 private HostStoreDelegate delegate = new InternalStoreDelegate();
83
tom5bcc9462014-09-19 10:11:31 -070084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected HostStore store;
tom7869ad92014-09-09 14:32:08 -070086
tom5f38b3a2014-08-27 23:50:54 -070087 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jonathan Hart70da5122014-10-01 16:37:42 -070088 protected DeviceService deviceService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected PacketService packetService;
92
Sahil Lele3a0cdd52015-07-21 14:16:31 -070093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected NetworkConfigService networkConfigService;
95
Jonathan Hart4cb39882015-08-12 23:50:55 -040096 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected InterfaceService interfaceService;
98
Jonathan Hartfb32a6e2015-09-01 12:12:14 +020099 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected EdgePortService edgePortService;
101
soumya3e6f05e2016-08-05 15:11:11 -0700102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected ComponentConfigService cfgService;
104
105 @Property(name = "allowDuplicateIps", boolValue = true,
106 label = "Enable removal of duplicate ip address")
107
108 private boolean allowDuplicateIps = true;
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530109
110 @Property(name = "monitorHosts", boolValue = false,
111 label = "Enable/Disable monitoring of hosts")
112 private boolean monitorHosts = false;
113
114 @Property(name = "probeRate", longValue = 30000,
115 label = "Set the probe Rate in milli seconds")
116 private long probeRate = 30000;
117
Jonathan Hart70da5122014-10-01 16:37:42 -0700118 private HostMonitor monitor;
tomdb0d03f2014-08-27 16:34:15 -0700119
soumya3e6f05e2016-08-05 15:11:11 -0700120
tomdb0d03f2014-08-27 16:34:15 -0700121 @Activate
soumya3e6f05e2016-08-05 15:11:11 -0700122 public void activate(ComponentContext context) {
tomc78acee2014-09-24 15:16:55 -0700123 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -0700124 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
soumya3e6f05e2016-08-05 15:11:11 -0700125 cfgService.registerProperties(getClass());
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700126 networkConfigService.addListener(networkConfigListener);
Jonathan Hartfb32a6e2015-09-01 12:12:14 +0200127 monitor = new HostMonitor(packetService, this, interfaceService, edgePortService);
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530128 monitor.setProbeRate(probeRate);
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700129 monitor.start();
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530130 modified(context);
131 cfgService.registerProperties(getClass());
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700132 log.info("Started");
tomdb0d03f2014-08-27 16:34:15 -0700133 }
134
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530135 @Deactivate
136 public void deactivate() {
137 store.unsetDelegate(delegate);
138 eventDispatcher.removeSink(HostEvent.class);
139 networkConfigService.removeListener(networkConfigListener);
140 cfgService.unregisterProperties(getClass(), false);
141 monitor.shutdown();
142 log.info("Stopped");
143 }
144
soumya3e6f05e2016-08-05 15:11:11 -0700145 @Modified
146 public void modified(ComponentContext context) {
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530147 boolean oldValue = monitorHosts;
148 readComponentConfiguration(context);
149 if (probeRate > 0) {
150 monitor.setProbeRate(probeRate);
151 } else {
152 log.warn("probeRate cannot be lessthan 0");
153 }
154
155 if (oldValue != monitorHosts) {
156 if (monitorHosts) {
157 startMonitoring();
158 } else {
159 stopMonitoring();
160 }
161 }
162 }
163
164 /**
165 * Extracts properties from the component configuration context.
166 *
167 * @param context the component context
168 */
169 private void readComponentConfiguration(ComponentContext context) {
soumya3e6f05e2016-08-05 15:11:11 -0700170 Dictionary<?, ?> properties = context.getProperties();
171 Boolean flag;
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530172
173 flag = Tools.isPropertyEnabled(properties, "monitorHosts");
174 if (flag == null) {
175 log.info("monitorHosts is not enabled " +
176 "using current value of {}", monitorHosts);
177 } else {
178 monitorHosts = flag;
179 log.info("Configured. monitorHosts {}",
180 monitorHosts ? "enabled" : "disabled");
181 }
182
183 Long longValue = Tools.getLongProperty(properties, "probeRate");
184 if (longValue == null || longValue == 0) {
185 log.info("probeRate is not set sing default value of {}", probeRate);
186 } else {
187 probeRate = longValue;
188 log.info("Configured. probeRate {}", probeRate);
189 }
190
soumya3e6f05e2016-08-05 15:11:11 -0700191 flag = Tools.isPropertyEnabled(properties, "allowDuplicateIps");
192 if (flag == null) {
193 log.info("Removal of duplicate ip address is not configured");
194 } else {
195 allowDuplicateIps = flag;
196 log.info("Removal of duplicate ip address is {}",
197 allowDuplicateIps ? "disabled" : "enabled");
198 }
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530199
200
soumya3e6f05e2016-08-05 15:11:11 -0700201 }
202
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530203 /**
204 * Starts monitoring the hosts by IP Address.
205 *
206 */
207 private void startMonitoring() {
208 store.getHosts().forEach(host -> {
209 host.ipAddresses().forEach(ip -> {
210 monitor.addMonitoringFor(ip);
211 });
212 });
213 }
214
215 /**
216 * Stops monitoring the hosts by IP Address.
217 *
218 */
219 private void stopMonitoring() {
220 store.getHosts().forEach(host -> {
221 host.ipAddresses().forEach(ip -> {
222 monitor.stopMonitoring(ip);
223 });
224 });
tomdb0d03f2014-08-27 16:34:15 -0700225 }
226
227 @Override
tom5f38b3a2014-08-27 23:50:54 -0700228 protected HostProviderService createProviderService(HostProvider provider) {
Jonathan Hart70da5122014-10-01 16:37:42 -0700229 monitor.registerHostProvider(provider);
tom5f38b3a2014-08-27 23:50:54 -0700230 return new InternalHostProviderService(provider);
tomdb0d03f2014-08-27 16:34:15 -0700231 }
232
tom7869ad92014-09-09 14:32:08 -0700233 @Override
234 public int getHostCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900235 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700236 return store.getHostCount();
237 }
238
239 @Override
240 public Iterable<Host> getHosts() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900241 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700242 return store.getHosts();
243 }
244
245 @Override
246 public Host getHost(HostId hostId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900247 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700248 checkNotNull(hostId, HOST_ID_NULL);
249 return store.getHost(hostId);
250 }
251
252 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700253 public Set<Host> getHostsByVlan(VlanId vlanId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900254 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700255 return store.getHosts(vlanId);
256 }
257
258 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700259 public Set<Host> getHostsByMac(MacAddress mac) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900260 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700261 checkNotNull(mac, "MAC address cannot be null");
262 return store.getHosts(mac);
263 }
264
265 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700266 public Set<Host> getHostsByIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900267 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700268 checkNotNull(ip, "IP address cannot be null");
269 return store.getHosts(ip);
270 }
271
272 @Override
273 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900274 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700275 checkNotNull(connectPoint, "Connection point cannot be null");
276 return store.getConnectedHosts(connectPoint);
277 }
278
279 @Override
280 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900281 checkPermission(HOST_READ);
tom7869ad92014-09-09 14:32:08 -0700282 checkNotNull(deviceId, "Device ID cannot be null");
283 return store.getConnectedHosts(deviceId);
284 }
285
286 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700287 public void startMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900288 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700289 monitor.addMonitoringFor(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700290 }
291
292 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700293 public void stopMonitoringIp(IpAddress ip) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900294 checkPermission(HOST_EVENT);
Jonathan Hart70da5122014-10-01 16:37:42 -0700295 monitor.stopMonitoring(ip);
Jonathan Hartac60c082014-09-23 08:55:17 -0700296 }
297
298 @Override
299 public void requestMac(IpAddress ip) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700300 // FIXME!!!! Auto-generated method stub
tom7869ad92014-09-09 14:32:08 -0700301 }
302
tom89b63c52014-09-16 09:19:51 -0700303 @Override
304 public void removeHost(HostId hostId) {
305 checkNotNull(hostId, HOST_ID_NULL);
Charles Chan009c3082015-11-10 14:18:04 -0800306 store.removeHost(hostId);
tom89b63c52014-09-16 09:19:51 -0700307 }
308
tomdb0d03f2014-08-27 16:34:15 -0700309 // Personalized host provider service issued to the supplied provider.
tom7869ad92014-09-09 14:32:08 -0700310 private class InternalHostProviderService
311 extends AbstractProviderService<HostProvider>
tomdb0d03f2014-08-27 16:34:15 -0700312 implements HostProviderService {
tomcfde0622014-09-09 11:02:42 -0700313 InternalHostProviderService(HostProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700314 super(provider);
315 }
316
317 @Override
Brian O'Connorf107bd72015-09-21 15:31:03 -0700318 public void hostDetected(HostId hostId, HostDescription hostDescription, boolean replaceIps) {
tom7869ad92014-09-09 14:32:08 -0700319 checkNotNull(hostId, HOST_ID_NULL);
320 checkValidity();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700321 hostDescription = validateHost(hostDescription, hostId);
soumya3e6f05e2016-08-05 15:11:11 -0700322
323 if (!allowDuplicateIps) {
324 removeDuplicates(hostId, hostDescription);
325 }
Charles Chan009c3082015-11-10 14:18:04 -0800326 store.createOrUpdateHost(provider().id(), hostId,
soumya3e6f05e2016-08-05 15:11:11 -0700327 hostDescription, replaceIps);
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530328
329 if (monitorHosts) {
330 hostDescription.ipAddress().forEach(ip -> {
331 monitor.addMonitoringFor(ip);
332 });
333 }
tomdb0d03f2014-08-27 16:34:15 -0700334 }
335
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530336
soumya3e6f05e2016-08-05 15:11:11 -0700337 // When a new IP is detected, remove that IP on other hosts if it exists
338 public void removeDuplicates(HostId hostId, HostDescription desc) {
339 desc.ipAddress().forEach(ip -> {
340 Set<Host> allHosts = store.getHosts(ip);
341 allHosts.forEach(eachHost -> {
342 if (!(eachHost.id().equals(hostId))) {
343 log.info("Duplicate ip {} found on host {} and {}", ip,
344 hostId.toString(), eachHost.id().toString());
345 store.removeIp(eachHost.id(), ip);
346 }
347 });
348 });
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530349 }
soumya3e6f05e2016-08-05 15:11:11 -0700350
351
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700352 // returns a HostDescription made from the union of the BasicHostConfig
353 // annotations if it exists
354 private HostDescription validateHost(HostDescription hostDescription, HostId hostId) {
355 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
356 checkState(cfg == null || cfg.isAllowed(), "Host {} is not allowed", hostId);
Ayaka Koshibe5373e762015-08-06 12:31:44 -0700357
358 return BasicHostOperator.combine(cfg, hostDescription);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700359 }
360
tomdb0d03f2014-08-27 16:34:15 -0700361 @Override
tom7869ad92014-09-09 14:32:08 -0700362 public void hostVanished(HostId hostId) {
363 checkNotNull(hostId, HOST_ID_NULL);
364 checkValidity();
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530365 Host host = store.getHost(hostId);
366 if (monitorHosts) {
367 host.ipAddresses().forEach(ip -> {
368 monitor.stopMonitoring(ip);
369 });
370 }
Charles Chan009c3082015-11-10 14:18:04 -0800371 store.removeHost(hostId);
tomdb0d03f2014-08-27 16:34:15 -0700372 }
samanwita palc40e5ed2015-09-24 11:01:51 -0700373
374 @Override
375 public void removeIpFromHost(HostId hostId, IpAddress ipAddress) {
376 checkNotNull(hostId, HOST_ID_NULL);
377 checkValidity();
Charles Chan009c3082015-11-10 14:18:04 -0800378 store.removeIp(hostId, ipAddress);
samanwita palc40e5ed2015-09-24 11:01:51 -0700379 }
tomdb0d03f2014-08-27 16:34:15 -0700380 }
tom7869ad92014-09-09 14:32:08 -0700381
tomc78acee2014-09-24 15:16:55 -0700382 // Store delegate to re-post events emitted from the store.
383 private class InternalStoreDelegate implements HostStoreDelegate {
384 @Override
385 public void notify(HostEvent event) {
386 post(event);
387 }
388 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700389
390 // listens for NetworkConfigEvents of type BasicHostConfig and removes
391 // links that the config does not allow
392 private class InternalNetworkConfigListener implements NetworkConfigListener {
393 @Override
394 public void event(NetworkConfigEvent event) {
395 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
396 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
397 event.configClass().equals(BasicHostConfig.class)) {
Thomas Vachuska138de8b2016-01-11 21:31:38 -0800398 log.debug("Detected host network config event {}", event.type());
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700399 kickOutBadHost(((HostId) event.subject()));
400 }
401 }
402 }
403
404 // checks if the specified host is allowed by the BasicHostConfig
405 // and if not, removes it
406 private void kickOutBadHost(HostId hostId) {
407 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
408 if (cfg != null && !cfg.isAllowed()) {
409 Host badHost = getHost(hostId);
410 if (badHost != null) {
411 removeHost(hostId);
412 } else {
413 log.info("Failed removal: Host {} does not exist", hostId);
414 }
415 }
416 }
tomdb0d03f2014-08-27 16:34:15 -0700417}
Deepa Vaddireddy50ad0802016-08-08 19:27:36 +0530418