2 * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.vpnmanager;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.concurrent.*;
14 import com.google.common.util.concurrent.CheckedFuture;
16 import com.google.common.util.concurrent.ThreadFactoryBuilder;
17 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
20 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op
31 .data.entry.VpnToDpnList;
32 import org.opendaylight.yangtools.concepts.ListenerRegistration;
33 import org.opendaylight.yangtools.yang.binding.DataObject;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
36 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
42 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
49 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
53 import com.google.common.base.Optional;
54 import com.google.common.util.concurrent.FutureCallback;
55 import com.google.common.util.concurrent.Futures;
57 public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
58 private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
59 private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration;
60 private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
61 private ExecutorService executorService = Executors.newSingleThreadExecutor();
62 private final DataBroker broker;
63 private final IBgpManager bgpManager;
64 private IdManagerService idManager;
65 private VpnInterfaceManager vpnInterfaceManager;
66 private final FibEntriesListener fibListener;
67 private NotificationService notificationService;
69 private static final FutureCallback<Void> DEFAULT_CALLBACK =
70 new FutureCallback<Void>() {
72 public void onSuccess(Void result) {
73 LOG.debug("Success in Datastore operation");
77 public void onFailure(Throwable error) {
78 LOG.error("Error in Datastore operation", error);
83 * Listens for data change related to VPN Instance
84 * Informs the BGP about VRF information
86 * @param db dataBroker reference
87 * @param bgpManager Used to advertise routes to the BGP Router
89 public VpnManager(final DataBroker db, final IBgpManager bgpManager) {
90 super(VpnInstance.class);
92 this.bgpManager = bgpManager;
93 this.fibListener = new FibEntriesListener();
97 private void registerListener(final DataBroker db) {
99 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
100 getWildCardPath(), VpnManager.this, DataChangeScope.SUBTREE);
101 fibListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
102 getFibEntryListenerPath(), fibListener, DataChangeScope.BASE);
103 } catch (final Exception e) {
104 LOG.error("VPN Service DataChange listener registration fail !", e);
105 throw new IllegalStateException("VPN Service registration Listener failed.", e);
109 public void setIdManager(IdManagerService idManager) {
110 this.idManager = idManager;
113 public void setVpnInterfaceManager(VpnInterfaceManager vpnInterfaceManager) {
114 this.vpnInterfaceManager = vpnInterfaceManager;
117 private void waitForOpRemoval(String rd, String vpnName) {
118 //wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is zero
119 //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
120 VpnInstanceOpDataEntry vpnOpEntry = null;
122 Long currentIntfCount = 0L;
123 Integer retryCount = 1;
124 long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
125 Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
126 vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
127 VpnUtil.getVpnInstanceOpDataIdentifier(rd));
129 if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
130 vpnOpEntry = vpnOpValue.get();
131 List<VpnToDpnList> dpnToVpns = vpnOpEntry.getVpnToDpnList();
132 if (dpnToVpns != null) {
133 for (VpnToDpnList dpn : dpnToVpns) {
134 if (dpn.getVpnInterfaces() != null) {
135 intfCount = intfCount + dpn.getVpnInterfaces().size();
139 //intfCount = vpnOpEntry.getVpnInterfaceCount();
142 // Minimum wait time of 5 seconds for one VPN Interface clearance (inclusive of full trace on)
143 timeout = intfCount * VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
144 // Maximum wait time of 90 seconds for all VPN Interfaces clearance (inclusive of full trace on)
145 if (timeout > VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS) {
146 timeout = VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS;
148 LOG.info("VPNInstance removal count of interface at {} for for rd {}, vpnname {}",
149 intfCount, rd, vpnName);
151 LOG.info("VPNInstance removal thread waiting for {} seconds for rd {}, vpnname {}",
152 (timeout / 1000), rd, vpnName);
155 Thread.sleep(timeout);
156 } catch (java.lang.InterruptedException e) {
158 // Runnable notifyTask = new VpnNotifyTask();
159 // synchronized (rd.intern()) {
161 // vpnOpMap.put(rd, notifyTask);
162 // synchronized (notifyTask) {
164 // notifyTask.wait(timeout);
165 // } catch (InterruptedException e) {
169 // vpnOpMap.remove(rd);
173 // Check current interface count
174 vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
175 VpnUtil.getVpnInstanceOpDataIdentifier(rd));
176 if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
177 vpnOpEntry = vpnOpValue.get();
178 dpnToVpns = vpnOpEntry.getVpnToDpnList();
179 currentIntfCount = 0L;
180 if (dpnToVpns != null) {
181 for (VpnToDpnList dpn : dpnToVpns) {
182 if (dpn.getVpnInterfaces() != null) {
183 currentIntfCount = currentIntfCount + dpn.getVpnInterfaces().size();
187 //currentIntfCount = vpnOpEntry.getVpnInterfaceCount();
188 if ((currentIntfCount == 0) || (currentIntfCount >= intfCount)) {
189 // Either the FibManager completed its job to cleanup all vpnInterfaces in VPN
191 // There is no progress by FibManager in removing all the interfaces even after good time!
192 // In either case, let us quit and take our chances.
193 //TODO(vpnteam): L3VPN refactoring to take care of this case.
194 if (retryCount > 0) {
196 LOG.info("Retrying clearing vpn with vpnname {} rd {} since currentIntfCount {} ", vpnName, rd, currentIntfCount);
197 if (currentIntfCount > 0L){
198 LOG.info("Current interface count for vpn {} and rd {} is not zero and so retrying ...", vpnName, rd);
199 intfCount = currentIntfCount;
201 LOG.info("Current interface count is zero but instance Op for vpn {} and rd {} not cleared yet. Waiting for 5 more seconds.", vpnName, rd);
205 LOG.info("VPNInstance bailing out of wait loop as currentIntfCount is {} and max retries exceeded for for rd {}, vpnname {}",
206 currentIntfCount, rd, vpnName);
210 // There is some progress by FibManager, so let us give it some more time!
211 intfCount = currentIntfCount;
213 LOG.info("current interface count {} for vpn {} and rd {} showing progress, waiting for it to drive to 0.", currentIntfCount, vpnName, rd);
216 // There is no VPNOPEntry. Something else happened on the system !
217 // So let us quit and take our chances.
218 //TODO(vpnteam): L3VPN refactoring to take care of this case.
223 LOG.info("Returned out of waiting for Op Data removal for rd {}, vpnname {}", rd, vpnName);
228 protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
229 LOG.trace("Remove VPN event key: {}, value: {}", identifier, del);
230 String vpnName = del.getVpnInstanceName();
231 String rd = del.getIpv4Family().getRouteDistinguisher();
232 long vpnId = VpnUtil.getVpnId(broker, vpnName);
234 //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
235 Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
236 if ((rd != null) && (!rd.isEmpty())) {
237 vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
238 VpnUtil.getVpnInstanceOpDataIdentifier(rd));
240 vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
241 VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
244 if ((rd != null) && (!rd.isEmpty())) {
245 waitForOpRemoval(rd, vpnName);
247 waitForOpRemoval(vpnName, vpnName);
250 // Clean up VpnInstanceToVpnId from Config DS
251 VpnUtil.removeVpnIdToVpnInstance(broker, vpnId);
252 VpnUtil.removeVpnInstanceToVpnId(broker, vpnName);
253 LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", rd, vpnName);
255 synchronized (rd.intern()) {
257 bgpManager.deleteVrf(rd);
258 } catch (Exception e) {
259 LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
263 // Clean up VPNExtraRoutes Operational DS
264 VpnUtil.removeVpnExtraRouteForVpn(broker, rd);
266 // Clean up VPNInstanceOpDataEntry
267 VpnUtil.removeVpnOpInstance(broker, rd);
269 // Clean up FIB Entries Config DS
270 synchronized (vpnName.intern()) {
271 VpnUtil.removeVrfTableForVpn(broker, vpnName);
274 // Clean up VPNExtraRoutes Operational DS
275 VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName);
277 // Clean up VPNInstanceOpDataEntry
278 VpnUtil.removeVpnOpInstance(broker, vpnName);
281 // Clean up PrefixToInterface Operational DS
282 VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId);
284 // Clean up L3NextHop Operational DS
285 VpnUtil.removeL3nexthopForVpnId(broker, vpnId);
287 // Release the ID used for this VPN back to IdManager
288 VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
292 protected void update(InstanceIdentifier<VpnInstance> identifier,
293 VpnInstance original, VpnInstance update) {
294 LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
298 protected void add(InstanceIdentifier<VpnInstance> identifier, VpnInstance value) {
299 LOG.trace("Add VPN event key: {}, value: {}", identifier, value);
300 VpnAfConfig config = value.getIpv4Family();
301 String rd = config.getRouteDistinguisher();
302 String vpnInstanceName = value.getVpnInstanceName();
304 long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnInstanceName);
305 LOG.trace("VPN instance to ID generated.");
306 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
307 vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(vpnInstanceName, vpnId, (rd != null) ? rd
310 syncWrite(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnInstanceName),
311 vpnInstanceToVpnId, DEFAULT_CALLBACK);
314 vpnIdToVpnInstance = VpnUtil.getVpnIdToVpnInstance(vpnId, value.getVpnInstanceName(),
315 (rd != null) ? rd : value.getVpnInstanceName(), (rd != null)/*isExternalVpn*/) ;
317 syncWrite(LogicalDatastoreType.CONFIGURATION,
318 VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId),
319 vpnIdToVpnInstance, DEFAULT_CALLBACK);
321 IFibManager fibManager = vpnInterfaceManager.getFibManager();
323 String cachedTransType = fibManager.getConfTransType();
324 LOG.trace("Value for confTransportType is " + cachedTransType);
325 if (cachedTransType.equals("Invalid")) {
327 fibManager.setConfTransType("L3VPN", "VXLAN");
328 } catch (Exception e) {
329 LOG.trace("Exception caught setting the cached value for transportType");
330 LOG.error(e.getMessage());
333 LOG.trace(":cached val is neither unset/invalid. NO-op.");
335 } catch (Exception e) {
336 LOG.error(e.getMessage());
340 VpnInstanceOpDataEntryBuilder builder =
341 new VpnInstanceOpDataEntryBuilder().setVrfId(vpnInstanceName).setVpnId(vpnId)
342 .setVpnInstanceName(vpnInstanceName)
343 .setVpnInterfaceCount(0L);
344 syncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(vpnInstanceName),
345 builder.build(), DEFAULT_CALLBACK);
348 VpnInstanceOpDataEntryBuilder builder =
349 new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnInstanceName)
350 .setVpnInterfaceCount(0L);
351 syncWrite(LogicalDatastoreType.OPERATIONAL,
352 VpnUtil.getVpnInstanceOpDataIdentifier(rd),
353 builder.build(), DEFAULT_CALLBACK);
355 List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
357 List<String> ertList = new ArrayList<String>();
358 List<String> irtList = new ArrayList<String>();
360 for (VpnTarget vpnTarget : vpnTargetList) {
361 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
362 ertList.add(vpnTarget.getVrfRTValue());
364 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
365 irtList.add(vpnTarget.getVrfRTValue());
367 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
368 ertList.add(vpnTarget.getVrfRTValue());
369 irtList.add(vpnTarget.getVrfRTValue());
374 bgpManager.addVrf(rd, irtList, ertList);
375 } catch(Exception e) {
376 LOG.error("Exception when adding VRF to BGP", e);
379 //Try to add up vpn Interfaces if already in Operational Datastore
380 InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
381 Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, vpnInterfacesId);
383 if(optionalVpnInterfaces.isPresent()) {
384 List<VpnInterface> vpnInterfaces = optionalVpnInterfaces.get().getVpnInterface();
385 for(VpnInterface vpnInterface : vpnInterfaces) {
386 if(vpnInterface.getVpnInstanceName().equals(vpnInstanceName)) {
387 LOG.debug("VpnInterface {} will be added from VPN {}", vpnInterface.getName(), vpnInstanceName);
388 vpnInterfaceManager.add(
389 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
394 vpnInterfaceManager.handleVpnsExportingRoutes(vpnInstanceName, rd);
397 public boolean isVPNConfigured() {
399 InstanceIdentifier<VpnInstances> vpnsIdentifier =
400 InstanceIdentifier.builder(VpnInstances.class).build();
401 Optional<VpnInstances> optionalVpns = read( LogicalDatastoreType.CONFIGURATION,
403 if (!optionalVpns.isPresent() ||
404 optionalVpns.get().getVpnInstance() == null ||
405 optionalVpns.get().getVpnInstance().isEmpty()) {
406 LOG.trace("No VPNs configured.");
409 LOG.trace("VPNs are configured on the system.");
413 private InstanceIdentifier<?> getWildCardPath() {
414 return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
417 private InstanceIdentifier<?> getFibEntryListenerPath() {
418 return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class)
419 .child(VrfEntry.class);
422 private InstanceIdentifier<?> getVpnInstanceOpListenerPath() {
423 return InstanceIdentifier.create(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class);
427 public void close() throws Exception {
428 if (listenerRegistration != null) {
430 listenerRegistration.close();
431 } catch (final Exception e) {
432 LOG.error("Error when cleaning up Vpn DataChangeListener.", e);
434 listenerRegistration = null;
436 if (fibListenerRegistration != null) {
438 fibListenerRegistration.close();
439 } catch (final Exception e) {
440 LOG.error("Error when cleaning up Fib entries DataChangeListener.", e);
442 fibListenerRegistration = null;
444 LOG.trace("VPN Manager Closed");
447 private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
448 InstanceIdentifier<T> path) {
450 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
452 Optional<T> result = Optional.absent();
454 result = tx.read(datastoreType, path).get();
455 } catch (Exception e) {
456 throw new RuntimeException(e);
462 private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
463 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
464 WriteTransaction tx = broker.newWriteOnlyTransaction();
465 tx.put(datastoreType, path, data, true);
466 Futures.addCallback(tx.submit(), callback);
469 private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
470 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
471 WriteTransaction tx = broker.newWriteOnlyTransaction();
472 tx.put(datastoreType, path, data, true);
473 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
476 } catch (InterruptedException | ExecutionException e) {
477 LOG.error("Error writing VPN instance to ID info to datastore (path, data) : ({}, {})", path, data);
478 throw new RuntimeException(e.getMessage());
482 protected VpnInstance getVpnInstance(String vpnInstanceName) {
483 return VpnUtil.getVpnInstance(broker, vpnInstanceName);
486 protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
487 InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
488 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
489 if(vpnInstanceOpData.isPresent()) {
490 return vpnInstanceOpData.get();
495 private class FibEntriesListener extends AbstractDataChangeListener<VrfEntry> {
497 public FibEntriesListener() {
498 super(VrfEntry.class);
502 protected void remove(InstanceIdentifier<VrfEntry> identifier,
504 LOG.trace("Remove Fib event - Key : {}, value : {} ", identifier, del);
505 final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
506 String rd = key.getRouteDistinguisher();
507 Long label = del.getLabel();
508 VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
509 if(vpnInstanceOpData != null) {
510 List<Long> routeIds = vpnInstanceOpData.getRouteEntryId();
511 if(routeIds == null) {
512 LOG.debug("Fib Route entry is empty.");
515 LOG.debug("Removing label from vpn info - {}", label);
516 routeIds.remove(label);
517 asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
518 new VpnInstanceOpDataEntryBuilder(vpnInstanceOpData).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
520 LOG.warn("No VPN Instance found for RD: {}", rd);
525 protected void update(InstanceIdentifier<VrfEntry> identifier,
526 VrfEntry original, VrfEntry update) {
527 // TODO Auto-generated method stub
532 protected void add(InstanceIdentifier<VrfEntry> identifier,
534 LOG.trace("Add Vrf Entry event - Key : {}, value : {}", identifier, add);
535 final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
536 String rd = key.getRouteDistinguisher();
537 Long label = add.getLabel();
538 VpnInstanceOpDataEntry vpn = getVpnInstanceOpData(rd);
540 List<Long> routeIds = vpn.getRouteEntryId();
541 if(routeIds == null) {
542 routeIds = new ArrayList<>();
544 LOG.debug("Adding label to vpn info - {}", label);
546 asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
547 new VpnInstanceOpDataEntryBuilder(vpn).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
549 LOG.warn("No VPN Instance found for RD: {}", rd);