blob: 75aeb1e559e60f96814dd2ff4975828786b4b232 [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;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.event.EventDeliveryService;
Simon Huntff663742015-05-14 13:33:05 -070028import org.onosproject.event.ListenerRegistry;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.ConnectPoint;
30import org.onosproject.net.DeviceId;
31import org.onosproject.net.Link;
32import org.onosproject.net.Link.State;
33import org.onosproject.net.MastershipRole;
34import org.onosproject.net.device.DeviceEvent;
35import org.onosproject.net.device.DeviceListener;
36import org.onosproject.net.device.DeviceService;
37import org.onosproject.net.link.LinkAdminService;
38import org.onosproject.net.link.LinkDescription;
39import org.onosproject.net.link.LinkEvent;
40import org.onosproject.net.link.LinkListener;
41import org.onosproject.net.link.LinkProvider;
42import org.onosproject.net.link.LinkProviderRegistry;
43import org.onosproject.net.link.LinkProviderService;
44import org.onosproject.net.link.LinkService;
45import org.onosproject.net.link.LinkStore;
46import org.onosproject.net.link.LinkStoreDelegate;
47import org.onosproject.net.provider.AbstractProviderRegistry;
48import org.onosproject.net.provider.AbstractProviderService;
tomdb0d03f2014-08-27 16:34:15 -070049import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070050
Simon Huntff663742015-05-14 13:33:05 -070051import java.util.Set;
tomdb0d03f2014-08-27 16:34:15 -070052
Ray Milkey7bbeb3f2014-12-11 14:59:26 -080053import static com.google.common.base.Preconditions.checkNotNull;
54import static org.slf4j.LoggerFactory.getLogger;
55
tomdb0d03f2014-08-27 16:34:15 -070056/**
57 * Provides basic implementation of the link SB & NB APIs.
58 */
59@Component(immediate = true)
60@Service
tom35c0dc32014-09-19 10:00:58 -070061public class LinkManager
tomdc361b62014-09-09 20:36:52 -070062 extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
63 implements LinkService, LinkAdminService, LinkProviderRegistry {
tomeadbb462014-09-07 16:10:19 -070064
65 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
66 private static final String LINK_DESC_NULL = "Link description cannot be null";
67 private static final String CONNECT_POINT_NULL = "Connection point cannot be null";
tomdb0d03f2014-08-27 16:34:15 -070068
tom5f38b3a2014-08-27 23:50:54 -070069 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -070070
Simon Huntff663742015-05-14 13:33:05 -070071 protected final ListenerRegistry<LinkEvent, LinkListener>
72 listenerRegistry = new ListenerRegistry<>();
tom5f38b3a2014-08-27 23:50:54 -070073
alshabibb5522ff2014-09-29 19:20:00 -070074 private final LinkStoreDelegate delegate = new InternalStoreDelegate();
tomc78acee2014-09-24 15:16:55 -070075
76 private final DeviceListener deviceListener = new InternalDeviceListener();
tom89b63c52014-09-16 09:19:51 -070077
78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom35c0dc32014-09-19 10:00:58 -070079 protected LinkStore store;
80
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom89b63c52014-09-16 09:19:51 -070082 protected DeviceService deviceService;
tom4c6606f2014-09-07 11:11:21 -070083
tom5f38b3a2014-08-27 23:50:54 -070084 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom0d395262014-09-07 16:53:40 -070085 protected EventDeliveryService eventDispatcher;
tomdb0d03f2014-08-27 16:34:15 -070086
87 @Activate
88 public void activate() {
tomc78acee2014-09-24 15:16:55 -070089 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -070090 eventDispatcher.addSink(LinkEvent.class, listenerRegistry);
tom89b63c52014-09-16 09:19:51 -070091 deviceService.addListener(deviceListener);
tomdb0d03f2014-08-27 16:34:15 -070092 log.info("Started");
93 }
94
95 @Deactivate
96 public void deactivate() {
tomc78acee2014-09-24 15:16:55 -070097 store.unsetDelegate(delegate);
tom5f38b3a2014-08-27 23:50:54 -070098 eventDispatcher.removeSink(LinkEvent.class);
tom89b63c52014-09-16 09:19:51 -070099 deviceService.removeListener(deviceListener);
tomdb0d03f2014-08-27 16:34:15 -0700100 log.info("Stopped");
101 }
102
103 @Override
tomeadbb462014-09-07 16:10:19 -0700104 public int getLinkCount() {
105 return store.getLinkCount();
106 }
107
108 @Override
109 public Iterable<Link> getLinks() {
110 return store.getLinks();
111 }
112
113 @Override
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800114 public Iterable<Link> getActiveLinks() {
115 return FluentIterable.from(getLinks())
116 .filter(new Predicate<Link>() {
117
118 @Override
119 public boolean apply(Link input) {
120 return input.state() == State.ACTIVE;
121 }
122 });
123 }
124
125 @Override
tomeadbb462014-09-07 16:10:19 -0700126 public Set<Link> getDeviceLinks(DeviceId deviceId) {
127 checkNotNull(deviceId, DEVICE_ID_NULL);
128 return Sets.union(store.getDeviceEgressLinks(deviceId),
tomdc361b62014-09-09 20:36:52 -0700129 store.getDeviceIngressLinks(deviceId));
tomeadbb462014-09-07 16:10:19 -0700130 }
131
132 @Override
133 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
134 checkNotNull(deviceId, DEVICE_ID_NULL);
135 return store.getDeviceEgressLinks(deviceId);
136 }
137
138 @Override
tomd176fc42014-09-08 00:12:30 -0700139 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
tomeadbb462014-09-07 16:10:19 -0700140 checkNotNull(deviceId, DEVICE_ID_NULL);
141 return store.getDeviceIngressLinks(deviceId);
142 }
143
144 @Override
145 public Set<Link> getLinks(ConnectPoint connectPoint) {
146 checkNotNull(connectPoint, CONNECT_POINT_NULL);
147 return Sets.union(store.getEgressLinks(connectPoint),
tomdc361b62014-09-09 20:36:52 -0700148 store.getIngressLinks(connectPoint));
tomeadbb462014-09-07 16:10:19 -0700149 }
150
151 @Override
152 public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
153 checkNotNull(connectPoint, CONNECT_POINT_NULL);
154 return store.getEgressLinks(connectPoint);
155 }
156
157 @Override
tomd176fc42014-09-08 00:12:30 -0700158 public Set<Link> getIngressLinks(ConnectPoint connectPoint) {
tomeadbb462014-09-07 16:10:19 -0700159 checkNotNull(connectPoint, CONNECT_POINT_NULL);
160 return store.getIngressLinks(connectPoint);
161 }
162
163 @Override
tomd176fc42014-09-08 00:12:30 -0700164 public Link getLink(ConnectPoint src, ConnectPoint dst) {
tomeadbb462014-09-07 16:10:19 -0700165 checkNotNull(src, CONNECT_POINT_NULL);
166 checkNotNull(dst, CONNECT_POINT_NULL);
tomd176fc42014-09-08 00:12:30 -0700167 return store.getLink(src, dst);
tomeadbb462014-09-07 16:10:19 -0700168 }
169
170 @Override
171 public void removeLinks(ConnectPoint connectPoint) {
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700172 if (deviceService.getRole(connectPoint.deviceId()) != MastershipRole.MASTER) {
173 return;
174 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800175 removeLinks(getLinks(connectPoint), false);
tomeadbb462014-09-07 16:10:19 -0700176 }
177
178 @Override
179 public void removeLinks(DeviceId deviceId) {
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700180 if (deviceService.getRole(deviceId) != MastershipRole.MASTER) {
181 return;
182 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800183 removeLinks(getDeviceLinks(deviceId), false);
tomeadbb462014-09-07 16:10:19 -0700184 }
185
186 @Override
187 public void addListener(LinkListener listener) {
188 listenerRegistry.addListener(listener);
189 }
190
191 @Override
192 public void removeListener(LinkListener listener) {
193 listenerRegistry.removeListener(listener);
194 }
195
tom89b63c52014-09-16 09:19:51 -0700196 // Auxiliary interceptor for device remove events to prune links that
197 // are associated with the removed device or its port.
tomc78acee2014-09-24 15:16:55 -0700198 private class InternalDeviceListener implements DeviceListener {
tom89b63c52014-09-16 09:19:51 -0700199 @Override
200 public void event(DeviceEvent event) {
201 if (event.type() == DeviceEvent.Type.DEVICE_REMOVED) {
202 removeLinks(event.subject().id());
203 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
204 removeLinks(new ConnectPoint(event.subject().id(),
205 event.port().number()));
206 }
207 }
208 }
209
tom7869ad92014-09-09 14:32:08 -0700210 @Override
211 protected LinkProviderService createProviderService(LinkProvider provider) {
212 return new InternalLinkProviderService(provider);
213 }
214
tomdb0d03f2014-08-27 16:34:15 -0700215 // Personalized link provider service issued to the supplied provider.
tomdc361b62014-09-09 20:36:52 -0700216 private class InternalLinkProviderService
217 extends AbstractProviderService<LinkProvider>
218 implements LinkProviderService {
tomdb0d03f2014-08-27 16:34:15 -0700219
tomcfde0622014-09-09 11:02:42 -0700220 InternalLinkProviderService(LinkProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700221 super(provider);
222 }
223
224 @Override
225 public void linkDetected(LinkDescription linkDescription) {
tomeadbb462014-09-07 16:10:19 -0700226 checkNotNull(linkDescription, LINK_DESC_NULL);
227 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700228
tomeadbb462014-09-07 16:10:19 -0700229 LinkEvent event = store.createOrUpdateLink(provider().id(),
tomdc361b62014-09-09 20:36:52 -0700230 linkDescription);
231 if (event != null) {
Thomas Vachuska0e752bd2014-10-22 22:33:41 -0700232 log.info("Link {} detected", linkDescription);
tomdc361b62014-09-09 20:36:52 -0700233 post(event);
234 }
tomdb0d03f2014-08-27 16:34:15 -0700235 }
236
237 @Override
238 public void linkVanished(LinkDescription linkDescription) {
tomeadbb462014-09-07 16:10:19 -0700239 checkNotNull(linkDescription, LINK_DESC_NULL);
240 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700241
242 ConnectPoint src = linkDescription.src();
243 ConnectPoint dst = linkDescription.dst();
alshabibdfc7afb2014-10-21 20:13:27 -0700244
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800245 LinkEvent event = store.removeOrDownLink(src, dst);
tomdc361b62014-09-09 20:36:52 -0700246 if (event != null) {
247 log.info("Link {} vanished", linkDescription);
248 post(event);
249 }
tomeadbb462014-09-07 16:10:19 -0700250 }
251
252 @Override
253 public void linksVanished(ConnectPoint connectPoint) {
254 checkNotNull(connectPoint, "Connect point cannot be null");
255 checkValidity();
alshabib12288c82014-10-23 10:24:23 -0700256
Yuta HIGUCHIddb77722014-12-11 19:39:04 -0800257 log.debug("Links for connection point {} vanished", connectPoint);
Yuta HIGUCHIe794cbe2014-10-17 13:21:23 -0700258 // FIXME: This will remove links registered by other providers
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800259 removeLinks(getLinks(connectPoint), true);
tomeadbb462014-09-07 16:10:19 -0700260 }
261
262 @Override
263 public void linksVanished(DeviceId deviceId) {
264 checkNotNull(deviceId, DEVICE_ID_NULL);
265 checkValidity();
alshabib12288c82014-10-23 10:24:23 -0700266
Yuta HIGUCHIddb77722014-12-11 19:39:04 -0800267 log.debug("Links for device {} vanished", deviceId);
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800268 removeLinks(getDeviceLinks(deviceId), true);
tomdb0d03f2014-08-27 16:34:15 -0700269 }
270 }
tomeadbb462014-09-07 16:10:19 -0700271
272 // Removes all links in the specified set and emits appropriate events.
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800273 private void removeLinks(Set<Link> links, boolean isSoftRemove) {
tomeadbb462014-09-07 16:10:19 -0700274 for (Link link : links) {
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800275 LinkEvent event = isSoftRemove ?
276 store.removeOrDownLink(link.src(), link.dst()) :
277 store.removeLink(link.src(), link.dst());
Yuta HIGUCHIddb77722014-12-11 19:39:04 -0800278 if (event != null) {
279 log.info("Link {} removed/vanished", event.subject());
280 post(event);
281 }
tomeadbb462014-09-07 16:10:19 -0700282 }
283 }
284
285 // Posts the specified event to the local event dispatcher.
286 private void post(LinkEvent event) {
tomdc361b62014-09-09 20:36:52 -0700287 if (event != null) {
tomeadbb462014-09-07 16:10:19 -0700288 eventDispatcher.post(event);
289 }
290 }
291
tomc78acee2014-09-24 15:16:55 -0700292 // Store delegate to re-post events emitted from the store.
293 private class InternalStoreDelegate implements LinkStoreDelegate {
294 @Override
295 public void notify(LinkEvent event) {
296 post(event);
297 }
298 }
tomdb0d03f2014-08-27 16:34:15 -0700299}