blob: 21f8152c84874539a86bcc49e670905d0f476499 [file] [log] [blame]
Madan Jampanibad538c2015-08-19 17:35:27 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Madan Jampanibad538c2015-08-19 17:35:27 -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 */
16package org.onosproject.store.link.impl;
17
Madan Jampanibad538c2015-08-19 17:35:27 -070018import java.util.Collection;
19import java.util.Map;
20import java.util.Objects;
21import java.util.Set;
22import java.util.concurrent.atomic.AtomicReference;
23import java.util.function.Predicate;
24import java.util.stream.Collectors;
25
26import org.apache.felix.scr.annotations.Activate;
27import org.apache.felix.scr.annotations.Component;
28import org.apache.felix.scr.annotations.Deactivate;
29import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
31import org.apache.felix.scr.annotations.Service;
32import org.onlab.util.KryoNamespace;
33import org.onlab.util.SharedExecutors;
34import org.onosproject.cluster.ClusterService;
35import org.onosproject.cluster.NodeId;
Ray Milkeyb7f0f642016-01-22 16:08:14 -080036import org.onosproject.core.ApplicationId;
37import org.onosproject.core.CoreService;
Madan Jampanibad538c2015-08-19 17:35:27 -070038import org.onosproject.mastership.MastershipService;
39import org.onosproject.net.AnnotationKeys;
40import org.onosproject.net.AnnotationsUtil;
41import org.onosproject.net.ConnectPoint;
42import org.onosproject.net.DefaultAnnotations;
43import org.onosproject.net.DefaultLink;
44import org.onosproject.net.DeviceId;
45import org.onosproject.net.Link;
Madan Jampanibad538c2015-08-19 17:35:27 -070046import org.onosproject.net.Link.Type;
Ray Milkeyb7f0f642016-01-22 16:08:14 -080047import org.onosproject.net.LinkKey;
48import org.onosproject.net.config.ConfigFactory;
49import org.onosproject.net.config.NetworkConfigEvent;
50import org.onosproject.net.config.NetworkConfigListener;
51import org.onosproject.net.config.NetworkConfigRegistry;
Madan Jampanibad538c2015-08-19 17:35:27 -070052import org.onosproject.net.device.DeviceClockService;
53import org.onosproject.net.link.DefaultLinkDescription;
54import org.onosproject.net.link.LinkDescription;
55import org.onosproject.net.link.LinkEvent;
56import org.onosproject.net.link.LinkStore;
57import org.onosproject.net.link.LinkStoreDelegate;
58import org.onosproject.net.provider.ProviderId;
59import org.onosproject.store.AbstractStore;
60import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
61import org.onosproject.store.cluster.messaging.MessageSubject;
62import org.onosproject.store.impl.MastershipBasedTimestamp;
63import org.onosproject.store.serializers.KryoNamespaces;
Madan Jampanibad538c2015-08-19 17:35:27 -070064import org.onosproject.store.serializers.custom.DistributedStoreSerializers;
65import org.onosproject.store.service.EventuallyConsistentMap;
66import org.onosproject.store.service.EventuallyConsistentMapEvent;
67import org.onosproject.store.service.EventuallyConsistentMapListener;
Jordan Haltermanc6c6ef22017-08-20 17:11:41 -070068import org.onosproject.store.service.Serializer;
Madan Jampanibad538c2015-08-19 17:35:27 -070069import org.onosproject.store.service.StorageService;
70import org.slf4j.Logger;
71
72import com.google.common.collect.Iterables;
73import com.google.common.collect.Maps;
kircaali28d67682016-04-11 15:08:14 +000074import com.google.common.collect.Sets;
Madan Jampanibad538c2015-08-19 17:35:27 -070075import com.google.common.util.concurrent.Futures;
76
Ray Milkeyb7f0f642016-01-22 16:08:14 -080077import static org.onosproject.net.DefaultAnnotations.union;
78import static org.onosproject.net.Link.State.ACTIVE;
79import static org.onosproject.net.Link.State.INACTIVE;
80import static org.onosproject.net.Link.Type.DIRECT;
81import static org.onosproject.net.Link.Type.INDIRECT;
82import static org.onosproject.net.LinkKey.linkKey;
83import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
84import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
85import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
86import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
87import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
88import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
89import static org.slf4j.LoggerFactory.getLogger;
90
Madan Jampanibad538c2015-08-19 17:35:27 -070091/**
92 * Manages the inventory of links using a {@code EventuallyConsistentMap}.
93 */
Sho SHIMIZU5c396e32016-08-12 15:19:12 -070094@Component(immediate = true)
Madan Jampanibad538c2015-08-19 17:35:27 -070095@Service
96public class ECLinkStore
kircaali28d67682016-04-11 15:08:14 +000097 extends AbstractStore<LinkEvent, LinkStoreDelegate>
98 implements LinkStore {
Madan Jampanibad538c2015-08-19 17:35:27 -070099
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800100 /**
101 * Modes for dealing with newly discovered links.
102 */
103 protected enum LinkDiscoveryMode {
104 /**
105 * Permissive mode - all newly discovered links are valid.
106 */
107 PERMISSIVE,
108
109 /**
110 * Strict mode - all newly discovered links must be defined in
111 * the network config.
112 */
113 STRICT
114 }
115
Madan Jampanibad538c2015-08-19 17:35:27 -0700116 private final Logger log = getLogger(getClass());
117
118 private final Map<LinkKey, Link> links = Maps.newConcurrentMap();
kircaali28d67682016-04-11 15:08:14 +0000119 private final Map<LinkKey, Set<ProviderId>> linkProviders = Maps.newConcurrentMap();
Madan Jampanibad538c2015-08-19 17:35:27 -0700120 private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions;
121
kircaali28d67682016-04-11 15:08:14 +0000122
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800123 private ApplicationId appId;
124
Madan Jampanibad538c2015-08-19 17:35:27 -0700125 private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request");
126
127 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 protected StorageService storageService;
129
130 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
131 protected MastershipService mastershipService;
132
133 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
134 protected DeviceClockService deviceClockService;
135
136 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
137 protected ClusterCommunicationService clusterCommunicator;
138
139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
140 protected ClusterService clusterService;
141
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800142 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 protected NetworkConfigRegistry netCfgService;
144
145 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
146 protected CoreService coreService;
147
Madan Jampanibad538c2015-08-19 17:35:27 -0700148 private EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> linkTracker =
149 new InternalLinkTracker();
150
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800151 // Listener for config changes
152 private final InternalConfigListener cfgListener = new InternalConfigListener();
153
154 protected LinkDiscoveryMode linkDiscoveryMode = LinkDiscoveryMode.STRICT;
155
Jordan Haltermanc6c6ef22017-08-20 17:11:41 -0700156 protected static final Serializer SERIALIZER = Serializer.using(
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700157 KryoNamespace.newBuilder()
Madan Jampanibad538c2015-08-19 17:35:27 -0700158 .register(DistributedStoreSerializers.STORE_COMMON)
159 .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
160 .register(Provided.class)
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700161 .build("ECLink"));
Madan Jampanibad538c2015-08-19 17:35:27 -0700162
163 @Activate
164 public void activate() {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800165 appId = coreService.registerApplication("org.onosproject.core");
166 netCfgService.registerConfigFactory(factory);
167 netCfgService.addListener(cfgListener);
168
169 cfgListener.reconfigure(netCfgService.getConfig(appId, CoreConfig.class));
170
Madan Jampanibad538c2015-08-19 17:35:27 -0700171 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
172 .register(KryoNamespaces.API)
173 .register(MastershipBasedTimestamp.class)
174 .register(Provided.class);
175
176 linkDescriptions = storageService.<Provided<LinkKey>, LinkDescription>eventuallyConsistentMapBuilder()
177 .withName("onos-link-descriptions")
178 .withSerializer(serializer)
179 .withTimestampProvider((k, v) -> {
180 try {
181 return v == null ? null : deviceClockService.getTimestamp(v.dst().deviceId());
182 } catch (IllegalStateException e) {
183 return null;
184 }
185 }).build();
186
187 clusterCommunicator.addSubscriber(LINK_INJECT_MESSAGE,
kircaali28d67682016-04-11 15:08:14 +0000188 SERIALIZER::decode,
189 this::injectLink,
190 SERIALIZER::encode,
191 SharedExecutors.getPoolThreadExecutor());
Madan Jampanibad538c2015-08-19 17:35:27 -0700192
193 linkDescriptions.addListener(linkTracker);
194
195 log.info("Started");
196 }
197
198 @Deactivate
199 public void deactivate() {
200 linkDescriptions.removeListener(linkTracker);
201 linkDescriptions.destroy();
kircaali28d67682016-04-11 15:08:14 +0000202 linkProviders.clear();
Madan Jampanibad538c2015-08-19 17:35:27 -0700203 links.clear();
204 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE);
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800205 netCfgService.removeListener(cfgListener);
206 netCfgService.unregisterConfigFactory(factory);
Madan Jampanibad538c2015-08-19 17:35:27 -0700207
208 log.info("Stopped");
209 }
210
211 @Override
212 public int getLinkCount() {
213 return links.size();
214 }
215
216 @Override
217 public Iterable<Link> getLinks() {
218 return links.values();
219 }
220
221 @Override
222 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
223 return filter(links.values(), link -> deviceId.equals(link.src().deviceId()));
224 }
225
226 @Override
227 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
228 return filter(links.values(), link -> deviceId.equals(link.dst().deviceId()));
229 }
230
231 @Override
232 public Link getLink(ConnectPoint src, ConnectPoint dst) {
233 return links.get(linkKey(src, dst));
234 }
235
236 @Override
237 public Set<Link> getEgressLinks(ConnectPoint src) {
238 return filter(links.values(), link -> src.equals(link.src()));
239 }
240
241 @Override
242 public Set<Link> getIngressLinks(ConnectPoint dst) {
243 return filter(links.values(), link -> dst.equals(link.dst()));
244 }
245
246 @Override
247 public LinkEvent createOrUpdateLink(ProviderId providerId,
248 LinkDescription linkDescription) {
249 final DeviceId dstDeviceId = linkDescription.dst().deviceId();
250 final NodeId dstNodeId = mastershipService.getMasterFor(dstDeviceId);
251
252 // Process link update only if we're the master of the destination node,
253 // otherwise signal the actual master.
254 if (clusterService.getLocalNode().id().equals(dstNodeId)) {
255 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700256 Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
257 if (internalLinkKey == null) {
258 return null;
259 }
Jian Li68c4fc42016-01-11 16:07:03 -0800260 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v, linkDescription));
Madan Jampanibad538c2015-08-19 17:35:27 -0700261 return refreshLinkCache(linkKey);
262 } else {
Thomas Vachuska1cf1fa42017-01-19 13:56:19 -0800263 // Only forward for ConfigProvider or NullProvider
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800264 // Forwarding was added as a workaround for ONOS-490
Jon Halla3fcf672017-03-28 16:53:22 -0700265 if (!"cfg".equals(providerId.scheme()) && !"null".equals(providerId.scheme())) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800266 return null;
267 }
268 // Temporary hack for NPE (ONOS-1171).
269 // Proper fix is to implement forwarding to master on ConfigProvider
Madan Jampanibad538c2015-08-19 17:35:27 -0700270 if (dstNodeId == null) {
271 return null;
272 }
273 return Futures.getUnchecked(clusterCommunicator.sendAndReceive(new Provided<>(linkDescription, providerId),
kircaali28d67682016-04-11 15:08:14 +0000274 LINK_INJECT_MESSAGE,
275 SERIALIZER::encode,
276 SERIALIZER::decode,
277 dstNodeId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700278 }
279 }
280
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700281 private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
282 ProviderId bpid = getBaseProviderId(linkKey);
283 if (provId == null) {
284 // The LinkService didn't know who this LinkKey belongs to.
285 // A fix is to either modify the getProvider() in LinkService classes
286 // or expose the contents of linkDescriptions to the LinkService.
287 return (bpid == null) ? null : new Provided<>(linkKey, bpid);
288 } else {
289 return new Provided<>(linkKey, provId);
290 }
291 }
292
Madan Jampanibad538c2015-08-19 17:35:27 -0700293 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
294 if (current != null) {
Yuta HIGUCHI40197862017-02-17 11:30:15 -0800295 Type type;
296 if (current.type() == DIRECT && updated.type() == Type.INDIRECT) {
297 // mask transition from DIRECT -> INDIRECT, likely to be triggered by BDDP
298 type = Type.DIRECT;
299 } else {
300 type = updated.type();
301 }
kircaali28d67682016-04-11 15:08:14 +0000302 return new DefaultLinkDescription(
303 current.src(),
304 current.dst(),
Yuta HIGUCHI40197862017-02-17 11:30:15 -0800305 type,
kircaali28d67682016-04-11 15:08:14 +0000306 current.isExpected(),
307 union(current.annotations(), updated.annotations()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700308 }
309 return updated;
310 }
311
kircaali28d67682016-04-11 15:08:14 +0000312 private Set<ProviderId> createOrUpdateLinkProviders(Set<ProviderId> current, ProviderId providerId) {
313 if (current == null) {
314 current = Sets.newConcurrentHashSet();
315 }
316 current.add(providerId);
317 return current;
318 }
319
Madan Jampanibad538c2015-08-19 17:35:27 -0700320 private LinkEvent refreshLinkCache(LinkKey linkKey) {
321 AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>();
322 Link link = links.compute(linkKey, (key, existingLink) -> {
323 Link newLink = composeLink(linkKey);
Madan Jampani11591862016-06-27 13:58:07 -0700324 if (newLink == null) {
325 return null;
326 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700327 if (existingLink == null) {
328 eventType.set(LINK_ADDED);
329 return newLink;
330 } else if (existingLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000331 existingLink.isExpected() != newLink.isExpected() ||
Yuta HIGUCHI40197862017-02-17 11:30:15 -0800332 (existingLink.type() != newLink.type()) ||
kircaali28d67682016-04-11 15:08:14 +0000333 !AnnotationsUtil.isEqual(existingLink.annotations(), newLink.annotations())) {
334 eventType.set(LINK_UPDATED);
335 return newLink;
Madan Jampanibad538c2015-08-19 17:35:27 -0700336 } else {
337 return existingLink;
338 }
339 });
340 return eventType.get() != null ? new LinkEvent(eventType.get(), link) : null;
341 }
342
343 private Set<ProviderId> getAllProviders(LinkKey linkKey) {
kircaali28d67682016-04-11 15:08:14 +0000344 return linkProviders.getOrDefault(linkKey, Sets.newConcurrentHashSet());
Madan Jampanibad538c2015-08-19 17:35:27 -0700345 }
346
347 private ProviderId getBaseProviderId(LinkKey linkKey) {
348 Set<ProviderId> allProviders = getAllProviders(linkKey);
349 if (allProviders.size() > 0) {
350 return allProviders.stream()
kircaali28d67682016-04-11 15:08:14 +0000351 .filter(p -> !p.isAncillary())
352 .findFirst()
353 .orElse(Iterables.getFirst(allProviders, null));
Madan Jampanibad538c2015-08-19 17:35:27 -0700354 }
355 return null;
356 }
357
358 private Link composeLink(LinkKey linkKey) {
359
Ray Milkey1bce6fb2016-07-15 13:38:53 -0700360 ProviderId baseProviderId = getBaseProviderId(linkKey);
361 if (baseProviderId == null) {
362 // provider was not found, this means it was already removed by the
363 // parent component.
364 return null;
365 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700366 LinkDescription base = linkDescriptions.get(new Provided<>(linkKey, baseProviderId));
Madan Jampani11591862016-06-27 13:58:07 -0700367 // short circuit if link description no longer exists
368 if (base == null) {
369 return null;
370 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700371 ConnectPoint src = base.src();
372 ConnectPoint dst = base.dst();
373 Type type = base.type();
Yuta HIGUCHI9eed0b12017-06-07 11:59:18 -0700374 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
375 builder.putAll(base.annotations());
Madan Jampanibad538c2015-08-19 17:35:27 -0700376
377 getAllProviders(linkKey).stream()
kircaali28d67682016-04-11 15:08:14 +0000378 .map(p -> new Provided<>(linkKey, p))
379 .forEach(key -> {
380 LinkDescription linkDescription = linkDescriptions.get(key);
381 if (linkDescription != null) {
Yuta HIGUCHI9eed0b12017-06-07 11:59:18 -0700382 builder.putAll(linkDescription.annotations());
kircaali28d67682016-04-11 15:08:14 +0000383 }
384 });
Madan Jampanibad538c2015-08-19 17:35:27 -0700385
Yuta HIGUCHI9eed0b12017-06-07 11:59:18 -0700386 DefaultAnnotations annotations = builder.build();
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800387 Link.State initialLinkState;
388
389 boolean isExpected;
390 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE) {
391 initialLinkState = ACTIVE;
392 isExpected =
Yuta HIGUCHI9eed0b12017-06-07 11:59:18 -0700393 Objects.equals(annotations.value(AnnotationKeys.DURABLE), "true");
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800394 } else {
395 initialLinkState = base.isExpected() ? ACTIVE : INACTIVE;
396 isExpected = base.isExpected();
397 }
398
399
Ray Milkey2693bda2016-01-22 16:08:14 -0800400 return DefaultLink.builder()
401 .providerId(baseProviderId)
402 .src(src)
403 .dst(dst)
404 .type(type)
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800405 .state(initialLinkState)
406 .isExpected(isExpected)
Yuta HIGUCHI9eed0b12017-06-07 11:59:18 -0700407 .annotations(annotations)
Ray Milkey2693bda2016-01-22 16:08:14 -0800408 .build();
Madan Jampanibad538c2015-08-19 17:35:27 -0700409 }
410
411 // Updates, if necessary the specified link and returns the appropriate event.
412 // Guarded by linkDescs value (=locking each Link)
413 private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
414 // Note: INDIRECT -> DIRECT transition only
415 // so that BDDP discovered Link will not overwrite LDDP Link
416 if (oldLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000417 (oldLink.type() == INDIRECT && newLink.type() == DIRECT) ||
418 !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700419
420 links.put(key, newLink);
421 return new LinkEvent(LINK_UPDATED, newLink);
422 }
423 return null;
424 }
425
426 @Override
427 public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) {
428 Link link = getLink(src, dst);
429 if (link == null) {
430 return null;
431 }
432
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800433 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE && link.isExpected()) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700434 // FIXME: this will not sync link state!!!
435 return link.state() == INACTIVE ? null :
436 updateLink(linkKey(link.src(), link.dst()), link,
Ray Milkey2693bda2016-01-22 16:08:14 -0800437 DefaultLink.builder()
438 .providerId(link.providerId())
439 .src(link.src())
440 .dst(link.dst())
441 .type(link.type())
442 .state(INACTIVE)
443 .isExpected(link.isExpected())
444 .annotations(link.annotations())
445 .build());
Madan Jampanibad538c2015-08-19 17:35:27 -0700446 }
447 return removeLink(src, dst);
448 }
449
450 @Override
451 public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
452 final LinkKey linkKey = LinkKey.linkKey(src, dst);
Madan Jampani5d4396f2015-09-02 16:04:20 -0700453 ProviderId primaryProviderId = getBaseProviderId(linkKey);
454 // Stop if there is no base provider.
455 if (primaryProviderId == null) {
456 return null;
457 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700458 LinkDescription removedLinkDescription =
Madan Jampani5d4396f2015-09-02 16:04:20 -0700459 linkDescriptions.remove(new Provided<>(linkKey, primaryProviderId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700460 if (removedLinkDescription != null) {
461 return purgeLinkCache(linkKey);
462 }
463 return null;
464 }
465
466 private LinkEvent purgeLinkCache(LinkKey linkKey) {
467 Link removedLink = links.remove(linkKey);
468 if (removedLink != null) {
469 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p)));
kircaali28d67682016-04-11 15:08:14 +0000470 linkProviders.remove(linkKey);
Madan Jampanibad538c2015-08-19 17:35:27 -0700471 return new LinkEvent(LINK_REMOVED, removedLink);
472 }
473 return null;
474 }
475
476 private Set<Link> filter(Collection<Link> links, Predicate<Link> predicate) {
477 return links.stream().filter(predicate).collect(Collectors.toSet());
478 }
479
480 private LinkEvent injectLink(Provided<LinkDescription> linkInjectRequest) {
481 log.trace("Received request to inject link {}", linkInjectRequest);
482
483 ProviderId providerId = linkInjectRequest.providerId();
484 LinkDescription linkDescription = linkInjectRequest.key();
485
486 final DeviceId deviceId = linkDescription.dst().deviceId();
487 if (!deviceClockService.isTimestampAvailable(deviceId)) {
488 // workaround for ONOS-1208
489 log.warn("Not ready to accept update. Dropping {}", linkInjectRequest);
490 return null;
491 }
492 return createOrUpdateLink(providerId, linkDescription);
493 }
494
495 private class InternalLinkTracker implements EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> {
496 @Override
497 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) {
498 if (event.type() == PUT) {
kircaali28d67682016-04-11 15:08:14 +0000499 linkProviders.compute(event.key().key(), (k, v) ->
500 createOrUpdateLinkProviders(v, event.key().providerId()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700501 notifyDelegate(refreshLinkCache(event.key().key()));
502 } else if (event.type() == REMOVE) {
503 notifyDelegate(purgeLinkCache(event.key().key()));
kircaali28d67682016-04-11 15:08:14 +0000504 linkProviders.remove(event.key().key());
Madan Jampanibad538c2015-08-19 17:35:27 -0700505 }
506 }
507 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800508
509 private class InternalConfigListener implements NetworkConfigListener {
510
511 void reconfigure(CoreConfig coreConfig) {
512 if (coreConfig == null) {
513 linkDiscoveryMode = LinkDiscoveryMode.PERMISSIVE;
514 } else {
515 linkDiscoveryMode = coreConfig.linkDiscoveryMode();
516 }
517 if (linkDiscoveryMode == LinkDiscoveryMode.STRICT) {
518 // Remove any previous links to force them to go through the strict
519 // discovery process
Ray Milkey15551272016-02-10 16:22:02 -0800520 if (linkDescriptions != null) {
521 linkDescriptions.clear();
522 }
523 if (links != null) {
524 links.clear();
525 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800526 }
527 log.debug("config set link discovery mode to {}",
528 linkDiscoveryMode.name());
529 }
530
531 @Override
532 public void event(NetworkConfigEvent event) {
533
534 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
535 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
536 event.configClass().equals(CoreConfig.class)) {
537
538 CoreConfig cfg = netCfgService.getConfig(appId, CoreConfig.class);
539 reconfigure(cfg);
540 log.info("Reconfigured");
541 }
542 }
543 }
544
545 // Configuration properties factory
546 private final ConfigFactory factory =
547 new ConfigFactory<ApplicationId, CoreConfig>(APP_SUBJECT_FACTORY,
kircaali28d67682016-04-11 15:08:14 +0000548 CoreConfig.class,
549 "core") {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800550 @Override
551 public CoreConfig createConfig() {
552 return new CoreConfig();
553 }
554 };
Ray Milkeyd0dd1352016-01-19 10:58:41 -0800555}