blob: 407377ef4a28e762f85f7fc012c2d46f04c5dd91 [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 com.google.common.base.Preconditions.checkNotNull;
78import static org.onosproject.net.DefaultAnnotations.merge;
79import static org.onosproject.net.DefaultAnnotations.union;
80import static org.onosproject.net.Link.State.ACTIVE;
81import static org.onosproject.net.Link.State.INACTIVE;
82import static org.onosproject.net.Link.Type.DIRECT;
83import static org.onosproject.net.Link.Type.INDIRECT;
84import static org.onosproject.net.LinkKey.linkKey;
85import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
86import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
87import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED;
88import static org.onosproject.net.link.LinkEvent.Type.LINK_UPDATED;
89import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.PUT;
90import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.REMOVE;
91import static org.slf4j.LoggerFactory.getLogger;
92
Madan Jampanibad538c2015-08-19 17:35:27 -070093/**
94 * Manages the inventory of links using a {@code EventuallyConsistentMap}.
95 */
Madan Jampani8856ee12015-08-21 09:24:27 -070096@Component(immediate = true, enabled = true)
Madan Jampanibad538c2015-08-19 17:35:27 -070097@Service
98public class ECLinkStore
kircaali28d67682016-04-11 15:08:14 +000099 extends AbstractStore<LinkEvent, LinkStoreDelegate>
100 implements LinkStore {
Madan Jampanibad538c2015-08-19 17:35:27 -0700101
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800102 /**
103 * Modes for dealing with newly discovered links.
104 */
105 protected enum LinkDiscoveryMode {
106 /**
107 * Permissive mode - all newly discovered links are valid.
108 */
109 PERMISSIVE,
110
111 /**
112 * Strict mode - all newly discovered links must be defined in
113 * the network config.
114 */
115 STRICT
116 }
117
Madan Jampanibad538c2015-08-19 17:35:27 -0700118 private final Logger log = getLogger(getClass());
119
120 private final Map<LinkKey, Link> links = Maps.newConcurrentMap();
kircaali28d67682016-04-11 15:08:14 +0000121 private final Map<LinkKey, Set<ProviderId>> linkProviders = Maps.newConcurrentMap();
Madan Jampanibad538c2015-08-19 17:35:27 -0700122 private EventuallyConsistentMap<Provided<LinkKey>, LinkDescription> linkDescriptions;
123
kircaali28d67682016-04-11 15:08:14 +0000124
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800125 private ApplicationId appId;
126
Madan Jampanibad538c2015-08-19 17:35:27 -0700127 private static final MessageSubject LINK_INJECT_MESSAGE = new MessageSubject("inject-link-request");
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 protected StorageService storageService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 protected MastershipService mastershipService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected DeviceClockService deviceClockService;
137
138 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
139 protected ClusterCommunicationService clusterCommunicator;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected ClusterService clusterService;
143
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800144 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
145 protected NetworkConfigRegistry netCfgService;
146
147 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
148 protected CoreService coreService;
149
Madan Jampanibad538c2015-08-19 17:35:27 -0700150 private EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> linkTracker =
151 new InternalLinkTracker();
152
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800153 // Listener for config changes
154 private final InternalConfigListener cfgListener = new InternalConfigListener();
155
156 protected LinkDiscoveryMode linkDiscoveryMode = LinkDiscoveryMode.STRICT;
157
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700158 protected static final StoreSerializer SERIALIZER = StoreSerializer.using(
159 KryoNamespace.newBuilder()
Madan Jampanibad538c2015-08-19 17:35:27 -0700160 .register(DistributedStoreSerializers.STORE_COMMON)
161 .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
162 .register(Provided.class)
HIGUCHI Yutae7290652016-05-18 11:29:01 -0700163 .build("ECLink"));
Madan Jampanibad538c2015-08-19 17:35:27 -0700164
165 @Activate
166 public void activate() {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800167 appId = coreService.registerApplication("org.onosproject.core");
168 netCfgService.registerConfigFactory(factory);
169 netCfgService.addListener(cfgListener);
170
171 cfgListener.reconfigure(netCfgService.getConfig(appId, CoreConfig.class));
172
Madan Jampanibad538c2015-08-19 17:35:27 -0700173 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
174 .register(KryoNamespaces.API)
175 .register(MastershipBasedTimestamp.class)
176 .register(Provided.class);
177
178 linkDescriptions = storageService.<Provided<LinkKey>, LinkDescription>eventuallyConsistentMapBuilder()
179 .withName("onos-link-descriptions")
180 .withSerializer(serializer)
181 .withTimestampProvider((k, v) -> {
182 try {
183 return v == null ? null : deviceClockService.getTimestamp(v.dst().deviceId());
184 } catch (IllegalStateException e) {
185 return null;
186 }
187 }).build();
188
189 clusterCommunicator.addSubscriber(LINK_INJECT_MESSAGE,
kircaali28d67682016-04-11 15:08:14 +0000190 SERIALIZER::decode,
191 this::injectLink,
192 SERIALIZER::encode,
193 SharedExecutors.getPoolThreadExecutor());
Madan Jampanibad538c2015-08-19 17:35:27 -0700194
195 linkDescriptions.addListener(linkTracker);
196
197 log.info("Started");
198 }
199
200 @Deactivate
201 public void deactivate() {
202 linkDescriptions.removeListener(linkTracker);
203 linkDescriptions.destroy();
kircaali28d67682016-04-11 15:08:14 +0000204 linkProviders.clear();
Madan Jampanibad538c2015-08-19 17:35:27 -0700205 links.clear();
206 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE);
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800207 netCfgService.removeListener(cfgListener);
208 netCfgService.unregisterConfigFactory(factory);
Madan Jampanibad538c2015-08-19 17:35:27 -0700209
210 log.info("Stopped");
211 }
212
213 @Override
214 public int getLinkCount() {
215 return links.size();
216 }
217
218 @Override
219 public Iterable<Link> getLinks() {
220 return links.values();
221 }
222
223 @Override
224 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
225 return filter(links.values(), link -> deviceId.equals(link.src().deviceId()));
226 }
227
228 @Override
229 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
230 return filter(links.values(), link -> deviceId.equals(link.dst().deviceId()));
231 }
232
233 @Override
234 public Link getLink(ConnectPoint src, ConnectPoint dst) {
235 return links.get(linkKey(src, dst));
236 }
237
238 @Override
239 public Set<Link> getEgressLinks(ConnectPoint src) {
240 return filter(links.values(), link -> src.equals(link.src()));
241 }
242
243 @Override
244 public Set<Link> getIngressLinks(ConnectPoint dst) {
245 return filter(links.values(), link -> dst.equals(link.dst()));
246 }
247
248 @Override
249 public LinkEvent createOrUpdateLink(ProviderId providerId,
250 LinkDescription linkDescription) {
251 final DeviceId dstDeviceId = linkDescription.dst().deviceId();
252 final NodeId dstNodeId = mastershipService.getMasterFor(dstDeviceId);
253
254 // Process link update only if we're the master of the destination node,
255 // otherwise signal the actual master.
256 if (clusterService.getLocalNode().id().equals(dstNodeId)) {
257 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700258 Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
259 if (internalLinkKey == null) {
260 return null;
261 }
Jian Li68c4fc42016-01-11 16:07:03 -0800262 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v, linkDescription));
Madan Jampanibad538c2015-08-19 17:35:27 -0700263 return refreshLinkCache(linkKey);
264 } else {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800265 // Only forward for ConfigProvider
266 // Forwarding was added as a workaround for ONOS-490
HIGUCHI Yuta4ea4e422016-01-13 16:40:34 -0800267 if (!providerId.scheme().equals("cfg")) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800268 return null;
269 }
270 // Temporary hack for NPE (ONOS-1171).
271 // Proper fix is to implement forwarding to master on ConfigProvider
Madan Jampanibad538c2015-08-19 17:35:27 -0700272 if (dstNodeId == null) {
273 return null;
274 }
275 return Futures.getUnchecked(clusterCommunicator.sendAndReceive(new Provided<>(linkDescription, providerId),
kircaali28d67682016-04-11 15:08:14 +0000276 LINK_INJECT_MESSAGE,
277 SERIALIZER::encode,
278 SERIALIZER::decode,
279 dstNodeId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700280 }
281 }
282
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700283 private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
284 ProviderId bpid = getBaseProviderId(linkKey);
285 if (provId == null) {
286 // The LinkService didn't know who this LinkKey belongs to.
287 // A fix is to either modify the getProvider() in LinkService classes
288 // or expose the contents of linkDescriptions to the LinkService.
289 return (bpid == null) ? null : new Provided<>(linkKey, bpid);
290 } else {
291 return new Provided<>(linkKey, provId);
292 }
293 }
294
Madan Jampanibad538c2015-08-19 17:35:27 -0700295 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
296 if (current != null) {
297 // we only allow transition from INDIRECT -> DIRECT
kircaali28d67682016-04-11 15:08:14 +0000298 return new DefaultLinkDescription(
299 current.src(),
300 current.dst(),
301 current.type() == DIRECT ? DIRECT : updated.type(),
302 current.isExpected(),
303 union(current.annotations(), updated.annotations()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700304 }
305 return updated;
306 }
307
kircaali28d67682016-04-11 15:08:14 +0000308 private Set<ProviderId> createOrUpdateLinkProviders(Set<ProviderId> current, ProviderId providerId) {
309 if (current == null) {
310 current = Sets.newConcurrentHashSet();
311 }
312 current.add(providerId);
313 return current;
314 }
315
Madan Jampanibad538c2015-08-19 17:35:27 -0700316 private LinkEvent refreshLinkCache(LinkKey linkKey) {
317 AtomicReference<LinkEvent.Type> eventType = new AtomicReference<>();
318 Link link = links.compute(linkKey, (key, existingLink) -> {
319 Link newLink = composeLink(linkKey);
320 if (existingLink == null) {
321 eventType.set(LINK_ADDED);
322 return newLink;
323 } else if (existingLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000324 existingLink.isExpected() != newLink.isExpected() ||
325 (existingLink.type() == INDIRECT && newLink.type() == DIRECT) ||
326 !AnnotationsUtil.isEqual(existingLink.annotations(), newLink.annotations())) {
327 eventType.set(LINK_UPDATED);
328 return newLink;
Madan Jampanibad538c2015-08-19 17:35:27 -0700329 } else {
330 return existingLink;
331 }
332 });
333 return eventType.get() != null ? new LinkEvent(eventType.get(), link) : null;
334 }
335
336 private Set<ProviderId> getAllProviders(LinkKey linkKey) {
kircaali28d67682016-04-11 15:08:14 +0000337 return linkProviders.getOrDefault(linkKey, Sets.newConcurrentHashSet());
Madan Jampanibad538c2015-08-19 17:35:27 -0700338 }
339
340 private ProviderId getBaseProviderId(LinkKey linkKey) {
341 Set<ProviderId> allProviders = getAllProviders(linkKey);
342 if (allProviders.size() > 0) {
343 return allProviders.stream()
kircaali28d67682016-04-11 15:08:14 +0000344 .filter(p -> !p.isAncillary())
345 .findFirst()
346 .orElse(Iterables.getFirst(allProviders, null));
Madan Jampanibad538c2015-08-19 17:35:27 -0700347 }
348 return null;
349 }
350
351 private Link composeLink(LinkKey linkKey) {
352
353 ProviderId baseProviderId = checkNotNull(getBaseProviderId(linkKey));
354 LinkDescription base = linkDescriptions.get(new Provided<>(linkKey, baseProviderId));
355
356 ConnectPoint src = base.src();
357 ConnectPoint dst = base.dst();
358 Type type = base.type();
359 AtomicReference<DefaultAnnotations> annotations = new AtomicReference<>(DefaultAnnotations.builder().build());
360 annotations.set(merge(annotations.get(), base.annotations()));
361
362 getAllProviders(linkKey).stream()
kircaali28d67682016-04-11 15:08:14 +0000363 .map(p -> new Provided<>(linkKey, p))
364 .forEach(key -> {
365 LinkDescription linkDescription = linkDescriptions.get(key);
366 if (linkDescription != null) {
367 annotations.set(merge(annotations.get(),
368 linkDescription.annotations()));
369 }
370 });
Madan Jampanibad538c2015-08-19 17:35:27 -0700371
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800372 Link.State initialLinkState;
373
374 boolean isExpected;
375 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE) {
376 initialLinkState = ACTIVE;
377 isExpected =
378 Objects.equals(annotations.get().value(AnnotationKeys.DURABLE), "true");
379 } else {
380 initialLinkState = base.isExpected() ? ACTIVE : INACTIVE;
381 isExpected = base.isExpected();
382 }
383
384
Ray Milkey2693bda2016-01-22 16:08:14 -0800385 return DefaultLink.builder()
386 .providerId(baseProviderId)
387 .src(src)
388 .dst(dst)
389 .type(type)
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800390 .state(initialLinkState)
391 .isExpected(isExpected)
Ray Milkey2693bda2016-01-22 16:08:14 -0800392 .annotations(annotations.get())
393 .build();
Madan Jampanibad538c2015-08-19 17:35:27 -0700394 }
395
396 // Updates, if necessary the specified link and returns the appropriate event.
397 // Guarded by linkDescs value (=locking each Link)
398 private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
399 // Note: INDIRECT -> DIRECT transition only
400 // so that BDDP discovered Link will not overwrite LDDP Link
401 if (oldLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000402 (oldLink.type() == INDIRECT && newLink.type() == DIRECT) ||
403 !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700404
405 links.put(key, newLink);
406 return new LinkEvent(LINK_UPDATED, newLink);
407 }
408 return null;
409 }
410
411 @Override
412 public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) {
413 Link link = getLink(src, dst);
414 if (link == null) {
415 return null;
416 }
417
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800418 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE && link.isExpected()) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700419 // FIXME: this will not sync link state!!!
420 return link.state() == INACTIVE ? null :
421 updateLink(linkKey(link.src(), link.dst()), link,
Ray Milkey2693bda2016-01-22 16:08:14 -0800422 DefaultLink.builder()
423 .providerId(link.providerId())
424 .src(link.src())
425 .dst(link.dst())
426 .type(link.type())
427 .state(INACTIVE)
428 .isExpected(link.isExpected())
429 .annotations(link.annotations())
430 .build());
Madan Jampanibad538c2015-08-19 17:35:27 -0700431 }
432 return removeLink(src, dst);
433 }
434
435 @Override
436 public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
437 final LinkKey linkKey = LinkKey.linkKey(src, dst);
Madan Jampani5d4396f2015-09-02 16:04:20 -0700438 ProviderId primaryProviderId = getBaseProviderId(linkKey);
439 // Stop if there is no base provider.
440 if (primaryProviderId == null) {
441 return null;
442 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700443 LinkDescription removedLinkDescription =
Madan Jampani5d4396f2015-09-02 16:04:20 -0700444 linkDescriptions.remove(new Provided<>(linkKey, primaryProviderId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700445 if (removedLinkDescription != null) {
446 return purgeLinkCache(linkKey);
447 }
448 return null;
449 }
450
451 private LinkEvent purgeLinkCache(LinkKey linkKey) {
452 Link removedLink = links.remove(linkKey);
453 if (removedLink != null) {
454 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p)));
kircaali28d67682016-04-11 15:08:14 +0000455 linkProviders.remove(linkKey);
Madan Jampanibad538c2015-08-19 17:35:27 -0700456 return new LinkEvent(LINK_REMOVED, removedLink);
457 }
458 return null;
459 }
460
461 private Set<Link> filter(Collection<Link> links, Predicate<Link> predicate) {
462 return links.stream().filter(predicate).collect(Collectors.toSet());
463 }
464
465 private LinkEvent injectLink(Provided<LinkDescription> linkInjectRequest) {
466 log.trace("Received request to inject link {}", linkInjectRequest);
467
468 ProviderId providerId = linkInjectRequest.providerId();
469 LinkDescription linkDescription = linkInjectRequest.key();
470
471 final DeviceId deviceId = linkDescription.dst().deviceId();
472 if (!deviceClockService.isTimestampAvailable(deviceId)) {
473 // workaround for ONOS-1208
474 log.warn("Not ready to accept update. Dropping {}", linkInjectRequest);
475 return null;
476 }
477 return createOrUpdateLink(providerId, linkDescription);
478 }
479
480 private class InternalLinkTracker implements EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> {
481 @Override
482 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) {
483 if (event.type() == PUT) {
kircaali28d67682016-04-11 15:08:14 +0000484 linkProviders.compute(event.key().key(), (k, v) ->
485 createOrUpdateLinkProviders(v, event.key().providerId()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700486 notifyDelegate(refreshLinkCache(event.key().key()));
487 } else if (event.type() == REMOVE) {
488 notifyDelegate(purgeLinkCache(event.key().key()));
kircaali28d67682016-04-11 15:08:14 +0000489 linkProviders.remove(event.key().key());
Madan Jampanibad538c2015-08-19 17:35:27 -0700490 }
491 }
492 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800493
494 private class InternalConfigListener implements NetworkConfigListener {
495
496 void reconfigure(CoreConfig coreConfig) {
497 if (coreConfig == null) {
498 linkDiscoveryMode = LinkDiscoveryMode.PERMISSIVE;
499 } else {
500 linkDiscoveryMode = coreConfig.linkDiscoveryMode();
501 }
502 if (linkDiscoveryMode == LinkDiscoveryMode.STRICT) {
503 // Remove any previous links to force them to go through the strict
504 // discovery process
Ray Milkey15551272016-02-10 16:22:02 -0800505 if (linkDescriptions != null) {
506 linkDescriptions.clear();
507 }
508 if (links != null) {
509 links.clear();
510 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800511 }
512 log.debug("config set link discovery mode to {}",
513 linkDiscoveryMode.name());
514 }
515
516 @Override
517 public void event(NetworkConfigEvent event) {
518
519 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
520 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
521 event.configClass().equals(CoreConfig.class)) {
522
523 CoreConfig cfg = netCfgService.getConfig(appId, CoreConfig.class);
524 reconfigure(cfg);
525 log.info("Reconfigured");
526 }
527 }
528 }
529
530 // Configuration properties factory
531 private final ConfigFactory factory =
532 new ConfigFactory<ApplicationId, CoreConfig>(APP_SUBJECT_FACTORY,
kircaali28d67682016-04-11 15:08:14 +0000533 CoreConfig.class,
534 "core") {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800535 @Override
536 public CoreConfig createConfig() {
537 return new CoreConfig();
538 }
539 };
Ray Milkeyd0dd1352016-01-19 10:58:41 -0800540}