blob: d93672e01466b8fb1fb23c028ec4244bf3562a04 [file] [log] [blame]
Madan Jampanibad538c2015-08-19 17:35:27 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
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;
HIGUCHI Yutae7290652016-05-18 11:29:01 -070064import org.onosproject.store.serializers.StoreSerializer;
Madan Jampanibad538c2015-08-19 17:35:27 -070065import org.onosproject.store.serializers.custom.DistributedStoreSerializers;
66import org.onosproject.store.service.EventuallyConsistentMap;
67import org.onosproject.store.service.EventuallyConsistentMapEvent;
68import org.onosproject.store.service.EventuallyConsistentMapListener;
69import 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.merge;
78import static org.onosproject.net.DefaultAnnotations.union;
79import static org.onosproject.net.Link.State.ACTIVE;
80import static org.onosproject.net.Link.State.INACTIVE;
81import static org.onosproject.net.Link.Type.DIRECT;
82import static org.onosproject.net.Link.Type.INDIRECT;
83import static org.onosproject.net.LinkKey.linkKey;
84import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
85import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
86import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
87import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
88import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
89import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
90import static org.slf4j.LoggerFactory.getLogger;
91
Madan Jampanibad538c2015-08-19 17:35:27 -070092/**
93 * Manages the inventory of links using a {@code EventuallyConsistentMap}.
94 */
Sho SHIMIZU5c396e32016-08-12 15:19:12 -070095@Component(immediate = true)
Madan Jampanibad538c2015-08-19 17:35:27 -070096@Service
97public class ECLinkStore
kircaali28d67682016-04-11 15:08:14 +000098 extends AbstractStore<LinkEvent, LinkStoreDelegate>
99 implements LinkStore {
Madan Jampanibad538c2015-08-19 17:35:27 -0700100
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800101 /**
102 * Modes for dealing with newly discovered links.
103 */
104 protected enum LinkDiscoveryMode {
105 /**
106 * Permissive mode - all newly discovered links are valid.
107 */
108 PERMISSIVE,
109
110 /**
111 * Strict mode - all newly discovered links must be defined in
112 * the network config.
113 */
114 STRICT
115 }
116
Madan Jampanibad538c2015-08-19 17:35:27 -0700117 private final Logger log = getLogger(getClass());
118
119 private final Map<LinkKey, Link> links = Maps.newConcurrentMap();
kircaali28d67682016-04-11 15:08:14 +0000120 private final Map<LinkKey, Set<ProviderId>> linkProviders = Maps.newConcurrentMap();
Madan Jampanibad538c2015-08-19 17:35:27 -0700121 private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions;
122
kircaali28d67682016-04-11 15:08:14 +0000123
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800124 private ApplicationId appId;
125
Madan Jampanibad538c2015-08-19 17:35:27 -0700126 private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request");
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
129 protected StorageService storageService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
132 protected MastershipService mastershipService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected DeviceClockService deviceClockService;
136
137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
138 protected ClusterCommunicationService clusterCommunicator;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected ClusterService clusterService;
142
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
144 protected NetworkConfigRegistry netCfgService;
145
146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected CoreService coreService;
148
Madan Jampanibad538c2015-08-19 17:35:27 -0700149 private EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> linkTracker =
150 new InternalLinkTracker();
151
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800152 // Listener for config changes
153 private final InternalConfigListener cfgListener = new InternalConfigListener();
154
155 protected LinkDiscoveryMode linkDiscoveryMode = LinkDiscoveryMode.STRICT;
156
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700157 protected static final StoreSerializer SERIALIZER = StoreSerializer.using(
158 KryoNamespace.newBuilder()
Madan Jampanibad538c2015-08-19 17:35:27 -0700159 .register(DistributedStoreSerializers.STORE_COMMON)
160 .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
161 .register(Provided.class)
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700162 .build("ECLink"));
Madan Jampanibad538c2015-08-19 17:35:27 -0700163
164 @Activate
165 public void activate() {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800166 appId = coreService.registerApplication("org.onosproject.core");
167 netCfgService.registerConfigFactory(factory);
168 netCfgService.addListener(cfgListener);
169
170 cfgListener.reconfigure(netCfgService.getConfig(appId, CoreConfig.class));
171
Madan Jampanibad538c2015-08-19 17:35:27 -0700172 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
173 .register(KryoNamespaces.API)
174 .register(MastershipBasedTimestamp.class)
175 .register(Provided.class);
176
177 linkDescriptions = storageService.<Provided<LinkKey>, LinkDescription>eventuallyConsistentMapBuilder()
178 .withName("onos-link-descriptions")
179 .withSerializer(serializer)
180 .withTimestampProvider((k, v) -> {
181 try {
182 return v == null ? null : deviceClockService.getTimestamp(v.dst().deviceId());
183 } catch (IllegalStateException e) {
184 return null;
185 }
186 }).build();
187
188 clusterCommunicator.addSubscriber(LINK_INJECT_MESSAGE,
kircaali28d67682016-04-11 15:08:14 +0000189 SERIALIZER::decode,
190 this::injectLink,
191 SERIALIZER::encode,
192 SharedExecutors.getPoolThreadExecutor());
Madan Jampanibad538c2015-08-19 17:35:27 -0700193
194 linkDescriptions.addListener(linkTracker);
195
196 log.info("Started");
197 }
198
199 @Deactivate
200 public void deactivate() {
201 linkDescriptions.removeListener(linkTracker);
202 linkDescriptions.destroy();
kircaali28d67682016-04-11 15:08:14 +0000203 linkProviders.clear();
Madan Jampanibad538c2015-08-19 17:35:27 -0700204 links.clear();
205 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE);
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800206 netCfgService.removeListener(cfgListener);
207 netCfgService.unregisterConfigFactory(factory);
Madan Jampanibad538c2015-08-19 17:35:27 -0700208
209 log.info("Stopped");
210 }
211
212 @Override
213 public int getLinkCount() {
214 return links.size();
215 }
216
217 @Override
218 public Iterable<Link> getLinks() {
219 return links.values();
220 }
221
222 @Override
223 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
224 return filter(links.values(), link -> deviceId.equals(link.src().deviceId()));
225 }
226
227 @Override
228 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
229 return filter(links.values(), link -> deviceId.equals(link.dst().deviceId()));
230 }
231
232 @Override
233 public Link getLink(ConnectPoint src, ConnectPoint dst) {
234 return links.get(linkKey(src, dst));
235 }
236
237 @Override
238 public Set<Link> getEgressLinks(ConnectPoint src) {
239 return filter(links.values(), link -> src.equals(link.src()));
240 }
241
242 @Override
243 public Set<Link> getIngressLinks(ConnectPoint dst) {
244 return filter(links.values(), link -> dst.equals(link.dst()));
245 }
246
247 @Override
248 public LinkEvent createOrUpdateLink(ProviderId providerId,
249 LinkDescription linkDescription) {
250 final DeviceId dstDeviceId = linkDescription.dst().deviceId();
251 final NodeId dstNodeId = mastershipService.getMasterFor(dstDeviceId);
252
253 // Process link update only if we're the master of the destination node,
254 // otherwise signal the actual master.
255 if (clusterService.getLocalNode().id().equals(dstNodeId)) {
256 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700257 Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
258 if (internalLinkKey == null) {
259 return null;
260 }
Jian Li68c4fc42016-01-11 16:07:03 -0800261 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v, linkDescription));
Madan Jampanibad538c2015-08-19 17:35:27 -0700262 return refreshLinkCache(linkKey);
263 } else {
Thomas Vachuska1cf1fa42017-01-19 13:56:19 -0800264 // Only forward for ConfigProvider or NullProvider
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800265 // Forwarding was added as a workaround for ONOS-490
Thomas Vachuska1cf1fa42017-01-19 13:56:19 -0800266 if (!providerId.scheme().equals("cfg") && !providerId.scheme().equals("null")) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800267 return null;
268 }
269 // Temporary hack for NPE (ONOS-1171).
270 // Proper fix is to implement forwarding to master on ConfigProvider
Madan Jampanibad538c2015-08-19 17:35:27 -0700271 if (dstNodeId == null) {
272 return null;
273 }
274 return Futures.getUnchecked(clusterCommunicator.sendAndReceive(new Provided<>(linkDescription, providerId),
kircaali28d67682016-04-11 15:08:14 +0000275 LINK_INJECT_MESSAGE,
276 SERIALIZER::encode,
277 SERIALIZER::decode,
278 dstNodeId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700279 }
280 }
281
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700282 private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
283 ProviderId bpid = getBaseProviderId(linkKey);
284 if (provId == null) {
285 // The LinkService didn't know who this LinkKey belongs to.
286 // A fix is to either modify the getProvider() in LinkService classes
287 // or expose the contents of linkDescriptions to the LinkService.
288 return (bpid == null) ? null : new Provided<>(linkKey, bpid);
289 } else {
290 return new Provided<>(linkKey, provId);
291 }
292 }
293
Madan Jampanibad538c2015-08-19 17:35:27 -0700294 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
295 if (current != null) {
296 // we only allow transition from INDIRECT -> DIRECT
kircaali28d67682016-04-11 15:08:14 +0000297 return new DefaultLinkDescription(
298 current.src(),
299 current.dst(),
300 current.type() == DIRECT ? DIRECT : updated.type(),
301 current.isExpected(),
302 union(current.annotations(), updated.annotations()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700303 }
304 return updated;
305 }
306
kircaali28d67682016-04-11 15:08:14 +0000307 private Set<ProviderId> createOrUpdateLinkProviders(Set<ProviderId> current, ProviderId providerId) {
308 if (current == null) {
309 current = Sets.newConcurrentHashSet();
310 }
311 current.add(providerId);
312 return current;
313 }
314
Madan Jampanibad538c2015-08-19 17:35:27 -0700315 private LinkEvent refreshLinkCache(LinkKey linkKey) {
316 AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>();
317 Link link = links.compute(linkKey, (key, existingLink) -> {
318 Link newLink = composeLink(linkKey);
Madan Jampani11591862016-06-27 13:58:07 -0700319 if (newLink == null) {
320 return null;
321 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700322 if (existingLink == null) {
323 eventType.set(LINK_ADDED);
324 return newLink;
325 } else if (existingLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000326 existingLink.isExpected() != newLink.isExpected() ||
327 (existingLink.type() == INDIRECT && newLink.type() == DIRECT) ||
328 !AnnotationsUtil.isEqual(existingLink.annotations(), newLink.annotations())) {
329 eventType.set(LINK_UPDATED);
330 return newLink;
Madan Jampanibad538c2015-08-19 17:35:27 -0700331 } else {
332 return existingLink;
333 }
334 });
335 return eventType.get() != null ? new LinkEvent(eventType.get(), link) : null;
336 }
337
338 private Set<ProviderId> getAllProviders(LinkKey linkKey) {
kircaali28d67682016-04-11 15:08:14 +0000339 return linkProviders.getOrDefault(linkKey, Sets.newConcurrentHashSet());
Madan Jampanibad538c2015-08-19 17:35:27 -0700340 }
341
342 private ProviderId getBaseProviderId(LinkKey linkKey) {
343 Set<ProviderId> allProviders = getAllProviders(linkKey);
344 if (allProviders.size() > 0) {
345 return allProviders.stream()
kircaali28d67682016-04-11 15:08:14 +0000346 .filter(p -> !p.isAncillary())
347 .findFirst()
348 .orElse(Iterables.getFirst(allProviders, null));
Madan Jampanibad538c2015-08-19 17:35:27 -0700349 }
350 return null;
351 }
352
353 private Link composeLink(LinkKey linkKey) {
354
Ray Milkey1bce6fb2016-07-15 13:38:53 -0700355 ProviderId baseProviderId = getBaseProviderId(linkKey);
356 if (baseProviderId == null) {
357 // provider was not found, this means it was already removed by the
358 // parent component.
359 return null;
360 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700361 LinkDescription base = linkDescriptions.get(new Provided<>(linkKey, baseProviderId));
Madan Jampani11591862016-06-27 13:58:07 -0700362 // short circuit if link description no longer exists
363 if (base == null) {
364 return null;
365 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700366 ConnectPoint src = base.src();
367 ConnectPoint dst = base.dst();
368 Type type = base.type();
369 AtomicReference<DefaultAnnotations> annotations = new AtomicReference<>(DefaultAnnotations.builder().build());
370 annotations.set(merge(annotations.get(), base.annotations()));
371
372 getAllProviders(linkKey).stream()
kircaali28d67682016-04-11 15:08:14 +0000373 .map(p -> new Provided<>(linkKey, p))
374 .forEach(key -> {
375 LinkDescription linkDescription = linkDescriptions.get(key);
376 if (linkDescription != null) {
377 annotations.set(merge(annotations.get(),
378 linkDescription.annotations()));
379 }
380 });
Madan Jampanibad538c2015-08-19 17:35:27 -0700381
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800382 Link.State initialLinkState;
383
384 boolean isExpected;
385 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE) {
386 initialLinkState = ACTIVE;
387 isExpected =
388 Objects.equals(annotations.get().value(AnnotationKeys.DURABLE), "true");
389 } else {
390 initialLinkState = base.isExpected() ? ACTIVE : INACTIVE;
391 isExpected = base.isExpected();
392 }
393
394
Ray Milkey2693bda2016-01-22 16:08:14 -0800395 return DefaultLink.builder()
396 .providerId(baseProviderId)
397 .src(src)
398 .dst(dst)
399 .type(type)
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800400 .state(initialLinkState)
401 .isExpected(isExpected)
Ray Milkey2693bda2016-01-22 16:08:14 -0800402 .annotations(annotations.get())
403 .build();
Madan Jampanibad538c2015-08-19 17:35:27 -0700404 }
405
406 // Updates, if necessary the specified link and returns the appropriate event.
407 // Guarded by linkDescs value (=locking each Link)
408 private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
409 // Note: INDIRECT -> DIRECT transition only
410 // so that BDDP discovered Link will not overwrite LDDP Link
411 if (oldLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000412 (oldLink.type() == INDIRECT && newLink.type() == DIRECT) ||
413 !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700414
415 links.put(key, newLink);
416 return new LinkEvent(LINK_UPDATED, newLink);
417 }
418 return null;
419 }
420
421 @Override
422 public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) {
423 Link link = getLink(src, dst);
424 if (link == null) {
425 return null;
426 }
427
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800428 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE && link.isExpected()) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700429 // FIXME: this will not sync link state!!!
430 return link.state() == INACTIVE ? null :
431 updateLink(linkKey(link.src(), link.dst()), link,
Ray Milkey2693bda2016-01-22 16:08:14 -0800432 DefaultLink.builder()
433 .providerId(link.providerId())
434 .src(link.src())
435 .dst(link.dst())
436 .type(link.type())
437 .state(INACTIVE)
438 .isExpected(link.isExpected())
439 .annotations(link.annotations())
440 .build());
Madan Jampanibad538c2015-08-19 17:35:27 -0700441 }
442 return removeLink(src, dst);
443 }
444
445 @Override
446 public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
447 final LinkKey linkKey = LinkKey.linkKey(src, dst);
Madan Jampani5d4396f2015-09-02 16:04:20 -0700448 ProviderId primaryProviderId = getBaseProviderId(linkKey);
449 // Stop if there is no base provider.
450 if (primaryProviderId == null) {
451 return null;
452 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700453 LinkDescription removedLinkDescription =
Madan Jampani5d4396f2015-09-02 16:04:20 -0700454 linkDescriptions.remove(new Provided<>(linkKey, primaryProviderId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700455 if (removedLinkDescription != null) {
456 return purgeLinkCache(linkKey);
457 }
458 return null;
459 }
460
461 private LinkEvent purgeLinkCache(LinkKey linkKey) {
462 Link removedLink = links.remove(linkKey);
463 if (removedLink != null) {
464 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p)));
kircaali28d67682016-04-11 15:08:14 +0000465 linkProviders.remove(linkKey);
Madan Jampanibad538c2015-08-19 17:35:27 -0700466 return new LinkEvent(LINK_REMOVED, removedLink);
467 }
468 return null;
469 }
470
471 private Set<Link> filter(Collection<Link> links, Predicate<Link> predicate) {
472 return links.stream().filter(predicate).collect(Collectors.toSet());
473 }
474
475 private LinkEvent injectLink(Provided<LinkDescription> linkInjectRequest) {
476 log.trace("Received request to inject link {}", linkInjectRequest);
477
478 ProviderId providerId = linkInjectRequest.providerId();
479 LinkDescription linkDescription = linkInjectRequest.key();
480
481 final DeviceId deviceId = linkDescription.dst().deviceId();
482 if (!deviceClockService.isTimestampAvailable(deviceId)) {
483 // workaround for ONOS-1208
484 log.warn("Not ready to accept update. Dropping {}", linkInjectRequest);
485 return null;
486 }
487 return createOrUpdateLink(providerId, linkDescription);
488 }
489
490 private class InternalLinkTracker implements EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> {
491 @Override
492 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) {
493 if (event.type() == PUT) {
kircaali28d67682016-04-11 15:08:14 +0000494 linkProviders.compute(event.key().key(), (k, v) ->
495 createOrUpdateLinkProviders(v, event.key().providerId()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700496 notifyDelegate(refreshLinkCache(event.key().key()));
497 } else if (event.type() == REMOVE) {
498 notifyDelegate(purgeLinkCache(event.key().key()));
kircaali28d67682016-04-11 15:08:14 +0000499 linkProviders.remove(event.key().key());
Madan Jampanibad538c2015-08-19 17:35:27 -0700500 }
501 }
502 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800503
504 private class InternalConfigListener implements NetworkConfigListener {
505
506 void reconfigure(CoreConfig coreConfig) {
507 if (coreConfig == null) {
508 linkDiscoveryMode = LinkDiscoveryMode.PERMISSIVE;
509 } else {
510 linkDiscoveryMode = coreConfig.linkDiscoveryMode();
511 }
512 if (linkDiscoveryMode == LinkDiscoveryMode.STRICT) {
513 // Remove any previous links to force them to go through the strict
514 // discovery process
Ray Milkey15551272016-02-10 16:22:02 -0800515 if (linkDescriptions != null) {
516 linkDescriptions.clear();
517 }
518 if (links != null) {
519 links.clear();
520 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800521 }
522 log.debug("config set link discovery mode to {}",
523 linkDiscoveryMode.name());
524 }
525
526 @Override
527 public void event(NetworkConfigEvent event) {
528
529 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
530 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
531 event.configClass().equals(CoreConfig.class)) {
532
533 CoreConfig cfg = netCfgService.getConfig(appId, CoreConfig.class);
534 reconfigure(cfg);
535 log.info("Reconfigured");
536 }
537 }
538 }
539
540 // Configuration properties factory
541 private final ConfigFactory factory =
542 new ConfigFactory<ApplicationId, CoreConfig>(APP_SUBJECT_FACTORY,
kircaali28d67682016-04-11 15:08:14 +0000543 CoreConfig.class,
544 "core") {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800545 @Override
546 public CoreConfig createConfig() {
547 return new CoreConfig();
548 }
549 };
Ray Milkeyd0dd1352016-01-19 10:58:41 -0800550}