blob: d36db84b569af7b2de38087b8e95662013496520 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
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;
tom5f38b3a2014-08-27 23:50:54 -070021import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070023import org.apache.felix.scr.annotations.Service;
Simon Huntff663742015-05-14 13:33:05 -070024import org.onlab.packet.IpAddress;
25import org.onlab.packet.MacAddress;
26import org.onlab.packet.VlanId;
Changhoon Yoon541ef712015-05-23 17:18:34 +090027import org.onosproject.core.Permission;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.event.EventDeliveryService;
Simon Huntff663742015-05-14 13:33:05 -070029import org.onosproject.event.ListenerRegistry;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070030import org.onosproject.incubator.net.config.NetworkConfigEvent;
31import org.onosproject.incubator.net.config.NetworkConfigListener;
32import org.onosproject.incubator.net.config.NetworkConfigService;
33import org.onosproject.incubator.net.config.basics.BasicHostConfig;
Brian O'Connorabafb502014-12-02 22:26:20 -080034import org.onosproject.net.ConnectPoint;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070035import org.onosproject.net.DefaultAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.DeviceId;
37import org.onosproject.net.Host;
38import org.onosproject.net.HostId;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070039import org.onosproject.net.SparseAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.device.DeviceService;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070041import org.onosproject.net.host.DefaultHostDescription;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.host.HostAdminService;
43import org.onosproject.net.host.HostDescription;
44import org.onosproject.net.host.HostEvent;
45import org.onosproject.net.host.HostListener;
46import org.onosproject.net.host.HostProvider;
47import org.onosproject.net.host.HostProviderRegistry;
48import org.onosproject.net.host.HostProviderService;
49import org.onosproject.net.host.HostService;
50import org.onosproject.net.host.HostStore;
51import org.onosproject.net.host.HostStoreDelegate;
52import org.onosproject.net.host.PortAddresses;
53import org.onosproject.net.packet.PacketService;
54import org.onosproject.net.provider.AbstractProviderRegistry;
55import org.onosproject.net.provider.AbstractProviderService;
tomdb0d03f2014-08-27 16:34:15 -070056import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070057
Simon Huntff663742015-05-14 13:33:05 -070058import java.util.Set;
59
60import static com.google.common.base.Preconditions.checkNotNull;
Sahil Lele3a0cdd52015-07-21 14:16:31 -070061import static com.google.common.base.Preconditions.checkState;
Simon Huntff663742015-05-14 13:33:05 -070062import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoon541ef712015-05-23 17:18:34 +090063import static org.onosproject.security.AppGuard.checkPermission;
64
Simon Huntff663742015-05-14 13:33:05 -070065
tomdb0d03f2014-08-27 16:34:15 -070066/**
67 * Provides basic implementation of the host SB & NB APIs.
68 */
69@Component(immediate = true)
70@Service
tom202175a2014-09-19 19:00:11 -070071public class HostManager
tom96dfcab2014-08-28 09:26:03 -070072 extends AbstractProviderRegistry<HostProvider, HostProviderService>
tom89b63c52014-09-16 09:19:51 -070073 implements HostService, HostAdminService, HostProviderRegistry {
tomdb0d03f2014-08-27 16:34:15 -070074
tom7869ad92014-09-09 14:32:08 -070075 public static final String HOST_ID_NULL = "Host ID cannot be null";
tom5f38b3a2014-08-27 23:50:54 -070076 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -070077
Simon Huntff663742015-05-14 13:33:05 -070078 private final ListenerRegistry<HostEvent, HostListener>
79 listenerRegistry = new ListenerRegistry<>();
tom5f38b3a2014-08-27 23:50:54 -070080
Sahil Lele3a0cdd52015-07-21 14:16:31 -070081 private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
82
tomc78acee2014-09-24 15:16:55 -070083 private HostStoreDelegate delegate = new InternalStoreDelegate();
84
tom5bcc9462014-09-19 10:11:31 -070085 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected HostStore store;
tom7869ad92014-09-09 14:32:08 -070087
tom5f38b3a2014-08-27 23:50:54 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibeac8e7292014-09-16 16:08:31 -070089 protected EventDeliveryService eventDispatcher;
tom5f38b3a2014-08-27 23:50:54 -070090
Jonathan Hart70da5122014-10-01 16:37:42 -070091 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected DeviceService deviceService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected PacketService packetService;
96
Sahil Lele3a0cdd52015-07-21 14:16:31 -070097 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected NetworkConfigService networkConfigService;
99
Jonathan Hart70da5122014-10-01 16:37:42 -0700100 private HostMonitor monitor;
tomdb0d03f2014-08-27 16:34:15 -0700101
102 @Activate
103 public void activate() {
Jonathan Hart70da5122014-10-01 16:37:42 -0700104 log.info("Started");
tomc78acee2014-09-24 15:16:55 -0700105 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -0700106 eventDispatcher.addSink(HostEvent.class, listenerRegistry);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700107 networkConfigService.addListener(networkConfigListener);
Jonathan Hart70da5122014-10-01 16:37:42 -0700108 monitor = new HostMonitor(deviceService, packetService, this);
Jonathan Hart8f6f1ea2014-10-03 16:05:19 -0700109 monitor.start();
tomdb0d03f2014-08-27 16:34:15 -0700110 }
111
112 @Deactivate
113 public void deactivate() {
tomc78acee2014-09-24 15:16:55 -0700114 store.unsetDelegate(delegate);
tom5f38b3a2014-08-27 23:50:54 -0700115 eventDispatcher.removeSink(HostEvent.class);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700116 networkConfigService.removeListener(networkConfigListener);
tomdb0d03f2014-08-27 16:34:15 -0700117 log.info("Stopped");
118 }
119
120 @Override
tom5f38b3a2014-08-27 23:50:54 -0700121 protected HostProviderService createProviderService(HostProvider provider) {
Jonathan Hart70da5122014-10-01 16:37:42 -0700122 monitor.registerHostProvider(provider);
123
tom5f38b3a2014-08-27 23:50:54 -0700124 return new InternalHostProviderService(provider);
tomdb0d03f2014-08-27 16:34:15 -0700125 }
126
tom7869ad92014-09-09 14:32:08 -0700127 @Override
128 public int getHostCount() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900129 checkPermission(Permission.HOST_READ);
130
tom7869ad92014-09-09 14:32:08 -0700131 return store.getHostCount();
132 }
133
134 @Override
135 public Iterable<Host> getHosts() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900136 checkPermission(Permission.HOST_READ);
137
tom7869ad92014-09-09 14:32:08 -0700138 return store.getHosts();
139 }
140
141 @Override
142 public Host getHost(HostId hostId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900143 checkPermission(Permission.HOST_READ);
144
tom7869ad92014-09-09 14:32:08 -0700145 checkNotNull(hostId, HOST_ID_NULL);
146 return store.getHost(hostId);
147 }
148
149 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700150 public Set<Host> getHostsByVlan(VlanId vlanId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900151 checkPermission(Permission.HOST_READ);
152
tom7869ad92014-09-09 14:32:08 -0700153 return store.getHosts(vlanId);
154 }
155
156 @Override
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700157 public Set<Host> getHostsByMac(MacAddress mac) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900158 checkPermission(Permission.HOST_READ);
159
tom7869ad92014-09-09 14:32:08 -0700160 checkNotNull(mac, "MAC address cannot be null");
161 return store.getHosts(mac);
162 }
163
164 @Override
Pavlin Radoslavov33f228a2014-10-27 19:33:16 -0700165 public Set<Host> getHostsByIp(IpAddress ip) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900166 checkPermission(Permission.HOST_READ);
167
tom7869ad92014-09-09 14:32:08 -0700168 checkNotNull(ip, "IP address cannot be null");
169 return store.getHosts(ip);
170 }
171
172 @Override
173 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900174 checkPermission(Permission.HOST_READ);
175
tom7869ad92014-09-09 14:32:08 -0700176 checkNotNull(connectPoint, "Connection point cannot be null");
177 return store.getConnectedHosts(connectPoint);
178 }
179
180 @Override
181 public Set<Host> getConnectedHosts(DeviceId deviceId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900182 checkPermission(Permission.HOST_READ);
183
tom7869ad92014-09-09 14:32:08 -0700184 checkNotNull(deviceId, "Device ID cannot be null");
185 return store.getConnectedHosts(deviceId);
186 }
187
188 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700189 public void startMonitoringIp(IpAddress ip) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900190 checkPermission(Permission.HOST_EVENT);
191
Jonathan Hart70da5122014-10-01 16:37:42 -0700192 monitor.addMonitoringFor(ip);
Jonathan Hartfca736c2014-09-19 17:26:59 -0700193 }
194
195 @Override
Jonathan Hartac60c082014-09-23 08:55:17 -0700196 public void stopMonitoringIp(IpAddress ip) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900197 checkPermission(Permission.HOST_EVENT);
198
Jonathan Hart70da5122014-10-01 16:37:42 -0700199 monitor.stopMonitoring(ip);
Jonathan Hartac60c082014-09-23 08:55:17 -0700200 }
201
202 @Override
203 public void requestMac(IpAddress ip) {
204 // TODO Auto-generated method stub
Jonathan Hartfca736c2014-09-19 17:26:59 -0700205 }
206
207 @Override
tom7869ad92014-09-09 14:32:08 -0700208 public void addListener(HostListener listener) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900209 checkPermission(Permission.HOST_EVENT);
210
tom7869ad92014-09-09 14:32:08 -0700211 listenerRegistry.addListener(listener);
212 }
213
214 @Override
215 public void removeListener(HostListener listener) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900216 checkPermission(Permission.HOST_EVENT);
217
tom7869ad92014-09-09 14:32:08 -0700218 listenerRegistry.removeListener(listener);
219 }
220
tom89b63c52014-09-16 09:19:51 -0700221 @Override
222 public void removeHost(HostId hostId) {
223 checkNotNull(hostId, HOST_ID_NULL);
224 HostEvent event = store.removeHost(hostId);
225 if (event != null) {
tom89b63c52014-09-16 09:19:51 -0700226 post(event);
227 }
228 }
229
Jonathan Hartac60c082014-09-23 08:55:17 -0700230 @Override
Jonathan Hart09585c62014-09-23 16:58:04 -0700231 public void bindAddressesToPort(PortAddresses addresses) {
232 store.updateAddressBindings(addresses);
Jonathan Hartac60c082014-09-23 08:55:17 -0700233 }
234
235 @Override
Jonathan Hart09585c62014-09-23 16:58:04 -0700236 public void unbindAddressesFromPort(PortAddresses portAddresses) {
237 store.removeAddressBindings(portAddresses);
238 }
239
240 @Override
241 public void clearAddresses(ConnectPoint connectPoint) {
242 store.clearAddressBindings(connectPoint);
Jonathan Hartac60c082014-09-23 08:55:17 -0700243 }
244
245 @Override
246 public Set<PortAddresses> getAddressBindings() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900247 checkPermission(Permission.HOST_READ);
248
Jonathan Hart43c182c2014-09-23 11:13:42 -0700249 return store.getAddressBindings();
Jonathan Hartac60c082014-09-23 08:55:17 -0700250 }
251
252 @Override
Jonathan Harta887ba82014-11-03 15:20:52 -0800253 public Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900254 checkPermission(Permission.HOST_READ);
255
Jonathan Hart43c182c2014-09-23 11:13:42 -0700256 return store.getAddressBindingsForPort(connectPoint);
Jonathan Hartac60c082014-09-23 08:55:17 -0700257 }
258
tomdb0d03f2014-08-27 16:34:15 -0700259 // Personalized host provider service issued to the supplied provider.
tom7869ad92014-09-09 14:32:08 -0700260 private class InternalHostProviderService
261 extends AbstractProviderService<HostProvider>
tomdb0d03f2014-08-27 16:34:15 -0700262 implements HostProviderService {
tomcfde0622014-09-09 11:02:42 -0700263 InternalHostProviderService(HostProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700264 super(provider);
265 }
266
267 @Override
tom7869ad92014-09-09 14:32:08 -0700268 public void hostDetected(HostId hostId, HostDescription hostDescription) {
269 checkNotNull(hostId, HOST_ID_NULL);
270 checkValidity();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700271 hostDescription = validateHost(hostDescription, hostId);
tom7869ad92014-09-09 14:32:08 -0700272 HostEvent event = store.createOrUpdateHost(provider().id(), hostId,
273 hostDescription);
274 if (event != null) {
tom7869ad92014-09-09 14:32:08 -0700275 post(event);
276 }
tomdb0d03f2014-08-27 16:34:15 -0700277 }
278
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700279 // returns a HostDescription made from the union of the BasicHostConfig
280 // annotations if it exists
281 private HostDescription validateHost(HostDescription hostDescription, HostId hostId) {
282 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
283 checkState(cfg == null || cfg.isAllowed(), "Host {} is not allowed", hostId);
284 if (cfg != null) {
285 SparseAnnotations finalSparse = processAnnotations(cfg, hostDescription);
286 hostDescription = new DefaultHostDescription(hostId.mac(),
287 hostDescription.vlan(),
288 hostDescription.location(),
289 finalSparse);
290 }
291 return hostDescription;
292 }
293
tomdb0d03f2014-08-27 16:34:15 -0700294 @Override
tom7869ad92014-09-09 14:32:08 -0700295 public void hostVanished(HostId hostId) {
296 checkNotNull(hostId, HOST_ID_NULL);
297 checkValidity();
298 HostEvent event = store.removeHost(hostId);
299 if (event != null) {
tom7869ad92014-09-09 14:32:08 -0700300 post(event);
301 }
tomdb0d03f2014-08-27 16:34:15 -0700302 }
303 }
tom7869ad92014-09-09 14:32:08 -0700304
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700305 // Supplements or replaces hostDescriptions's annotations with BasicHostConfig's
306 // annotations
307 private SparseAnnotations processAnnotations(BasicHostConfig cfg, HostDescription hostDescription) {
308 SparseAnnotations originalAnnotations = hostDescription.annotations();
309 DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();
310 if (cfg.name() != null) {
311 newBuilder.set(cfg.NAME, cfg.name());
312 }
313 if (cfg.latitude() != -1) {
314 newBuilder.set(cfg.LATITUDE, Double.toString(cfg.latitude()));
315 }
316 if (cfg.longitude() != -1) {
317 newBuilder.set(cfg.LONGITUDE, Double.toString(cfg.longitude()));
318 }
319 if (cfg.rackAddress() != null) {
320 newBuilder.set(cfg.RACK_ADDRESS, cfg.rackAddress());
321 }
322 if (cfg.owner() != null) {
323 newBuilder.set(cfg.OWNER, cfg.owner());
324 }
325 DefaultAnnotations newAnnotations = newBuilder.build();
326 return DefaultAnnotations.union(originalAnnotations, newAnnotations);
327 }
328
tom7869ad92014-09-09 14:32:08 -0700329 // Posts the specified event to the local event dispatcher.
330 private void post(HostEvent event) {
tomdc361b62014-09-09 20:36:52 -0700331 if (event != null) {
tom7869ad92014-09-09 14:32:08 -0700332 eventDispatcher.post(event);
333 }
334 }
335
tomc78acee2014-09-24 15:16:55 -0700336 // Store delegate to re-post events emitted from the store.
337 private class InternalStoreDelegate implements HostStoreDelegate {
338 @Override
339 public void notify(HostEvent event) {
340 post(event);
341 }
342 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700343
344 // listens for NetworkConfigEvents of type BasicHostConfig and removes
345 // links that the config does not allow
346 private class InternalNetworkConfigListener implements NetworkConfigListener {
347 @Override
348 public void event(NetworkConfigEvent event) {
349 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
350 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
351 event.configClass().equals(BasicHostConfig.class)) {
352 log.info("Detected Host network config event {}", event.type());
353 kickOutBadHost(((HostId) event.subject()));
354 }
355 }
356 }
357
358 // checks if the specified host is allowed by the BasicHostConfig
359 // and if not, removes it
360 private void kickOutBadHost(HostId hostId) {
361 BasicHostConfig cfg = networkConfigService.getConfig(hostId, BasicHostConfig.class);
362 if (cfg != null && !cfg.isAllowed()) {
363 Host badHost = getHost(hostId);
364 if (badHost != null) {
365 removeHost(hostId);
366 } else {
367 log.info("Failed removal: Host {} does not exist", hostId);
368 }
369 }
370 }
tomdb0d03f2014-08-27 16:34:15 -0700371}