blob: 3dc048fc4bec9b70b9f62e183daeb346b03a8079 [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;
64import org.onosproject.store.serializers.KryoSerializer;
65import 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
Madan Jampanibad538c2015-08-19 17:35:27 -0700158 protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
159 @Override
160 protected void setupKryoPool() {
161 serializerPool = KryoNamespace.newBuilder()
162 .register(DistributedStoreSerializers.STORE_COMMON)
163 .nextId(DistributedStoreSerializers.STORE_CUSTOM_BEGIN)
164 .register(Provided.class)
165 .build();
166 }
167 };
168
169 @Activate
170 public void activate() {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800171 appId = coreService.registerApplication("org.onosproject.core");
172 netCfgService.registerConfigFactory(factory);
173 netCfgService.addListener(cfgListener);
174
175 cfgListener.reconfigure(netCfgService.getConfig(appId, CoreConfig.class));
176
Madan Jampanibad538c2015-08-19 17:35:27 -0700177 KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
178 .register(KryoNamespaces.API)
179 .register(MastershipBasedTimestamp.class)
180 .register(Provided.class);
181
182 linkDescriptions = storageService.<Provided<LinkKey>, LinkDescription>eventuallyConsistentMapBuilder()
183 .withName("onos-link-descriptions")
184 .withSerializer(serializer)
185 .withTimestampProvider((k, v) -> {
186 try {
187 return v == null ? null : deviceClockService.getTimestamp(v.dst().deviceId());
188 } catch (IllegalStateException e) {
189 return null;
190 }
191 }).build();
192
193 clusterCommunicator.addSubscriber(LINK_INJECT_MESSAGE,
kircaali28d67682016-04-11 15:08:14 +0000194 SERIALIZER::decode,
195 this::injectLink,
196 SERIALIZER::encode,
197 SharedExecutors.getPoolThreadExecutor());
Madan Jampanibad538c2015-08-19 17:35:27 -0700198
199 linkDescriptions.addListener(linkTracker);
200
201 log.info("Started");
202 }
203
204 @Deactivate
205 public void deactivate() {
206 linkDescriptions.removeListener(linkTracker);
207 linkDescriptions.destroy();
kircaali28d67682016-04-11 15:08:14 +0000208 linkProviders.clear();
Madan Jampanibad538c2015-08-19 17:35:27 -0700209 links.clear();
210 clusterCommunicator.removeSubscriber(LINK_INJECT_MESSAGE);
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800211 netCfgService.removeListener(cfgListener);
212 netCfgService.unregisterConfigFactory(factory);
Madan Jampanibad538c2015-08-19 17:35:27 -0700213
214 log.info("Stopped");
215 }
216
217 @Override
218 public int getLinkCount() {
219 return links.size();
220 }
221
222 @Override
223 public Iterable<Link> getLinks() {
224 return links.values();
225 }
226
227 @Override
228 public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
229 return filter(links.values(), link -> deviceId.equals(link.src().deviceId()));
230 }
231
232 @Override
233 public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
234 return filter(links.values(), link -> deviceId.equals(link.dst().deviceId()));
235 }
236
237 @Override
238 public Link getLink(ConnectPoint src, ConnectPoint dst) {
239 return links.get(linkKey(src, dst));
240 }
241
242 @Override
243 public Set<Link> getEgressLinks(ConnectPoint src) {
244 return filter(links.values(), link -> src.equals(link.src()));
245 }
246
247 @Override
248 public Set<Link> getIngressLinks(ConnectPoint dst) {
249 return filter(links.values(), link -> dst.equals(link.dst()));
250 }
251
252 @Override
253 public LinkEvent createOrUpdateLink(ProviderId providerId,
254 LinkDescription linkDescription) {
255 final DeviceId dstDeviceId = linkDescription.dst().deviceId();
256 final NodeId dstNodeId = mastershipService.getMasterFor(dstDeviceId);
257
258 // Process link update only if we're the master of the destination node,
259 // otherwise signal the actual master.
260 if (clusterService.getLocalNode().id().equals(dstNodeId)) {
261 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700262 Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
263 if (internalLinkKey == null) {
264 return null;
265 }
Jian Li68c4fc42016-01-11 16:07:03 -0800266 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v, linkDescription));
Madan Jampanibad538c2015-08-19 17:35:27 -0700267 return refreshLinkCache(linkKey);
268 } else {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800269 // Only forward for ConfigProvider
270 // Forwarding was added as a workaround for ONOS-490
HIGUCHI Yuta4ea4e422016-01-13 16:40:34 -0800271 if (!providerId.scheme().equals("cfg")) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800272 return null;
273 }
274 // Temporary hack for NPE (ONOS-1171).
275 // Proper fix is to implement forwarding to master on ConfigProvider
Madan Jampanibad538c2015-08-19 17:35:27 -0700276 if (dstNodeId == null) {
277 return null;
278 }
279 return Futures.getUnchecked(clusterCommunicator.sendAndReceive(new Provided<>(linkDescription, providerId),
kircaali28d67682016-04-11 15:08:14 +0000280 LINK_INJECT_MESSAGE,
281 SERIALIZER::encode,
282 SERIALIZER::decode,
283 dstNodeId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700284 }
285 }
286
Ayaka Koshibe2c59acf2015-09-08 15:37:47 -0700287 private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
288 ProviderId bpid = getBaseProviderId(linkKey);
289 if (provId == null) {
290 // The LinkService didn't know who this LinkKey belongs to.
291 // A fix is to either modify the getProvider() in LinkService classes
292 // or expose the contents of linkDescriptions to the LinkService.
293 return (bpid == null) ? null : new Provided<>(linkKey, bpid);
294 } else {
295 return new Provided<>(linkKey, provId);
296 }
297 }
298
Madan Jampanibad538c2015-08-19 17:35:27 -0700299 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
300 if (current != null) {
301 // we only allow transition from INDIRECT -> DIRECT
kircaali28d67682016-04-11 15:08:14 +0000302 return new DefaultLinkDescription(
303 current.src(),
304 current.dst(),
305 current.type() == DIRECT ? DIRECT : updated.type(),
306 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);
324 if (existingLink == null) {
325 eventType.set(LINK_ADDED);
326 return newLink;
327 } else if (existingLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000328 existingLink.isExpected() != newLink.isExpected() ||
329 (existingLink.type() == INDIRECT && newLink.type() == DIRECT) ||
330 !AnnotationsUtil.isEqual(existingLink.annotations(), newLink.annotations())) {
331 eventType.set(LINK_UPDATED);
332 return newLink;
Madan Jampanibad538c2015-08-19 17:35:27 -0700333 } else {
334 return existingLink;
335 }
336 });
337 return eventType.get() != null ? new LinkEvent(eventType.get(), link) : null;
338 }
339
340 private Set<ProviderId> getAllProviders(LinkKey linkKey) {
kircaali28d67682016-04-11 15:08:14 +0000341 return linkProviders.getOrDefault(linkKey, Sets.newConcurrentHashSet());
Madan Jampanibad538c2015-08-19 17:35:27 -0700342 }
343
344 private ProviderId getBaseProviderId(LinkKey linkKey) {
345 Set<ProviderId> allProviders = getAllProviders(linkKey);
346 if (allProviders.size() > 0) {
347 return allProviders.stream()
kircaali28d67682016-04-11 15:08:14 +0000348 .filter(p -> !p.isAncillary())
349 .findFirst()
350 .orElse(Iterables.getFirst(allProviders, null));
Madan Jampanibad538c2015-08-19 17:35:27 -0700351 }
352 return null;
353 }
354
355 private Link composeLink(LinkKey linkKey) {
356
357 ProviderId baseProviderId = checkNotNull(getBaseProviderId(linkKey));
358 LinkDescription base = linkDescriptions.get(new Provided<>(linkKey, baseProviderId));
359
360 ConnectPoint src = base.src();
361 ConnectPoint dst = base.dst();
362 Type type = base.type();
363 AtomicReference<DefaultAnnotations> annotations = new AtomicReference<>(DefaultAnnotations.builder().build());
364 annotations.set(merge(annotations.get(), base.annotations()));
365
366 getAllProviders(linkKey).stream()
kircaali28d67682016-04-11 15:08:14 +0000367 .map(p -> new Provided<>(linkKey, p))
368 .forEach(key -> {
369 LinkDescription linkDescription = linkDescriptions.get(key);
370 if (linkDescription != null) {
371 annotations.set(merge(annotations.get(),
372 linkDescription.annotations()));
373 }
374 });
Madan Jampanibad538c2015-08-19 17:35:27 -0700375
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800376 Link.State initialLinkState;
377
378 boolean isExpected;
379 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE) {
380 initialLinkState = ACTIVE;
381 isExpected =
382 Objects.equals(annotations.get().value(AnnotationKeys.DURABLE), "true");
383 } else {
384 initialLinkState = base.isExpected() ? ACTIVE : INACTIVE;
385 isExpected = base.isExpected();
386 }
387
388
Ray Milkey2693bda2016-01-22 16:08:14 -0800389 return DefaultLink.builder()
390 .providerId(baseProviderId)
391 .src(src)
392 .dst(dst)
393 .type(type)
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800394 .state(initialLinkState)
395 .isExpected(isExpected)
Ray Milkey2693bda2016-01-22 16:08:14 -0800396 .annotations(annotations.get())
397 .build();
Madan Jampanibad538c2015-08-19 17:35:27 -0700398 }
399
400 // Updates, if necessary the specified link and returns the appropriate event.
401 // Guarded by linkDescs value (=locking each Link)
402 private LinkEvent updateLink(LinkKey key, Link oldLink, Link newLink) {
403 // Note: INDIRECT -> DIRECT transition only
404 // so that BDDP discovered Link will not overwrite LDDP Link
405 if (oldLink.state() != newLink.state() ||
kircaali28d67682016-04-11 15:08:14 +0000406 (oldLink.type() == INDIRECT && newLink.type() == DIRECT) ||
407 !AnnotationsUtil.isEqual(oldLink.annotations(), newLink.annotations())) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700408
409 links.put(key, newLink);
410 return new LinkEvent(LINK_UPDATED, newLink);
411 }
412 return null;
413 }
414
415 @Override
416 public LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst) {
417 Link link = getLink(src, dst);
418 if (link == null) {
419 return null;
420 }
421
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800422 if (linkDiscoveryMode == LinkDiscoveryMode.PERMISSIVE && link.isExpected()) {
Madan Jampanibad538c2015-08-19 17:35:27 -0700423 // FIXME: this will not sync link state!!!
424 return link.state() == INACTIVE ? null :
425 updateLink(linkKey(link.src(), link.dst()), link,
Ray Milkey2693bda2016-01-22 16:08:14 -0800426 DefaultLink.builder()
427 .providerId(link.providerId())
428 .src(link.src())
429 .dst(link.dst())
430 .type(link.type())
431 .state(INACTIVE)
432 .isExpected(link.isExpected())
433 .annotations(link.annotations())
434 .build());
Madan Jampanibad538c2015-08-19 17:35:27 -0700435 }
436 return removeLink(src, dst);
437 }
438
439 @Override
440 public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
441 final LinkKey linkKey = LinkKey.linkKey(src, dst);
Madan Jampani5d4396f2015-09-02 16:04:20 -0700442 ProviderId primaryProviderId = getBaseProviderId(linkKey);
443 // Stop if there is no base provider.
444 if (primaryProviderId == null) {
445 return null;
446 }
Madan Jampanibad538c2015-08-19 17:35:27 -0700447 LinkDescription removedLinkDescription =
Madan Jampani5d4396f2015-09-02 16:04:20 -0700448 linkDescriptions.remove(new Provided<>(linkKey, primaryProviderId));
Madan Jampanibad538c2015-08-19 17:35:27 -0700449 if (removedLinkDescription != null) {
450 return purgeLinkCache(linkKey);
451 }
452 return null;
453 }
454
455 private LinkEvent purgeLinkCache(LinkKey linkKey) {
456 Link removedLink = links.remove(linkKey);
457 if (removedLink != null) {
458 getAllProviders(linkKey).forEach(p -> linkDescriptions.remove(new Provided<>(linkKey, p)));
kircaali28d67682016-04-11 15:08:14 +0000459 linkProviders.remove(linkKey);
Madan Jampanibad538c2015-08-19 17:35:27 -0700460 return new LinkEvent(LINK_REMOVED, removedLink);
461 }
462 return null;
463 }
464
465 private Set<Link> filter(Collection<Link> links, Predicate<Link> predicate) {
466 return links.stream().filter(predicate).collect(Collectors.toSet());
467 }
468
469 private LinkEvent injectLink(Provided<LinkDescription> linkInjectRequest) {
470 log.trace("Received request to inject link {}", linkInjectRequest);
471
472 ProviderId providerId = linkInjectRequest.providerId();
473 LinkDescription linkDescription = linkInjectRequest.key();
474
475 final DeviceId deviceId = linkDescription.dst().deviceId();
476 if (!deviceClockService.isTimestampAvailable(deviceId)) {
477 // workaround for ONOS-1208
478 log.warn("Not ready to accept update. Dropping {}", linkInjectRequest);
479 return null;
480 }
481 return createOrUpdateLink(providerId, linkDescription);
482 }
483
484 private class InternalLinkTracker implements EventuallyConsistentMapListener<Provided<LinkKey>, LinkDescription> {
485 @Override
486 public void event(EventuallyConsistentMapEvent<Provided<LinkKey>, LinkDescription> event) {
487 if (event.type() == PUT) {
kircaali28d67682016-04-11 15:08:14 +0000488 linkProviders.compute(event.key().key(), (k, v) ->
489 createOrUpdateLinkProviders(v, event.key().providerId()));
Madan Jampanibad538c2015-08-19 17:35:27 -0700490 notifyDelegate(refreshLinkCache(event.key().key()));
491 } else if (event.type() == REMOVE) {
492 notifyDelegate(purgeLinkCache(event.key().key()));
kircaali28d67682016-04-11 15:08:14 +0000493 linkProviders.remove(event.key().key());
Madan Jampanibad538c2015-08-19 17:35:27 -0700494 }
495 }
496 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800497
498 private class InternalConfigListener implements NetworkConfigListener {
499
500 void reconfigure(CoreConfig coreConfig) {
501 if (coreConfig == null) {
502 linkDiscoveryMode = LinkDiscoveryMode.PERMISSIVE;
503 } else {
504 linkDiscoveryMode = coreConfig.linkDiscoveryMode();
505 }
506 if (linkDiscoveryMode == LinkDiscoveryMode.STRICT) {
507 // Remove any previous links to force them to go through the strict
508 // discovery process
Ray Milkey15551272016-02-10 16:22:02 -0800509 if (linkDescriptions != null) {
510 linkDescriptions.clear();
511 }
512 if (links != null) {
513 links.clear();
514 }
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800515 }
516 log.debug("config set link discovery mode to {}",
517 linkDiscoveryMode.name());
518 }
519
520 @Override
521 public void event(NetworkConfigEvent event) {
522
523 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
524 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
525 event.configClass().equals(CoreConfig.class)) {
526
527 CoreConfig cfg = netCfgService.getConfig(appId, CoreConfig.class);
528 reconfigure(cfg);
529 log.info("Reconfigured");
530 }
531 }
532 }
533
534 // Configuration properties factory
535 private final ConfigFactory factory =
536 new ConfigFactory<ApplicationId, CoreConfig>(APP_SUBJECT_FACTORY,
kircaali28d67682016-04-11 15:08:14 +0000537 CoreConfig.class,
538 "core") {
Ray Milkeyb7f0f642016-01-22 16:08:14 -0800539 @Override
540 public CoreConfig createConfig() {
541 return new CoreConfig();
542 }
543 };
Ray Milkeyd0dd1352016-01-19 10:58:41 -0800544}