blob: 75134f3d383b166c7ac76e61603c0d80343282be [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.link.impl;
tomdb0d03f2014-08-27 16:34:15 -070017
Simon Huntff663742015-05-14 13:33:05 -070018import com.google.common.base.Predicate;
19import com.google.common.collect.FluentIterable;
20import com.google.common.collect.Sets;
tomdb0d03f2014-08-27 16:34:15 -070021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
tom5f38b3a2014-08-27 23:50:54 -070024import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070026import org.apache.felix.scr.annotations.Service;
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;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.ConnectPoint;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.Link;
33import org.onosproject.net.Link.State;
34import org.onosproject.net.MastershipRole;
35import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.device.DeviceListener;
37import org.onosproject.net.device.DeviceService;
38import org.onosproject.net.link.LinkAdminService;
39import org.onosproject.net.link.LinkDescription;
40import org.onosproject.net.link.LinkEvent;
41import org.onosproject.net.link.LinkListener;
42import org.onosproject.net.link.LinkProvider;
43import org.onosproject.net.link.LinkProviderRegistry;
44import org.onosproject.net.link.LinkProviderService;
45import org.onosproject.net.link.LinkService;
46import org.onosproject.net.link.LinkStore;
47import org.onosproject.net.link.LinkStoreDelegate;
48import org.onosproject.net.provider.AbstractProviderRegistry;
49import org.onosproject.net.provider.AbstractProviderService;
tomdb0d03f2014-08-27 16:34:15 -070050import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070051
Simon Huntff663742015-05-14 13:33:05 -070052import java.util.Set;
tomdb0d03f2014-08-27 16:34:15 -070053
Ray Milkey7bbeb3f2014-12-11 14:59:26 -080054import static com.google.common.base.Preconditions.checkNotNull;
55import static org.slf4j.LoggerFactory.getLogger;
Changhoon Yoon541ef712015-05-23 17:18:34 +090056import static org.onosproject.security.AppGuard.checkPermission;
57
Ray Milkey7bbeb3f2014-12-11 14:59:26 -080058
tomdb0d03f2014-08-27 16:34:15 -070059/**
60 * Provides basic implementation of the link SB & NB APIs.
61 */
62@Component(immediate = true)
63@Service
tom35c0dc32014-09-19 10:00:58 -070064public class LinkManager
tomdc361b62014-09-09 20:36:52 -070065 extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
66 implements LinkService, LinkAdminService, LinkProviderRegistry {
tomeadbb462014-09-07 16:10:19 -070067
68 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
69 private static final String LINK_DESC_NULL = "Link description cannot be null";
70 private static final String CONNECT_POINT_NULL = "Connection point cannot be null";
tomdb0d03f2014-08-27 16:34:15 -070071
tom5f38b3a2014-08-27 23:50:54 -070072 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -070073
Simon Huntff663742015-05-14 13:33:05 -070074 protected final ListenerRegistry<LinkEvent, LinkListener>
75 listenerRegistry = new ListenerRegistry<>();
tom5f38b3a2014-08-27 23:50:54 -070076
alshabibb5522ff2014-09-29 19:20:00 -070077 private final LinkStoreDelegate delegate = new InternalStoreDelegate();
tomc78acee2014-09-24 15:16:55 -070078
79 private final DeviceListener deviceListener = new InternalDeviceListener();
tom89b63c52014-09-16 09:19:51 -070080
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom35c0dc32014-09-19 10:00:58 -070082 protected LinkStore store;
83
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom89b63c52014-09-16 09:19:51 -070085 protected DeviceService deviceService;
tom4c6606f2014-09-07 11:11:21 -070086
tom5f38b3a2014-08-27 23:50:54 -070087 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom0d395262014-09-07 16:53:40 -070088 protected EventDeliveryService eventDispatcher;
tomdb0d03f2014-08-27 16:34:15 -070089
90 @Activate
91 public void activate() {
tomc78acee2014-09-24 15:16:55 -070092 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -070093 eventDispatcher.addSink(LinkEvent.class, listenerRegistry);
tom89b63c52014-09-16 09:19:51 -070094 deviceService.addListener(deviceListener);
tomdb0d03f2014-08-27 16:34:15 -070095 log.info("Started");
96 }
97
98 @Deactivate
99 public void deactivate() {
tomc78acee2014-09-24 15:16:55 -0700100 store.unsetDelegate(delegate);
tom5f38b3a2014-08-27 23:50:54 -0700101 eventDispatcher.removeSink(LinkEvent.class);
tom89b63c52014-09-16 09:19:51 -0700102 deviceService.removeListener(deviceListener);
tomdb0d03f2014-08-27 16:34:15 -0700103 log.info("Stopped");
104 }
105
106 @Override
tomeadbb462014-09-07 16:10:19 -0700107 public int getLinkCount() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900108 checkPermission(Permission.LINK_READ);
109
tomeadbb462014-09-07 16:10:19 -0700110 return store.getLinkCount();
111 }
112
113 @Override
114 public Iterable<Link> getLinks() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900115 checkPermission(Permission.LINK_READ);
116
tomeadbb462014-09-07 16:10:19 -0700117 return store.getLinks();
118 }
119
120 @Override
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800121 public Iterable<Link> getActiveLinks() {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900122 checkPermission(Permission.LINK_READ);
123
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800124 return FluentIterable.from(getLinks())
125 .filter(new Predicate<Link>() {
126
127 @Override
128 public boolean apply(Link input) {
129 return input.state() == State.ACTIVE;
130 }
131 });
132 }
133
134 @Override
tomeadbb462014-09-07 16:10:19 -0700135 public Set<Link> getDeviceLinks(DeviceId deviceId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900136 checkPermission(Permission.LINK_READ);
137
tomeadbb462014-09-07 16:10:19 -0700138 checkNotNull(deviceId, DEVICE_ID_NULL);
139 return Sets.union(store.getDeviceEgressLinks(deviceId),
tomdc361b62014-09-09 20:36:52 -0700140 store.getDeviceIngressLinks(deviceId));
tomeadbb462014-09-07 16:10:19 -0700141 }
142
143 @Override
144 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900145 checkPermission(Permission.LINK_READ);
146
tomeadbb462014-09-07 16:10:19 -0700147 checkNotNull(deviceId, DEVICE_ID_NULL);
148 return store.getDeviceEgressLinks(deviceId);
149 }
150
151 @Override
tomd176fc42014-09-08 00:12:30 -0700152 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900153 checkPermission(Permission.LINK_READ);
154
tomeadbb462014-09-07 16:10:19 -0700155 checkNotNull(deviceId, DEVICE_ID_NULL);
156 return store.getDeviceIngressLinks(deviceId);
157 }
158
159 @Override
160 public Set<Link> getLinks(ConnectPoint connectPoint) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900161 checkPermission(Permission.LINK_READ);
162
tomeadbb462014-09-07 16:10:19 -0700163 checkNotNull(connectPoint, CONNECT_POINT_NULL);
164 return Sets.union(store.getEgressLinks(connectPoint),
tomdc361b62014-09-09 20:36:52 -0700165 store.getIngressLinks(connectPoint));
tomeadbb462014-09-07 16:10:19 -0700166 }
167
168 @Override
169 public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900170 checkPermission(Permission.LINK_READ);
171
tomeadbb462014-09-07 16:10:19 -0700172 checkNotNull(connectPoint, CONNECT_POINT_NULL);
173 return store.getEgressLinks(connectPoint);
174 }
175
176 @Override
tomd176fc42014-09-08 00:12:30 -0700177 public Set<Link> getIngressLinks(ConnectPoint connectPoint) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900178 checkPermission(Permission.LINK_READ);
179
tomeadbb462014-09-07 16:10:19 -0700180 checkNotNull(connectPoint, CONNECT_POINT_NULL);
181 return store.getIngressLinks(connectPoint);
182 }
183
184 @Override
tomd176fc42014-09-08 00:12:30 -0700185 public Link getLink(ConnectPoint src, ConnectPoint dst) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900186 checkPermission(Permission.LINK_READ);
187
tomeadbb462014-09-07 16:10:19 -0700188 checkNotNull(src, CONNECT_POINT_NULL);
189 checkNotNull(dst, CONNECT_POINT_NULL);
tomd176fc42014-09-08 00:12:30 -0700190 return store.getLink(src, dst);
tomeadbb462014-09-07 16:10:19 -0700191 }
192
193 @Override
194 public void removeLinks(ConnectPoint connectPoint) {
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700195 if (deviceService.getRole(connectPoint.deviceId()) != MastershipRole.MASTER) {
196 return;
197 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800198 removeLinks(getLinks(connectPoint), false);
tomeadbb462014-09-07 16:10:19 -0700199 }
200
201 @Override
202 public void removeLinks(DeviceId deviceId) {
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700203 if (deviceService.getRole(deviceId) != MastershipRole.MASTER) {
204 return;
205 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800206 removeLinks(getDeviceLinks(deviceId), false);
tomeadbb462014-09-07 16:10:19 -0700207 }
208
209 @Override
210 public void addListener(LinkListener listener) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900211 checkPermission(Permission.LINK_EVENT);
212
tomeadbb462014-09-07 16:10:19 -0700213 listenerRegistry.addListener(listener);
214 }
215
216 @Override
217 public void removeListener(LinkListener listener) {
Changhoon Yoon541ef712015-05-23 17:18:34 +0900218 checkPermission(Permission.LINK_EVENT);
219
tomeadbb462014-09-07 16:10:19 -0700220 listenerRegistry.removeListener(listener);
221 }
222
tom89b63c52014-09-16 09:19:51 -0700223 // Auxiliary interceptor for device remove events to prune links that
224 // are associated with the removed device or its port.
tomc78acee2014-09-24 15:16:55 -0700225 private class InternalDeviceListener implements DeviceListener {
tom89b63c52014-09-16 09:19:51 -0700226 @Override
227 public void event(DeviceEvent event) {
228 if (event.type() == DeviceEvent.Type.DEVICE_REMOVED) {
229 removeLinks(event.subject().id());
230 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
231 removeLinks(new ConnectPoint(event.subject().id(),
232 event.port().number()));
233 }
234 }
235 }
236
tom7869ad92014-09-09 14:32:08 -0700237 @Override
238 protected LinkProviderService createProviderService(LinkProvider provider) {
239 return new InternalLinkProviderService(provider);
240 }
241
tomdb0d03f2014-08-27 16:34:15 -0700242 // Personalized link provider service issued to the supplied provider.
tomdc361b62014-09-09 20:36:52 -0700243 private class InternalLinkProviderService
244 extends AbstractProviderService<LinkProvider>
245 implements LinkProviderService {
tomdb0d03f2014-08-27 16:34:15 -0700246
tomcfde0622014-09-09 11:02:42 -0700247 InternalLinkProviderService(LinkProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700248 super(provider);
249 }
250
251 @Override
252 public void linkDetected(LinkDescription linkDescription) {
tomeadbb462014-09-07 16:10:19 -0700253 checkNotNull(linkDescription, LINK_DESC_NULL);
254 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700255
tomeadbb462014-09-07 16:10:19 -0700256 LinkEvent event = store.createOrUpdateLink(provider().id(),
tomdc361b62014-09-09 20:36:52 -0700257 linkDescription);
258 if (event != null) {
Thomas Vachuska0e752bd2014-10-22 22:33:41 -0700259 log.info("Link {} detected", linkDescription);
tomdc361b62014-09-09 20:36:52 -0700260 post(event);
261 }
tomdb0d03f2014-08-27 16:34:15 -0700262 }
263
264 @Override
265 public void linkVanished(LinkDescription linkDescription) {
tomeadbb462014-09-07 16:10:19 -0700266 checkNotNull(linkDescription, LINK_DESC_NULL);
267 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700268
269 ConnectPoint src = linkDescription.src();
270 ConnectPoint dst = linkDescription.dst();
alshabibdfc7afb2014-10-21 20:13:27 -0700271
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800272 LinkEvent event = store.removeOrDownLink(src, dst);
tomdc361b62014-09-09 20:36:52 -0700273 if (event != null) {
274 log.info("Link {} vanished", linkDescription);
275 post(event);
276 }
tomeadbb462014-09-07 16:10:19 -0700277 }
278
279 @Override
280 public void linksVanished(ConnectPoint connectPoint) {
281 checkNotNull(connectPoint, "Connect point cannot be null");
282 checkValidity();
alshabib12288c82014-10-23 10:24:23 -0700283
Yuta HIGUCHIddb77722014-12-11 19:39:04 -0800284 log.debug("Links for connection point {} vanished", connectPoint);
Yuta HIGUCHIe794cbe2014-10-17 13:21:23 -0700285 // FIXME: This will remove links registered by other providers
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800286 removeLinks(getLinks(connectPoint), true);
tomeadbb462014-09-07 16:10:19 -0700287 }
288
289 @Override
290 public void linksVanished(DeviceId deviceId) {
291 checkNotNull(deviceId, DEVICE_ID_NULL);
292 checkValidity();
alshabib12288c82014-10-23 10:24:23 -0700293
Yuta HIGUCHIddb77722014-12-11 19:39:04 -0800294 log.debug("Links for device {} vanished", deviceId);
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800295 removeLinks(getDeviceLinks(deviceId), true);
tomdb0d03f2014-08-27 16:34:15 -0700296 }
297 }
tomeadbb462014-09-07 16:10:19 -0700298
299 // Removes all links in the specified set and emits appropriate events.
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800300 private void removeLinks(Set<Link> links, boolean isSoftRemove) {
tomeadbb462014-09-07 16:10:19 -0700301 for (Link link : links) {
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800302 LinkEvent event = isSoftRemove ?
303 store.removeOrDownLink(link.src(), link.dst()) :
304 store.removeLink(link.src(), link.dst());
Yuta HIGUCHIddb77722014-12-11 19:39:04 -0800305 if (event != null) {
306 log.info("Link {} removed/vanished", event.subject());
307 post(event);
308 }
tomeadbb462014-09-07 16:10:19 -0700309 }
310 }
311
312 // Posts the specified event to the local event dispatcher.
313 private void post(LinkEvent event) {
tomdc361b62014-09-09 20:36:52 -0700314 if (event != null) {
tomeadbb462014-09-07 16:10:19 -0700315 eventDispatcher.post(event);
316 }
317 }
318
tomc78acee2014-09-24 15:16:55 -0700319 // Store delegate to re-post events emitted from the store.
320 private class InternalStoreDelegate implements LinkStoreDelegate {
321 @Override
322 public void notify(LinkEvent event) {
323 post(event);
324 }
325 }
tomdb0d03f2014-08-27 16:34:15 -0700326}