MRI version bumpup for Aluminium
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / InterfaceStateChangeListener.java
1 /*
2  * Copyright (c) 2015, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.vpnmanager;
9
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
11 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
12
13 import com.google.common.collect.HashBasedTable;
14 import com.google.common.collect.Table;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Optional;
25 import java.util.Set;
26 import javax.annotation.PreDestroy;
27 import javax.inject.Inject;
28 import javax.inject.Singleton;
29 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
30 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
31 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
32 import org.opendaylight.infrautils.utils.concurrent.Executors;
33 import org.opendaylight.mdsal.binding.api.DataBroker;
34 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
35 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
36 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
37 import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.common.Uint64;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 @Singleton
55 public class InterfaceStateChangeListener extends AbstractAsyncDataTreeChangeListener<Interface> {
56
57     private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
58     private static final short DJC_MAX_RETRIES = 3;
59     private final DataBroker dataBroker;
60     private final ManagedNewTransactionRunner txRunner;
61     private final VpnInterfaceManager vpnInterfaceManager;
62     private final VpnUtil vpnUtil;
63     private final JobCoordinator jobCoordinator;
64     private final IFibManager fibManager;
65
66     Table<OperStatus, OperStatus, IntfTransitionState> stateTable = HashBasedTable.create();
67
68     enum IntfTransitionState {
69         STATE_UP,
70         STATE_DOWN,
71         STATE_IGNORE
72     }
73
74     private void initialize() {
75         //  Interface State Transition Table
76         //               Up                Down            Unknown
77         // ---------------------------------------------------------------
78         /* Up       { STATE_IGNORE,   STATE_DOWN,     STATE_IGNORE }, */
79         /* Down     { STATE_UP,       STATE_IGNORE,   STATE_IGNORE }, */
80         /* Unknown  { STATE_UP,       STATE_DOWN,     STATE_IGNORE }, */
81
82         stateTable.put(Interface.OperStatus.Up, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
83         stateTable.put(Interface.OperStatus.Down, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
84         stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Up, IntfTransitionState.STATE_UP);
85         stateTable.put(Interface.OperStatus.Unknown, Interface.OperStatus.Down, IntfTransitionState.STATE_DOWN);
86     }
87
88     @Inject
89     public InterfaceStateChangeListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager,
90             final VpnUtil vpnUtil, final JobCoordinator jobCoordinator, final IFibManager fibManager) {
91         super(dataBroker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class)
92                 .child(Interface.class),
93                 Executors.newListeningSingleThreadExecutor("InterfaceStateChangeListener", LOG));
94         this.dataBroker = dataBroker;
95         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
96         this.vpnInterfaceManager = vpnInterfaceManager;
97         this.vpnUtil = vpnUtil;
98         this.jobCoordinator = jobCoordinator;
99         this.fibManager = fibManager;
100         initialize();
101     }
102
103     public void start() {
104         LOG.info("{} start", getClass().getSimpleName());
105     }
106
107     @Override
108     @PreDestroy
109     public void close() {
110         super.close();
111         Executors.shutdownAndAwaitTermination(getExecutorService());
112     }
113
114
115     @Override
116     // TODO Clean up the exception handling
117     @SuppressWarnings("checkstyle:IllegalCatch")
118     public void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
119         try {
120             if (L2vlan.class.equals(intrf.getType())) {
121                 LOG.info("VPN Interface add event - intfName {} from InterfaceStateChangeListener",
122                                 intrf.getName());
123                 jobCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(), () -> {
124                     List<ListenableFuture<Void>> futures = new ArrayList<>(3);
125                     futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeInvTxn -> {
126                         //map of prefix and vpn name used, as entry in prefix-to-interface datastore
127                         // is prerequisite for refresh Fib to avoid race condition leading to missing remote next hop
128                         // in bucket actions on bgp-vpn delete
129                         Map<String, Set<String>> mapOfRdAndPrefixesForRefreshFib = new HashMap<>();
130                         ListenableFuture<Void> configFuture
131                             = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, writeConfigTxn -> {
132                                 ListenableFuture<Void> operFuture
133                                     = txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeOperTxn -> {
134                                         final String interfaceName = intrf.getName();
135                                         LOG.info("Detected interface add event for interface {}", interfaceName);
136                                         final VpnInterface vpnIf = vpnUtil.getConfiguredVpnInterface(interfaceName);
137                                         if (vpnIf != null) {
138                                             for (VpnInstanceNames vpnInterfaceVpnInstance :
139                                                     vpnIf.nonnullVpnInstanceNames().values()) {
140                                                 String vpnName = vpnInterfaceVpnInstance.getVpnName();
141                                                 String primaryRd = vpnUtil.getPrimaryRd(vpnName);
142                                                 if (!vpnInterfaceManager.isVpnInstanceReady(vpnName)) {
143                                                     LOG.info("VPN Interface add event - intfName {} onto vpnName {} "
144                                                             + "running oper-driven, VpnInstance not ready, holding"
145                                                             + " on", vpnIf.getName(), vpnName);
146                                                 } else if (vpnUtil.isVpnPendingDelete(primaryRd)) {
147                                                     LOG.error("add: Ignoring addition of vpnInterface {}, as"
148                                                             + " vpnInstance {} with primaryRd {} is already marked for"
149                                                             + " deletion", interfaceName, vpnName, primaryRd);
150                                                 } else {
151                                                     Uint64 intfDpnId = Uint64.ZERO;
152                                                     try {
153                                                         intfDpnId = InterfaceUtils.getDpIdFromInterface(intrf);
154                                                     } catch (Exception e) {
155                                                         LOG.error("Unable to retrieve dpnId for interface {}. "
156                                                                 + "Process vpn interface add failed",intrf.getName(),
157                                                                 e);
158                                                         return;
159                                                     }
160                                                     LOG.error("InterfaceStateChangeListener- Processing ifState"
161                                                                     + " {} add event with dpnId {}",
162                                                             intrf.getName(), intfDpnId);
163                                                     final Uint64 dpnId = intfDpnId;
164                                                     final int ifIndex = intrf.getIfIndex();
165                                                     LOG.info("VPN Interface add event - intfName {} onto vpnName {}"
166                                                             + " running oper-driven", vpnIf.getName(), vpnName);
167                                                     Set<String> prefixes = new HashSet<>();
168                                                     vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnIf, primaryRd,
169                                                             ifIndex, false, writeConfigTxn, writeOperTxn, writeInvTxn,
170                                                             intrf, vpnName, prefixes);
171                                                     mapOfRdAndPrefixesForRefreshFib.put(primaryRd, prefixes);
172                                                 }
173                                             }
174
175                                         }
176                                     });
177                                 futures.add(operFuture);
178                                 operFuture.get(); //Synchronous submit of operTxn
179                             });
180                         Futures.addCallback(configFuture,
181                                 new VpnInterfaceCallBackHandler(mapOfRdAndPrefixesForRefreshFib),
182                                 MoreExecutors.directExecutor());
183                         futures.add(configFuture);
184                         //TODO: Allow immediateFailedFuture from writeCfgTxn to cancel writeInvTxn as well.
185                         Futures.addCallback(configFuture, new PostVpnInterfaceThreadWorker(intrf.getName(), true,
186                                 "Operational"), MoreExecutors.directExecutor());
187                     }));
188                     return futures;
189                 });
190             }
191         } catch (Exception e) {
192             LOG.error("Exception caught in Interface {} Operational State Up event", intrf.getName(), e);
193         }
194     }
195
196     @Override
197     // TODO Clean up the exception handling
198     @SuppressWarnings("checkstyle:IllegalCatch")
199     public void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
200         final String ifName = intrf.getName();
201         Uint64 dpId = Uint64.ZERO;
202         try {
203             if (L2vlan.class.equals(intrf.getType())) {
204                 LOG.info("VPN Interface remove event - intfName {} from InterfaceStateChangeListener",
205                                 intrf.getName());
206                 try {
207                     dpId = InterfaceUtils.getDpIdFromInterface(intrf);
208                 } catch (Exception e) {
209                     LOG.error("Unable to retrieve dpnId from interface operational data store for interface"
210                             + " {}. Fetching from vpn interface op data store. ", ifName, e);
211                 }
212                 final Uint64 inputDpId = dpId;
213                 jobCoordinator.enqueueJob("VPNINTERFACE-" + ifName, () -> {
214                     List<ListenableFuture<Void>> futures = new ArrayList<>(3);
215                     ListenableFuture<Void> configFuture =
216                         txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
217                             writeConfigTxn -> futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
218                                 writeOperTxn -> futures.add(
219                                     txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, writeInvTxn -> {
220                                         VpnInterface cfgVpnInterface =
221                                             vpnUtil.getConfiguredVpnInterface(ifName);
222                                         if (cfgVpnInterface == null) {
223                                             LOG.debug("Interface {} is not a vpninterface, ignoring.", ifName);
224                                             return;
225                                         }
226                                         for (VpnInstanceNames vpnInterfaceVpnInstance :
227                                                 cfgVpnInterface.nonnullVpnInstanceNames().values()) {
228                                             String vpnName = vpnInterfaceVpnInstance.getVpnName();
229                                             Optional<VpnInterfaceOpDataEntry> optVpnInterface =
230                                                 vpnUtil.getVpnInterfaceOpDataEntry(ifName, vpnName);
231                                             if (!optVpnInterface.isPresent()) {
232                                                 LOG.debug("Interface {} vpn {} is not a vpninterface, or deletion"
233                                                     + " triggered by northbound agent. ignoring.", ifName, vpnName);
234                                                 continue;
235                                             }
236                                             handleMipAdjRemoval(cfgVpnInterface, vpnName);
237                                             final VpnInterfaceOpDataEntry vpnInterface = optVpnInterface.get();
238                                             String gwMac = intrf.getPhysAddress() != null ? intrf.getPhysAddress()
239                                                 .getValue() : vpnInterface.getGatewayMacAddress();
240                                             Uint64 dpnId = inputDpId;
241                                             if (dpnId == null || dpnId.equals(Uint64.ZERO)) {
242                                                 dpnId = vpnInterface.getDpnId();
243                                             }
244                                             final int ifIndex = intrf.getIfIndex();
245                                             LOG.info("VPN Interface remove event - intfName {} onto vpnName {}"
246                                                 + " running oper-driver", vpnInterface.getName(), vpnName);
247                                             vpnInterfaceManager.processVpnInterfaceDown(dpnId, ifName, ifIndex, gwMac,
248                                                 vpnInterface, false, writeConfigTxn, writeOperTxn, writeInvTxn);
249                                         }
250                                     })))));
251                     futures.add(configFuture);
252                     Futures.addCallback(configFuture, new PostVpnInterfaceThreadWorker(intrf.getName(), false,
253                             "Operational"), MoreExecutors.directExecutor());
254                     return futures;
255                 }, DJC_MAX_RETRIES);
256             }
257         } catch (Exception e) {
258             LOG.error("Exception observed in handling deletion of VPN Interface {}. ", ifName, e);
259         }
260     }
261
262     // TODO Clean up the exception handling
263     @SuppressWarnings("checkstyle:IllegalCatch")
264     @Override
265     public void update(InstanceIdentifier<Interface> identifier,
266                     Interface original, Interface update) {
267         final String ifName = update.getName();
268         try {
269             if (update.getIfIndex() == null) {
270                 return;
271             }
272             if (L2vlan.class.equals(update.getType())) {
273                 LOG.info("VPN Interface update event - intfName {} from InterfaceStateChangeListener",
274                         update.getName());
275                 jobCoordinator.enqueueJob("VPNINTERFACE-" + ifName, () -> {
276                     List<ListenableFuture<Void>> futures = new ArrayList<>(3);
277                     futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, writeOperTxn -> {
278                         //map of prefix and vpn name used, as entry in prefix-to-interface datastore
279                         // is prerequisite for refresh Fib to avoid race condition leading to missing remote
280                         // next hop in bucket actions on bgp-vpn delete
281                         Map<String, Set<String>> mapOfRdAndPrefixesForRefreshFib = new HashMap<>();
282                         ListenableFuture<Void> configTxFuture =
283                                 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, writeConfigTxn ->
284                                     futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
285                                         writeInvTxn -> {
286                                             final VpnInterface vpnIf = vpnUtil.getConfiguredVpnInterface(ifName);
287                                             if (vpnIf != null) {
288                                                 final int ifIndex = update.getIfIndex();
289                                                 Uint64 dpnId;
290                                                 try {
291                                                     dpnId = InterfaceUtils.getDpIdFromInterface(update);
292                                                 } catch (Exception e) {
293                                                     LOG.error("remove: Unable to retrieve dpnId for interface {}",
294                                                         ifName, e);
295                                                     return;
296                                                 }
297                                                 IntfTransitionState state = getTransitionState(
298                                                         original.getOperStatus(), update.getOperStatus());
299                                                 if (state.equals(IntfTransitionState.STATE_IGNORE)) {
300                                                     LOG.info("InterfaceStateChangeListener: Interface {} state "
301                                                          + "original {}" + "updated {} not handled", ifName,
302                                                          original.getOperStatus(), update.getOperStatus());
303                                                     return;
304                                                 }
305                                                 LOG.error("InterfaceStateChangeListener- Processing ifState {} "
306                                                                 + "update event "
307                                                                 + "with dpnId {} operstate {}",
308                                                         ifName, dpnId, update.getOperStatus());
309                                                 if (state.equals(IntfTransitionState.STATE_UP)
310                                                         && vpnIf.getVpnInstanceNames() != null) {
311                                                     for (VpnInstanceNames vpnInterfaceVpnInstance :
312                                                             vpnIf.getVpnInstanceNames().values()) {
313                                                         String vpnName = vpnInterfaceVpnInstance.getVpnName();
314                                                         String primaryRd = vpnUtil.getPrimaryRd(vpnName);
315                                                         Set<String> prefixes = new HashSet<>();
316                                                         if (!vpnInterfaceManager.isVpnInstanceReady(vpnName)) {
317                                                             LOG.error("VPN Interface update event - intfName {} "
318                                                                 + "onto vpnName {} running oper-driven UP, "
319                                                                 + "VpnInstance not ready, holding on",
320                                                                 vpnIf.getName(), vpnName);
321                                                         } else if (vpnUtil.isVpnPendingDelete(primaryRd)) {
322                                                             LOG.error("update: Ignoring UP event for vpnInterface "
323                                                                 + "{}, as vpnInstance {} with primaryRd {} is "
324                                                                 + "already marked for deletion ",
325                                                                 vpnIf.getName(), vpnName, primaryRd);
326                                                         } else {
327                                                             vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnIf,
328                                                                 primaryRd, ifIndex, true, writeConfigTxn,
329                                                                 writeOperTxn, writeInvTxn, update, vpnName, prefixes);
330                                                             mapOfRdAndPrefixesForRefreshFib.put(primaryRd, prefixes);
331                                                         }
332                                                     }
333                                                 } else if (state.equals(IntfTransitionState.STATE_DOWN)
334                                                         && vpnIf.getVpnInstanceNames() != null) {
335                                                     for (VpnInstanceNames vpnInterfaceVpnInstance :
336                                                             vpnIf.getVpnInstanceNames().values()) {
337                                                         String vpnName = vpnInterfaceVpnInstance.getVpnName();
338                                                         LOG.info("VPN Interface update event - intfName {} "
339                                                             + " onto vpnName {} running oper-driven DOWN",
340                                                             vpnIf.getName(), vpnName);
341                                                         Optional<VpnInterfaceOpDataEntry> optVpnInterface = vpnUtil
342                                                             .getVpnInterfaceOpDataEntry(vpnIf.getName(), vpnName);
343                                                         if (optVpnInterface.isPresent()) {
344                                                             VpnInterfaceOpDataEntry vpnOpInterface =
345                                                                 optVpnInterface.get();
346                                                             handleMipAdjRemoval(vpnIf, vpnName);
347                                                             vpnInterfaceManager.processVpnInterfaceDown(dpnId,
348                                                                 vpnIf.getName(), ifIndex, update.getPhysAddress()
349                                                                 .getValue(), vpnOpInterface, true,
350                                                                 writeConfigTxn, writeOperTxn, writeInvTxn);
351                                                         } else {
352                                                             LOG.error("InterfaceStateChangeListener Update DOWN - "
353                                                                 + " vpnInterface {}not available, ignoring event",
354                                                                 vpnIf.getName());
355                                                             continue;
356                                                         }
357                                                     }
358                                                 }
359                                             } else {
360                                                 LOG.debug("Interface {} is not a vpninterface, ignoring.", ifName);
361                                             }
362                                         })));
363                         Futures.addCallback(configTxFuture,
364                             new VpnInterfaceCallBackHandler(mapOfRdAndPrefixesForRefreshFib),
365                             MoreExecutors.directExecutor());
366                         futures.add(configTxFuture);
367                     }));
368                     return futures;
369                 });
370             }
371         } catch (Exception e) {
372             LOG.error("Exception observed in handling updation of VPN Interface {}. ", update.getName(), e);
373         }
374     }
375
376     private void handleMipAdjRemoval(VpnInterface cfgVpnInterface, String vpnName) {
377         String interfaceName = cfgVpnInterface.getName();
378         Adjacencies adjacencies = cfgVpnInterface.augmentation(Adjacencies.class);
379         if (adjacencies != null) {
380             Map<AdjacencyKey, Adjacency> adjacencyMap = adjacencies.getAdjacency();
381             if (!adjacencyMap.isEmpty()) {
382                 for (Adjacency adj : adjacencyMap.values()) {
383                     if (adj.getAdjacencyType() != Adjacency.AdjacencyType.PrimaryAdjacency) {
384                         String ipAddress = adj.getIpAddress();
385                         String prefix = ipAddress.split("/")[0];
386                         LearntVpnVipToPort vpnVipToPort = vpnUtil.getLearntVpnVipToPort(vpnName, prefix);
387                         if (vpnVipToPort != null && vpnVipToPort.getPortName().equals(interfaceName)) {
388                             vpnUtil.removeMipAdjacency(vpnName, interfaceName, ipAddress, null);
389                         } else {
390                             LOG.debug("IP {} could be extra-route or learnt-ip on different interface"
391                                     + "than oper-vpn-interface {}", ipAddress, interfaceName);
392                         }
393                     }
394                 }
395             }
396         }
397     }
398
399     private class PostVpnInterfaceThreadWorker implements FutureCallback<Void> {
400         private final String interfaceName;
401         private final boolean add;
402         private final String txnDestination;
403
404         PostVpnInterfaceThreadWorker(String interfaceName, boolean add, String transactionDest) {
405             this.interfaceName = interfaceName;
406             this.add = add;
407             this.txnDestination = transactionDest;
408         }
409
410         @Override
411         public void onSuccess(Void voidObj) {
412             if (add) {
413                 LOG.debug("InterfaceStateChangeListener: VrfEntries for {} stored into destination {} successfully",
414                         interfaceName, txnDestination);
415             } else {
416                 LOG.debug("InterfaceStateChangeListener:  VrfEntries for {} removed successfully", interfaceName);
417             }
418         }
419
420         @Override
421         public void onFailure(Throwable throwable) {
422             if (add) {
423                 LOG.error("InterfaceStateChangeListener: VrfEntries for {} failed to store into destination {}",
424                         interfaceName, txnDestination, throwable);
425             } else {
426                 LOG.error("InterfaceStateChangeListener: VrfEntries for {} removal failed", interfaceName, throwable);
427                 vpnUtil.unsetScheduledToRemoveForVpnInterface(interfaceName);
428             }
429         }
430     }
431
432     private IntfTransitionState getTransitionState(Interface.OperStatus original , Interface.OperStatus updated) {
433         IntfTransitionState transitionState = stateTable.get(original, updated);
434
435         if (transitionState == null) {
436             return IntfTransitionState.STATE_IGNORE;
437         }
438         return transitionState;
439     }
440
441     private class VpnInterfaceCallBackHandler implements FutureCallback<Void> {
442         private final Map<String, Set<String>> mapOfRdAndPrefixesForRefreshFib;
443
444         VpnInterfaceCallBackHandler(Map<String, Set<String>> mapOfRdAndPrefixesForRefreshFib) {
445             this.mapOfRdAndPrefixesForRefreshFib = mapOfRdAndPrefixesForRefreshFib;
446         }
447
448         @Override
449         public void onSuccess(Void voidObj) {
450             mapOfRdAndPrefixesForRefreshFib.forEach((primaryRd, prefixes) -> {
451                 prefixes.forEach(prefix -> {
452                     fibManager.refreshVrfEntry(primaryRd, prefix);
453                 });
454             });
455         }
456
457         @Override
458         public void onFailure(Throwable throwable) {
459             LOG.debug("write Tx config operation failedTunnelEndPointChangeListener", throwable);
460         }
461     }
462 }