blob: be84a8b1ae546af1146bd35d8b44084e8673c21d [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
alshabibdf652ad2014-09-09 11:53:19 -070018import static com.google.common.base.Preconditions.checkNotNull;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.util.Set;
22
tomdb0d03f2014-08-27 16:34:15 -070023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
tom5f38b3a2014-08-27 23:50:54 -070026import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
tomdb0d03f2014-08-27 16:34:15 -070028import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.event.AbstractListenerRegistry;
30import org.onosproject.event.EventDeliveryService;
31import org.onosproject.net.ConnectPoint;
Ray Milkeyf2695402014-12-08 16:24:24 -080032import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.DeviceId;
34import org.onosproject.net.Link;
35import org.onosproject.net.Link.State;
36import org.onosproject.net.MastershipRole;
37import org.onosproject.net.device.DeviceEvent;
38import org.onosproject.net.device.DeviceListener;
39import org.onosproject.net.device.DeviceService;
40import org.onosproject.net.link.LinkAdminService;
41import org.onosproject.net.link.LinkDescription;
42import org.onosproject.net.link.LinkEvent;
43import org.onosproject.net.link.LinkListener;
44import org.onosproject.net.link.LinkProvider;
45import org.onosproject.net.link.LinkProviderRegistry;
46import org.onosproject.net.link.LinkProviderService;
47import org.onosproject.net.link.LinkService;
48import org.onosproject.net.link.LinkStore;
49import org.onosproject.net.link.LinkStoreDelegate;
50import org.onosproject.net.provider.AbstractProviderRegistry;
51import org.onosproject.net.provider.AbstractProviderService;
tomdb0d03f2014-08-27 16:34:15 -070052import org.slf4j.Logger;
tom5f38b3a2014-08-27 23:50:54 -070053
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -080054import com.google.common.base.Predicate;
55import com.google.common.collect.FluentIterable;
alshabibdf652ad2014-09-09 11:53:19 -070056import com.google.common.collect.Sets;
tomdb0d03f2014-08-27 16:34:15 -070057
58/**
59 * Provides basic implementation of the link SB & NB APIs.
60 */
61@Component(immediate = true)
62@Service
tom35c0dc32014-09-19 10:00:58 -070063public class LinkManager
tomdc361b62014-09-09 20:36:52 -070064 extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
65 implements LinkService, LinkAdminService, LinkProviderRegistry {
tomeadbb462014-09-07 16:10:19 -070066
67 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
68 private static final String LINK_DESC_NULL = "Link description cannot be null";
69 private static final String CONNECT_POINT_NULL = "Connection point cannot be null";
tomdb0d03f2014-08-27 16:34:15 -070070
tom5f38b3a2014-08-27 23:50:54 -070071 private final Logger log = getLogger(getClass());
tomdb0d03f2014-08-27 16:34:15 -070072
tomb86066b2014-09-15 09:52:24 -070073 protected final AbstractListenerRegistry<LinkEvent, LinkListener>
tomdc361b62014-09-09 20:36:52 -070074 listenerRegistry = new AbstractListenerRegistry<>();
tom5f38b3a2014-08-27 23:50:54 -070075
alshabibb5522ff2014-09-29 19:20:00 -070076 private final LinkStoreDelegate delegate = new InternalStoreDelegate();
tomc78acee2014-09-24 15:16:55 -070077
78 private final DeviceListener deviceListener = new InternalDeviceListener();
tom89b63c52014-09-16 09:19:51 -070079
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom35c0dc32014-09-19 10:00:58 -070081 protected LinkStore store;
82
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom89b63c52014-09-16 09:19:51 -070084 protected DeviceService deviceService;
tom4c6606f2014-09-07 11:11:21 -070085
tom5f38b3a2014-08-27 23:50:54 -070086 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tom0d395262014-09-07 16:53:40 -070087 protected EventDeliveryService eventDispatcher;
tomdb0d03f2014-08-27 16:34:15 -070088
89 @Activate
90 public void activate() {
tomc78acee2014-09-24 15:16:55 -070091 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -070092 eventDispatcher.addSink(LinkEvent.class, listenerRegistry);
tom89b63c52014-09-16 09:19:51 -070093 deviceService.addListener(deviceListener);
tomdb0d03f2014-08-27 16:34:15 -070094 log.info("Started");
95 }
96
97 @Deactivate
98 public void deactivate() {
tomc78acee2014-09-24 15:16:55 -070099 store.unsetDelegate(delegate);
tom5f38b3a2014-08-27 23:50:54 -0700100 eventDispatcher.removeSink(LinkEvent.class);
tom89b63c52014-09-16 09:19:51 -0700101 deviceService.removeListener(deviceListener);
tomdb0d03f2014-08-27 16:34:15 -0700102 log.info("Stopped");
103 }
104
105 @Override
tomeadbb462014-09-07 16:10:19 -0700106 public int getLinkCount() {
107 return store.getLinkCount();
108 }
109
110 @Override
111 public Iterable<Link> getLinks() {
112 return store.getLinks();
113 }
114
115 @Override
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800116 public Iterable<Link> getActiveLinks() {
117 return FluentIterable.from(getLinks())
118 .filter(new Predicate<Link>() {
119
120 @Override
121 public boolean apply(Link input) {
122 return input.state() == State.ACTIVE;
123 }
124 });
125 }
126
127 @Override
tomeadbb462014-09-07 16:10:19 -0700128 public Set<Link> getDeviceLinks(DeviceId deviceId) {
129 checkNotNull(deviceId, DEVICE_ID_NULL);
130 return Sets.union(store.getDeviceEgressLinks(deviceId),
tomdc361b62014-09-09 20:36:52 -0700131 store.getDeviceIngressLinks(deviceId));
tomeadbb462014-09-07 16:10:19 -0700132 }
133
134 @Override
135 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
136 checkNotNull(deviceId, DEVICE_ID_NULL);
137 return store.getDeviceEgressLinks(deviceId);
138 }
139
140 @Override
tomd176fc42014-09-08 00:12:30 -0700141 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
tomeadbb462014-09-07 16:10:19 -0700142 checkNotNull(deviceId, DEVICE_ID_NULL);
143 return store.getDeviceIngressLinks(deviceId);
144 }
145
146 @Override
147 public Set<Link> getLinks(ConnectPoint connectPoint) {
148 checkNotNull(connectPoint, CONNECT_POINT_NULL);
149 return Sets.union(store.getEgressLinks(connectPoint),
tomdc361b62014-09-09 20:36:52 -0700150 store.getIngressLinks(connectPoint));
tomeadbb462014-09-07 16:10:19 -0700151 }
152
153 @Override
154 public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
155 checkNotNull(connectPoint, CONNECT_POINT_NULL);
156 return store.getEgressLinks(connectPoint);
157 }
158
159 @Override
tomd176fc42014-09-08 00:12:30 -0700160 public Set<Link> getIngressLinks(ConnectPoint connectPoint) {
tomeadbb462014-09-07 16:10:19 -0700161 checkNotNull(connectPoint, CONNECT_POINT_NULL);
162 return store.getIngressLinks(connectPoint);
163 }
164
165 @Override
tomd176fc42014-09-08 00:12:30 -0700166 public Link getLink(ConnectPoint src, ConnectPoint dst) {
tomeadbb462014-09-07 16:10:19 -0700167 checkNotNull(src, CONNECT_POINT_NULL);
168 checkNotNull(dst, CONNECT_POINT_NULL);
tomd176fc42014-09-08 00:12:30 -0700169 return store.getLink(src, dst);
tomeadbb462014-09-07 16:10:19 -0700170 }
171
172 @Override
173 public void removeLinks(ConnectPoint connectPoint) {
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700174 if (deviceService.getRole(connectPoint.deviceId()) != MastershipRole.MASTER) {
175 return;
176 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800177 removeLinks(getLinks(connectPoint), false);
tomeadbb462014-09-07 16:10:19 -0700178 }
179
180 @Override
181 public void removeLinks(DeviceId deviceId) {
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700182 if (deviceService.getRole(deviceId) != MastershipRole.MASTER) {
183 return;
184 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800185 removeLinks(getDeviceLinks(deviceId), false);
tomeadbb462014-09-07 16:10:19 -0700186 }
187
188 @Override
189 public void addListener(LinkListener listener) {
190 listenerRegistry.addListener(listener);
191 }
192
193 @Override
194 public void removeListener(LinkListener listener) {
195 listenerRegistry.removeListener(listener);
196 }
197
tom89b63c52014-09-16 09:19:51 -0700198 // Auxiliary interceptor for device remove events to prune links that
199 // are associated with the removed device or its port.
tomc78acee2014-09-24 15:16:55 -0700200 private class InternalDeviceListener implements DeviceListener {
tom89b63c52014-09-16 09:19:51 -0700201 @Override
202 public void event(DeviceEvent event) {
203 if (event.type() == DeviceEvent.Type.DEVICE_REMOVED) {
204 removeLinks(event.subject().id());
205 } else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
206 removeLinks(new ConnectPoint(event.subject().id(),
207 event.port().number()));
208 }
209 }
210 }
211
tom7869ad92014-09-09 14:32:08 -0700212 @Override
213 protected LinkProviderService createProviderService(LinkProvider provider) {
214 return new InternalLinkProviderService(provider);
215 }
216
tomdb0d03f2014-08-27 16:34:15 -0700217 // Personalized link provider service issued to the supplied provider.
tomdc361b62014-09-09 20:36:52 -0700218 private class InternalLinkProviderService
219 extends AbstractProviderService<LinkProvider>
220 implements LinkProviderService {
tomdb0d03f2014-08-27 16:34:15 -0700221
tomcfde0622014-09-09 11:02:42 -0700222 InternalLinkProviderService(LinkProvider provider) {
tomdb0d03f2014-08-27 16:34:15 -0700223 super(provider);
224 }
225
226 @Override
227 public void linkDetected(LinkDescription linkDescription) {
tomeadbb462014-09-07 16:10:19 -0700228 checkNotNull(linkDescription, LINK_DESC_NULL);
229 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700230
tomeadbb462014-09-07 16:10:19 -0700231 LinkEvent event = store.createOrUpdateLink(provider().id(),
tomdc361b62014-09-09 20:36:52 -0700232 linkDescription);
233 if (event != null) {
Thomas Vachuska0e752bd2014-10-22 22:33:41 -0700234 log.info("Link {} detected", linkDescription);
tomdc361b62014-09-09 20:36:52 -0700235 post(event);
236 }
tomdb0d03f2014-08-27 16:34:15 -0700237 }
238
239 @Override
240 public void linkVanished(LinkDescription linkDescription) {
tomeadbb462014-09-07 16:10:19 -0700241 checkNotNull(linkDescription, LINK_DESC_NULL);
242 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700243
244 ConnectPoint src = linkDescription.src();
245 ConnectPoint dst = linkDescription.dst();
alshabibdfc7afb2014-10-21 20:13:27 -0700246
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800247 LinkEvent event = store.removeOrDownLink(src, dst);
tomdc361b62014-09-09 20:36:52 -0700248 if (event != null) {
249 log.info("Link {} vanished", linkDescription);
250 post(event);
251 }
tomeadbb462014-09-07 16:10:19 -0700252 }
253
254 @Override
255 public void linksVanished(ConnectPoint connectPoint) {
256 checkNotNull(connectPoint, "Connect point cannot be null");
257 checkValidity();
alshabib12288c82014-10-23 10:24:23 -0700258
tomdc361b62014-09-09 20:36:52 -0700259 log.info("Links for connection point {} vanished", connectPoint);
Yuta HIGUCHIe794cbe2014-10-17 13:21:23 -0700260 // FIXME: This will remove links registered by other providers
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800261 removeLinks(getLinks(connectPoint), true);
tomeadbb462014-09-07 16:10:19 -0700262 }
263
264 @Override
265 public void linksVanished(DeviceId deviceId) {
266 checkNotNull(deviceId, DEVICE_ID_NULL);
267 checkValidity();
alshabib12288c82014-10-23 10:24:23 -0700268
tomdc361b62014-09-09 20:36:52 -0700269 log.info("Links for device {} vanished", deviceId);
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800270 removeLinks(getDeviceLinks(deviceId), true);
tomdb0d03f2014-08-27 16:34:15 -0700271 }
272 }
tomeadbb462014-09-07 16:10:19 -0700273
274 // Removes all links in the specified set and emits appropriate events.
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800275 private void removeLinks(Set<Link> links, boolean isSoftRemove) {
tomeadbb462014-09-07 16:10:19 -0700276 for (Link link : links) {
Ray Milkeyf2695402014-12-08 16:24:24 -0800277 final Device srcDevice = deviceService.getDevice(link.src().deviceId());
278 final Device dstDevice = deviceService.getDevice(link.dst().deviceId());
279 if (srcDevice != null &&
280 dstDevice != null &&
281 !srcDevice.type().equals(dstDevice.type())) {
282 //TODO this is awful. need to be fixed so that we don't down
Praseed Balakrishnan00dd1f92014-11-19 17:12:36 -0800283 // configured links. perhaps add a mechanism to figure out the
284 // state of this link
285 log.info("Ignoring removal of link as device types are " +
286 "different {} {} ",
287 link.src() ,
288 link.dst());
289 continue;
290 }
Thomas Vachuska57126fe2014-11-11 17:13:24 -0800291 LinkEvent event = isSoftRemove ?
292 store.removeOrDownLink(link.src(), link.dst()) :
293 store.removeLink(link.src(), link.dst());
tomeadbb462014-09-07 16:10:19 -0700294 post(event);
295 }
296 }
297
298 // Posts the specified event to the local event dispatcher.
299 private void post(LinkEvent event) {
tomdc361b62014-09-09 20:36:52 -0700300 if (event != null) {
tomeadbb462014-09-07 16:10:19 -0700301 eventDispatcher.post(event);
302 }
303 }
304
tomc78acee2014-09-24 15:16:55 -0700305 // Store delegate to re-post events emitted from the store.
306 private class InternalStoreDelegate implements LinkStoreDelegate {
307 @Override
308 public void notify(LinkEvent event) {
309 post(event);
310 }
311 }
tomdb0d03f2014-08-27 16:34:15 -0700312}