Drop unused exceptions in bgpmanager
[netvirt.git] / bgpmanager / impl / src / main / java / org / opendaylight / netvirt / bgpmanager / BgpConfigurationManager.java
1 /*
2  * Copyright © 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.bgpmanager;
9
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.ThreadFactoryBuilder;
12 import io.netty.util.concurrent.GlobalEventExecutor;
13 import java.io.IOException;
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.InvocationTargetException;
16 import java.net.InetAddress;
17 import java.net.NetworkInterface;
18 import java.net.SocketException;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Timer;
29 import java.util.concurrent.Callable;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Executors;
34 import java.util.concurrent.Future;
35 import java.util.concurrent.ScheduledExecutorService;
36 import java.util.concurrent.ScheduledFuture;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.TimeoutException;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import java.util.concurrent.atomic.AtomicReference;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.apache.thrift.TApplicationException;
46 import org.apache.thrift.TException;
47 import org.apache.thrift.transport.TTransport;
48 import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
49 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
50 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
51 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
52 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
53 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
54 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
55 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
58 import org.opendaylight.infrautils.metrics.MetricProvider;
59 import org.opendaylight.mdsal.eos.binding.api.Entity;
60 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
61 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
62 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
63 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
64 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
65 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
66 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
67 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
68 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
69 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
70 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
71 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
72 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
73 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
74 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
75 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
76 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
77 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
78 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
79 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
80 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
81 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
82 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
83 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
84 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
85 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
86 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
87 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
88 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
89 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
90 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
91 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Multipath;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathBuilder;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathKey;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
102 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
103 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
104 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpath;
105 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathKey;
107 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
108 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
109 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
110 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
111 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
112 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
113 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
114 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
115 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
116 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
117 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrf;
118 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrfBuilder;
119 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
120 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOption;
121 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
122 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
123 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
129 import org.opendaylight.yangtools.yang.binding.DataObject;
130 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
131 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
132 import org.osgi.framework.BundleContext;
133 import org.slf4j.Logger;
134 import org.slf4j.LoggerFactory;
135
136 @Singleton
137 public class BgpConfigurationManager {
138     private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
139
140     // to have stale FIB map (RD, Prefix)
141     //  number of seconds wait for route sync-up between ODL and BGP
142     private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
143     private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
144     private static final String DEF_LOGLEVEL = "errors";
145     private static final String UPDATE_PORT = "bgp.thrift.service.port";
146     private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
147     private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
148     private static final String DEF_UPORT = "6644";
149     private static final String DEF_CHOST = "255.255.255.255"; // Invalid Host IP
150     private static final String DEF_CPORT = "0";               // Invalid Port
151     private static final String DEF_BGP_SDNC_MIP = "127.0.0.1";
152     private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.sdnc.mip";
153     private static final int RESTART_DEFAULT_GR = 90;
154     private static final int DS_RETRY_COUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
155     private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
156     private static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
157     private static final String BGP_ENTITY_NAME = "bgp";
158     private static final String ADD_WARN = "Config store updated; undo with Delete if needed.";
159     private static final String DEL_WARN = "Config store updated; undo with Add if needed.";
160     private static final String UPD_WARN = "Update operation not supported; Config store updated;"
161             + " restore with another Update if needed.";
162
163     private static final Class<?>[] REACTORS = {
164         ConfigServerReactor.class, AsIdReactor.class,
165         GracefulRestartReactor.class, LoggingReactor.class,
166         NeighborsReactor.class, UpdateSourceReactor.class,
167         EbgpMultihopReactor.class, AddressFamiliesReactor.class,
168         NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
169         MultipathReactor.class, VrfMaxpathReactor.class
170     };
171
172     private IBgpManager bgpManager;
173     private final DataBroker dataBroker;
174     private final FibDSWriter fibDSWriter;
175     private final IVpnLinkService vpnLinkService;
176     private final BundleContext bundleContext;
177     private final BgpUtil bgpUtil;
178     private volatile Bgp config;
179     private final BgpRouter bgpRouter;
180     private final BgpSyncHandle bgpSyncHandle = new BgpSyncHandle();
181     private BgpThriftService updateServer;
182
183     private final CountDownLatch initer = new CountDownLatch(1);
184
185     private final String hostStartup;
186     private final String portStartup;
187
188     private final AtomicReference<BgpCounters> bgpCountersReference = new AtomicReference<>();
189     private ScheduledFuture<?> bgpCountersTask;
190
191     private final AtomicReference<BgpAlarms> bgpAlarmsReference = new AtomicReference<>();
192     private ScheduledFuture<?> bgpAlarmsTask;
193
194     private Future<?> lastReplayJobFt;
195     private ScheduledFuture<?> routeCleanupFuture;
196
197     private long staleStartTime;
198     private long staleEndTime;
199     private long cfgReplayStartTime;
200     private long cfgReplayEndTime;
201     private long staleCleanupTime;
202     private int totalStaledCount;
203     private int totalCleared;
204     private int totalExternalRoutes;
205     private int totalExternalMacRoutes;
206
207     private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
208             new ThreadFactoryBuilder().setNameFormat("BgpConfigurationManager-%d").setDaemon(true).build());
209
210     /**
211      * this map store the new address families to send to quagga. When it is sended you must clear it.
212      * The keys String are rd (route distinguisher).
213      * */
214     private final ConcurrentHashMap<String, List<AddressFamiliesVrf>> mapNewAdFamily = new ConcurrentHashMap<>();
215
216     // map<rd, map<prefix/len:nexthop, label>>
217     private final Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
218
219     // map<rd, map<tep-ip, map<mac, l2vni>>>
220     private final Map<String, Map<String, Map<String, Long>>> rt2TepMap = new ConcurrentHashMap<>();
221
222     private final List<AutoCloseable> listeners = new ArrayList<>();
223
224     private final EntityOwnershipUtils entityOwnershipUtils;
225     private final EntityOwnershipCandidateRegistration candidateRegistration;
226     private final EntityOwnershipListenerRegistration entityListenerRegistration;
227     private final MetricProvider metricProvider;
228
229     @Inject
230     public BgpConfigurationManager(final DataBroker dataBroker,
231             final EntityOwnershipService entityOwnershipService,
232             final FibDSWriter fibDSWriter,
233             final IVpnLinkService vpnLinkSrvce,
234             final BundleContext bundleContext,
235             final BgpUtil bgpUtil,
236             final MetricProvider metricProvider) {
237         this.dataBroker = dataBroker;
238         this.fibDSWriter = fibDSWriter;
239         this.vpnLinkService = vpnLinkSrvce;
240         this.bundleContext = bundleContext;
241         this.bgpUtil = bgpUtil;
242         this.metricProvider = metricProvider;
243         String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
244         hostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
245         portStartup = getProperty(CONFIG_PORT, DEF_CPORT);
246         LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
247                 + hostStartup + ":" + portStartup);
248         VtyshCli.setHostAddr(hostStartup);
249         ClearBgpCli.setHostAddr(hostStartup);
250         bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner);
251         registerCallbacks();
252
253         entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
254
255         candidateRegistration = registerEntityCandidate(entityOwnershipService);
256         entityListenerRegistration = registerEntityListener(entityOwnershipService);
257
258         LOG.info("BGP Configuration manager initialized");
259         initer.countDown();
260
261         GlobalEventExecutor.INSTANCE.execute(() -> {
262             final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
263                     IBgpManager.class, bundleContext);
264             bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
265             updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, this);
266             updateServer.start();
267             LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
268         });
269     }
270
271     public String getBgpSdncMipIp() {
272         return getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
273     }
274
275     public long getStaleCleanupTime() {
276         return staleCleanupTime;
277     }
278
279     public void setStaleCleanupTime(long staleCleanupTime) {
280         this.staleCleanupTime = staleCleanupTime;
281     }
282
283     public long getCfgReplayEndTime() {
284         return cfgReplayEndTime;
285     }
286
287     public void setCfgReplayEndTime(long cfgReplayEndTime) {
288         this.cfgReplayEndTime = cfgReplayEndTime;
289     }
290
291     public long getCfgReplayStartTime() {
292         return cfgReplayStartTime;
293     }
294
295     public void setCfgReplayStartTime(long cfgReplayStartTime) {
296         this.cfgReplayStartTime = cfgReplayStartTime;
297     }
298
299     public long getStaleEndTime() {
300         return staleEndTime;
301     }
302
303     public void setStaleEndTime(long staleEndTime) {
304         this.staleEndTime = staleEndTime;
305     }
306
307     public long getStaleStartTime() {
308         return staleStartTime;
309     }
310
311     public void setStaleStartTime(long staleStartTime) {
312         this.staleStartTime = staleStartTime;
313     }
314
315     private Object createListener(Class<?> cls) {
316         try {
317             Constructor<?> ctor = cls.getConstructor(BgpConfigurationManager.class);
318             return ctor.newInstance(this);
319         } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
320                 e) {
321             LOG.error("Failed to create listener object", e);
322             return null;
323         }
324     }
325
326     private void registerCallbacks() {
327         for (Class<?> reactor : REACTORS) {
328             Object obj = createListener(reactor);
329             if (obj != null) {
330                 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
331                 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
332                 listeners.add(dcl);
333             }
334         }
335     }
336
337     @SuppressWarnings("checkstyle:IllegalCatch")
338     @PreDestroy
339     public void close() {
340         executor.shutdown();
341
342         if (updateServer != null) {
343             updateServer.stop();
344         }
345
346         if (candidateRegistration != null) {
347             candidateRegistration.close();
348         }
349
350         entityListenerRegistration.close();
351
352         listeners.forEach(l -> {
353             try {
354                 l.close();
355             } catch (Exception e) {
356                 LOG.warn("Error closing {}", l ,e);
357             }
358         });
359
360         LOG.info("{} close", getClass().getSimpleName());
361     }
362
363     private String getProperty(String var, String def) {
364         String property = bundleContext.getProperty(var);
365         return property == null ? def : property;
366     }
367
368     private EntityOwnershipCandidateRegistration registerEntityCandidate(
369             final EntityOwnershipService entityOwnershipService) {
370         try {
371             return entityOwnershipService.registerCandidate(
372                     new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME));
373         } catch (CandidateAlreadyRegisteredException e) {
374             LOG.error("failed to register bgp entity", e);
375             return null;
376         }
377     }
378
379     private EntityOwnershipListenerRegistration registerEntityListener(
380             final EntityOwnershipService entityOwnershipService) {
381         return entityOwnershipService.registerListener(BGP_ENTITY_TYPE_FOR_OWNERSHIP, ownershipChange -> {
382             LOG.trace("entity owner change event fired: {}", ownershipChange);
383
384             if (ownershipChange.getState() == EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED) {
385                 LOG.trace("This PL is the Owner");
386                 activateMIP();
387                 bgpRestarted();
388             } else {
389                 LOG.debug("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
390                         ownershipChange.getState().isOwner());
391             }
392         });
393     }
394
395     public boolean isBGPEntityOwner() {
396         return entityOwnershipUtils.isEntityOwner(new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME), 0, 1);
397     }
398
399     public Bgp get() {
400         config = getConfig();
401         return config;
402     }
403
404     public class ConfigServerReactor
405             extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
406             implements ClusteredDataTreeChangeListener<ConfigServer> {
407         private static final String YANG_OBJ = "config-server ";
408
409         public ConfigServerReactor() {
410             super(ConfigServer.class, ConfigServerReactor.class);
411         }
412
413         @Override
414         protected void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
415             LOG.trace("received bgp connect config host {}", val.getHost().getValue());
416             if (!isBGPEntityOwner()) {
417                 return;
418             }
419
420             try {
421                 initer.await();
422             } catch (InterruptedException e) {
423                 // Ignored
424             }
425             LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
426             bgpRouter.configServerUpdated();
427             synchronized (BgpConfigurationManager.this) {
428                 boolean res = bgpRouter.connect(val.getHost().getValue(),
429                         val.getPort().intValue());
430                 if (!res) {
431                     LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
432                 }
433             }
434             VtyshCli.setHostAddr(val.getHost().getValue());
435             ClearBgpCli.setHostAddr(val.getHost().getValue());
436         }
437
438         @Override
439         protected ConfigServerReactor getDataTreeChangeListener() {
440             return ConfigServerReactor.this;
441         }
442
443         @Override
444         protected InstanceIdentifier<ConfigServer> getWildCardPath() {
445             return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
446         }
447
448         @Override
449         protected void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
450             LOG.trace("received bgp disconnect");
451             if (!isBGPEntityOwner()) {
452                 return;
453             }
454
455             bgpRouter.configServerUpdated();
456
457             synchronized (BgpConfigurationManager.this) {
458                 bgpRouter.disconnect();
459             }
460         }
461
462         @Override
463         protected void update(InstanceIdentifier<ConfigServer> iid,
464                 ConfigServer oldval, ConfigServer newval) {
465             LOG.trace("received bgp Connection update");
466             if (!isBGPEntityOwner()) {
467                 return;
468             }
469             LOG.error(YANG_OBJ + UPD_WARN);
470         }
471     }
472
473     private BgpRouter getClient(String yangObj) {
474         if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
475             LOG.warn("{}: configuration received when BGP is inactive", yangObj);
476             return null;
477         }
478         return bgpRouter;
479     }
480
481     public class AsIdReactor
482             extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
483             implements ClusteredDataTreeChangeListener<AsId> {
484
485         private static final String YANG_OBJ = "as-id ";
486
487         public AsIdReactor() {
488             super(AsId.class, AsIdReactor.class);
489         }
490
491         @Override
492         protected void add(InstanceIdentifier<AsId> iid, AsId val) {
493             LOG.error("received bgp add asid {}", val);
494             if (!isBGPEntityOwner()) {
495                 return;
496             }
497             LOG.debug("received add router config asNum {}", val.getLocalAs());
498             synchronized (BgpConfigurationManager.this) {
499                 BgpRouter br = getClient(YANG_OBJ);
500                 if (br == null) {
501                     LOG.debug("{} Unable to process add for asNum {}; {}", YANG_OBJ, val.getLocalAs(),
502                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
503                     return;
504                 }
505                 bgpRestarted();
506
507                 startBgpCountersTask();
508                 startBgpAlarmsTask();
509             }
510         }
511
512         @Override
513         protected AsIdReactor getDataTreeChangeListener() {
514             return AsIdReactor.this;
515         }
516
517         @Override
518         protected InstanceIdentifier<AsId> getWildCardPath() {
519             return InstanceIdentifier.create(Bgp.class).child(AsId.class);
520         }
521
522         @Override
523         protected void remove(InstanceIdentifier<AsId> iid, AsId val) {
524             LOG.error("received delete router config asNum {}", val.getLocalAs());
525             if (!isBGPEntityOwner()) {
526                 return;
527             }
528             synchronized (BgpConfigurationManager.this) {
529                 long asNum = val.getLocalAs();
530                 BgpRouter br = getClient(YANG_OBJ);
531                 if (br == null) {
532                     LOG.debug("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
533                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
534                     return;
535                 }
536                 try {
537                     br.stopBgp(asNum);
538                 } catch (TException | BgpRouterException e) {
539                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
540                 }
541
542                 stopBgpCountersTask();
543                 stopBgpAlarmsTask();
544
545                 Bgp conf = getConfig();
546                 if (conf == null) {
547                     LOG.error("Config Null while removing the as-id");
548                     return;
549                 }
550                 LOG.debug("Removing external routes from FIB");
551                 deleteExternalFibRoutes();
552                 List<Neighbors> nbrs = conf.getNeighbors();
553                 if (nbrs != null && nbrs.size() > 0) {
554                     LOG.error("Tring to remove the as-id when neighbor config is already present");
555                     for (Neighbors nbr : nbrs) {
556                         LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
557                         delNeighbor(nbr.getAddress().getValue());
558                     }
559                 }
560             }
561         }
562
563         @Override
564         protected void update(InstanceIdentifier<AsId> iid,
565                 AsId oldval, AsId newval) {
566             if (!isBGPEntityOwner()) {
567                 return;
568             }
569             LOG.error(YANG_OBJ + UPD_WARN);
570         }
571     }
572
573     public class GracefulRestartReactor
574             extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
575             implements ClusteredDataTreeChangeListener<GracefulRestart> {
576
577         private static final String YANG_OBJ = "graceful-restart ";
578
579         public GracefulRestartReactor() {
580             super(GracefulRestart.class, GracefulRestartReactor.class);
581         }
582
583         @Override
584         protected void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
585             if (!isBGPEntityOwner()) {
586                 return;
587             }
588             synchronized (BgpConfigurationManager.this) {
589                 int stalePathTime = val.getStalepathTime().intValue();
590                 BgpRouter br = getClient(YANG_OBJ);
591                 if (br == null) {
592                     LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
593                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
594                     return;
595                 }
596                 try {
597                     br.addGracefulRestart(stalePathTime);
598                 } catch (TException | BgpRouterException e) {
599                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
600                 }
601             }
602         }
603
604         @Override
605         protected GracefulRestartReactor getDataTreeChangeListener() {
606             return GracefulRestartReactor.this;
607         }
608
609         @Override
610         protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
611             return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
612         }
613
614         @Override
615         protected void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
616             if (!isBGPEntityOwner()) {
617                 return;
618             }
619             LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
620             synchronized (BgpConfigurationManager.this) {
621                 BgpRouter br = getClient(YANG_OBJ);
622                 if (br == null) {
623                     LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
624                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
625                     return;
626                 }
627                 try {
628                     br.delGracefulRestart();
629                 } catch (TException | BgpRouterException e) {
630                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
631                 }
632             }
633         }
634
635         @Override
636         protected void update(InstanceIdentifier<GracefulRestart> iid,
637                 GracefulRestart oldval, GracefulRestart newval) {
638             if (!isBGPEntityOwner()) {
639                 return;
640             }
641             LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
642             synchronized (BgpConfigurationManager.this) {
643                 int stalePathTime = newval.getStalepathTime().intValue();
644                 BgpRouter br = getClient(YANG_OBJ);
645                 if (br == null) {
646                     LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
647                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
648                     return;
649                 }
650                 try {
651                     br.addGracefulRestart(stalePathTime);
652                 } catch (TException | BgpRouterException e) {
653                     LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
654                 }
655             }
656         }
657     }
658
659     public class LoggingReactor
660             extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
661             implements ClusteredDataTreeChangeListener<Logging> {
662
663         private static final String YANG_OBJ = "logging ";
664
665         public LoggingReactor() {
666             super(Logging.class, LoggingReactor.class);
667         }
668
669         @Override
670         protected void add(InstanceIdentifier<Logging> iid, Logging val) {
671             if (!isBGPEntityOwner()) {
672                 return;
673             }
674             synchronized (BgpConfigurationManager.this) {
675                 BgpRouter br = getClient(YANG_OBJ);
676                 if (br == null) {
677                     LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
678                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
679                     return;
680                 }
681                 try {
682                     br.setLogging(val.getFile(), val.getLevel());
683                 } catch (TException | BgpRouterException e) {
684                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
685                 }
686             }
687         }
688
689         @Override
690         protected LoggingReactor getDataTreeChangeListener() {
691             return LoggingReactor.this;
692         }
693
694         @Override
695         protected InstanceIdentifier<Logging> getWildCardPath() {
696             return InstanceIdentifier.create(Bgp.class).child(Logging.class);
697         }
698
699         @Override
700         protected void remove(InstanceIdentifier<Logging> iid, Logging val) {
701             if (!isBGPEntityOwner()) {
702                 return;
703             }
704             LOG.debug("received remove Logging config val {}", val.getLevel());
705             synchronized (BgpConfigurationManager.this) {
706                 BgpRouter br = getClient(YANG_OBJ);
707                 if (br == null) {
708                     LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
709                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
710                     return;
711                 }
712                 try {
713                     br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
714                 } catch (TException | BgpRouterException e) {
715                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
716                 }
717             }
718         }
719
720         @Override
721         protected void update(InstanceIdentifier<Logging> iid,
722                 Logging oldval, Logging newval) {
723             if (!isBGPEntityOwner()) {
724                 return;
725             }
726             synchronized (BgpConfigurationManager.this) {
727                 BgpRouter br = getClient(YANG_OBJ);
728                 if (br == null) {
729                     LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
730                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
731                     return;
732                 }
733                 try {
734                     br.setLogging(newval.getFile(), newval.getLevel());
735                 } catch (TException | BgpRouterException e) {
736                     LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
737                 }
738             }
739         }
740     }
741
742     public class NeighborsReactor
743             extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
744             implements ClusteredDataTreeChangeListener<Neighbors> {
745
746         private static final String YANG_OBJ = "neighbors ";
747
748         public NeighborsReactor() {
749             super(Neighbors.class, NeighborsReactor.class);
750         }
751
752         @Override
753         protected void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
754             if (!isBGPEntityOwner()) {
755                 return;
756             }
757             LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
758             synchronized (BgpConfigurationManager.this) {
759                 String peerIp = val.getAddress().getValue();
760                 long as = val.getRemoteAs();
761                 final String md5Secret = extractMd5Secret(val);
762                 BgpRouter br = getClient(YANG_OBJ);
763                 if (br == null) {
764                     LOG.debug("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
765                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
766                     return;
767                 }
768                 try {
769                     //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
770                     br.addNeighbor(peerIp, as, md5Secret);
771
772                 } catch (TException | BgpRouterException e) {
773                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
774                 }
775             }
776         }
777
778         @Override
779         protected NeighborsReactor getDataTreeChangeListener() {
780             return NeighborsReactor.this;
781         }
782
783         @Override
784         protected InstanceIdentifier<Neighbors> getWildCardPath() {
785             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
786         }
787
788         @Override
789         protected void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
790             if (!isBGPEntityOwner()) {
791                 return;
792             }
793             LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
794             synchronized (BgpConfigurationManager.this) {
795                 String peerIp = val.getAddress().getValue();
796                 BgpRouter br = getClient(YANG_OBJ);
797                 if (br == null) {
798                     LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
799                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
800                     return;
801                 }
802                 try {
803                     //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
804                     br.delNeighbor(peerIp);
805                 } catch (TException | BgpRouterException e) {
806                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
807                 }
808
809                 final BgpAlarms bgpAlarms = getBgpAlarms();
810                 if (bgpAlarms != null) {
811                     bgpAlarms.clearBgpNbrDownAlarm(peerIp);
812                 }
813             }
814         }
815
816         @Override
817         protected void update(InstanceIdentifier<Neighbors> iid,
818                 Neighbors oldval, Neighbors newval) {
819             if (!isBGPEntityOwner()) {
820                 return;
821             }
822             //purposefully nothing to do.
823         }
824     }
825
826     public class EbgpMultihopReactor
827             extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
828             implements ClusteredDataTreeChangeListener<EbgpMultihop> {
829
830         private static final String YANG_OBJ = "ebgp-multihop ";
831
832         public EbgpMultihopReactor() {
833             super(EbgpMultihop.class, EbgpMultihopReactor.class);
834         }
835
836         @Override
837         protected void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
838             if (!isBGPEntityOwner()) {
839                 return;
840             }
841             LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
842             synchronized (BgpConfigurationManager.this) {
843                 String peerIp = val.getPeerIp().getValue();
844                 BgpRouter br = getClient(YANG_OBJ);
845                 if (br == null) {
846                     LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
847                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
848                     return;
849                 }
850                 try {
851                     br.addEbgpMultihop(peerIp, val.getNhops().intValue());
852                 } catch (TException | BgpRouterException e) {
853                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
854                 }
855             }
856         }
857
858         @Override
859         protected EbgpMultihopReactor getDataTreeChangeListener() {
860             return EbgpMultihopReactor.this;
861         }
862
863         @Override
864         protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
865             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
866         }
867
868         @Override
869         protected void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
870             if (!isBGPEntityOwner()) {
871                 return;
872             }
873             LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
874             synchronized (BgpConfigurationManager.this) {
875                 String peerIp = val.getPeerIp().getValue();
876                 BgpRouter br = getClient(YANG_OBJ);
877                 if (br == null) {
878                     LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
879                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
880                     return;
881                 }
882                 try {
883                     br.delEbgpMultihop(peerIp);
884                 } catch (TException | BgpRouterException e) {
885                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
886                 }
887             }
888         }
889
890         @Override
891         protected void update(InstanceIdentifier<EbgpMultihop> iid,
892                 EbgpMultihop oldval, EbgpMultihop newval) {
893             if (!isBGPEntityOwner()) {
894                 return;
895             }
896             LOG.error(YANG_OBJ + UPD_WARN);
897         }
898     }
899
900     public class UpdateSourceReactor
901             extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
902             implements ClusteredDataTreeChangeListener<UpdateSource> {
903
904         private static final String YANG_OBJ = "update-source ";
905
906         public UpdateSourceReactor() {
907             super(UpdateSource.class, UpdateSourceReactor.class);
908         }
909
910         @Override
911         protected void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
912             if (!isBGPEntityOwner()) {
913                 return;
914             }
915             LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
916             synchronized (BgpConfigurationManager.this) {
917                 String peerIp = val.getPeerIp().getValue();
918                 BgpRouter br = getClient(YANG_OBJ);
919                 if (br == null) {
920                     LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
921                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
922                     return;
923                 }
924                 try {
925                     br.addUpdateSource(peerIp, val.getSourceIp().getValue());
926                 } catch (TException | BgpRouterException e) {
927                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
928                 }
929             }
930         }
931
932         @Override
933         protected UpdateSourceReactor getDataTreeChangeListener() {
934             return UpdateSourceReactor.this;
935         }
936
937         @Override
938         protected InstanceIdentifier<UpdateSource> getWildCardPath() {
939             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
940         }
941
942         @Override
943         protected void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
944             if (!isBGPEntityOwner()) {
945                 return;
946             }
947             LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
948             synchronized (BgpConfigurationManager.this) {
949                 String peerIp = val.getPeerIp().getValue();
950                 BgpRouter br = getClient(YANG_OBJ);
951                 if (br == null) {
952                     LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
953                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
954                     return;
955                 }
956                 try {
957                     br.delUpdateSource(peerIp);
958                 } catch (TException | BgpRouterException e) {
959                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
960                 }
961             }
962         }
963
964         @Override
965         protected void update(InstanceIdentifier<UpdateSource> iid,
966                 UpdateSource oldval, UpdateSource newval) {
967             if (!isBGPEntityOwner()) {
968                 return;
969             }
970             LOG.error(YANG_OBJ + UPD_WARN);
971         }
972     }
973
974     public class AddressFamiliesReactor
975             extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
976             implements ClusteredDataTreeChangeListener<AddressFamilies> {
977
978         private static final String YANG_OBJ = "address-families ";
979
980         public AddressFamiliesReactor() {
981             super(AddressFamilies.class, AddressFamiliesReactor.class);
982         }
983
984         @Override
985         protected void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
986             if (!isBGPEntityOwner()) {
987                 return;
988             }
989             LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
990             synchronized (BgpConfigurationManager.this) {
991                 String peerIp = val.getPeerIp().getValue();
992                 BgpRouter br = getClient(YANG_OBJ);
993                 if (br == null) {
994                     LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
995                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
996                     return;
997                 }
998                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
999                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1000                 try {
1001                     br.addAddressFamily(peerIp, afi, safi);
1002                 } catch (TException | BgpRouterException e) {
1003                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1004                 }
1005             }
1006         }
1007
1008         @Override
1009         protected AddressFamiliesReactor getDataTreeChangeListener() {
1010             return AddressFamiliesReactor.this;
1011         }
1012
1013         @Override
1014         protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
1015             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
1016         }
1017
1018         @Override
1019         protected void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1020             if (!isBGPEntityOwner()) {
1021                 return;
1022             }
1023             LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
1024             synchronized (BgpConfigurationManager.this) {
1025                 String peerIp = val.getPeerIp().getValue();
1026                 BgpRouter br = getClient(YANG_OBJ);
1027                 if (br == null) {
1028                     LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
1029                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1030                     return;
1031                 }
1032                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1033                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1034                 try {
1035                     br.delAddressFamily(peerIp, afi, safi);
1036                 } catch (TException | BgpRouterException e) {
1037                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1038                 }
1039             }
1040         }
1041
1042         @Override
1043         protected void update(InstanceIdentifier<AddressFamilies> iid,
1044                 AddressFamilies oldval, AddressFamilies newval) {
1045             if (!isBGPEntityOwner()) {
1046                 return;
1047             }
1048             LOG.error(YANG_OBJ + UPD_WARN);
1049         }
1050     }
1051
1052     public class NetworksReactor
1053             extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1054             implements ClusteredDataTreeChangeListener<Networks> {
1055
1056         private static final String YANG_OBJ = "networks ";
1057
1058         public NetworksReactor() {
1059             super(Networks.class, NetworksReactor.class);
1060         }
1061
1062         @Override
1063         public NetworksReactor getDataTreeChangeListener() {
1064             return NetworksReactor.this;
1065         }
1066
1067         @Override
1068         protected void add(InstanceIdentifier<Networks> iid, Networks val) {
1069             if (!isBGPEntityOwner()) {
1070                 return;
1071             }
1072             LOG.debug("received add Networks config val {}", val.getPrefixLen());
1073             synchronized (BgpConfigurationManager.this) {
1074                 String rd = val.getRd();
1075                 String pfxlen = val.getPrefixLen();
1076                 String nh = val.getNexthop().getValue();
1077                 BgpRouter br = getClient(YANG_OBJ);
1078                 if (br == null) {
1079                     LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
1080                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1081                     return;
1082                 }
1083                 Long label = val.getLabel();
1084                 int lbl = label == null ? qbgpConstants.LBL_NO_LABEL
1085                         : label.intValue();
1086                 int l3vni = val.getL3vni() == null ? qbgpConstants.LBL_NO_LABEL
1087                         : val.getL3vni().intValue();
1088                 int l2vni = val.getL2vni() == null ? qbgpConstants.LBL_NO_LABEL
1089                         : val.getL2vni().intValue();
1090
1091                 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1092                 int ethernetTag = val.getEthtag().intValue();
1093                 String esi = val.getEsi();
1094                 String macaddress = val.getMacaddress();
1095                 EncapType encapType = val.getEncapType();
1096                 String routerMac = val.getRoutermac();
1097
1098                 try {
1099                     br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni, BgpUtil.convertToThriftProtocolType(protocolType),
1100                             ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1101                 } catch (TException | BgpRouterException e) {
1102                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1103                 }
1104             }
1105         }
1106
1107         @Override
1108         protected InstanceIdentifier<Networks> getWildCardPath() {
1109             return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1110         }
1111
1112         @Override
1113         protected void remove(InstanceIdentifier<Networks> iid, Networks val) {
1114             if (!isBGPEntityOwner()) {
1115                 return;
1116             }
1117             LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1118             synchronized (BgpConfigurationManager.this) {
1119                 String rd = val.getRd();
1120                 String pfxlen = val.getPrefixLen();
1121                 BgpRouter br = getClient(YANG_OBJ);
1122                 if (br == null) {
1123                     LOG.debug("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
1124                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1125                     return;
1126                 }
1127                 Long label = val.getLabel();
1128                 int lbl = label == null ? 0 : label.intValue();
1129                 if (rd == null && lbl > 0) {
1130                     //LU prefix is being deleted.
1131                     rd = Integer.toString(lbl);
1132                 }
1133                 try {
1134                     br.delPrefix(rd, pfxlen);
1135                 } catch (TException | BgpRouterException e) {
1136                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1137                 }
1138             }
1139         }
1140
1141         /**get the value AFI from a prefix as "x.x.x.x/x".
1142          *
1143          * @param pfxlen the prefix to get an afi
1144          * @return the afi value as you are need
1145          */
1146         public  int  testValueAFI(String pfxlen) {
1147             int afiNew = af_afi.AFI_IP.getValue();
1148             try {
1149                 String ipOnly = pfxlen.substring(0, pfxlen.lastIndexOf("/"));
1150                 java.net.Inet6Address.getByName(ipOnly);
1151                 afiNew = af_afi.AFI_IPV6.getValue();
1152             } catch (java.net.UnknownHostException e) {
1153                 //ce n'est pas de l'ipv6
1154             }
1155             return afiNew;
1156         }
1157
1158
1159         @Override
1160         protected void update(final InstanceIdentifier<Networks> iid,
1161                 final Networks oldval, final Networks newval) {
1162             if (!isBGPEntityOwner()) {
1163                 return;
1164             }
1165             if (oldval.equals(newval)) {
1166                 //Update: OLD and New values are same, no need to trigger remove/add.
1167                 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1168                         oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1169                 return;
1170             }
1171             LOG.debug("update networks old val RD: {}, Prefix: {}, Label: {}, NH: {} "
1172                             + "new val RD: {}, Prefix: {}, Label: {}, NH: {}",
1173                     oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop(),
1174                     newval.getRd(), newval.getPrefixLen(), newval.getLabel(), newval.getNexthop());
1175             remove(iid, oldval);
1176             add(iid, newval);
1177         }
1178     }
1179
1180     static Timer timer = new Timer();
1181
1182     public class VrfsReactor
1183             extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1184             implements ClusteredDataTreeChangeListener<Vrfs> {
1185
1186         private static final String YANG_OBJ = "vrfs ";
1187
1188         public VrfsReactor() {
1189             super(Vrfs.class, VrfsReactor.class);
1190         }
1191
1192         @Override
1193         protected void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
1194             if (!isBGPEntityOwner()) {
1195                 return;
1196             }
1197             LOG.debug("received add Vrfs config value {}", vrfs.getRd());
1198             synchronized (BgpConfigurationManager.this) {
1199                 String rd = vrfs.getRd();
1200                 BgpRouter br = getClient(YANG_OBJ);
1201                 if (br == null) {
1202                     LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1203                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1204                     return;
1205                 }
1206                 try {
1207                     List<AddressFamiliesVrf> vrfAddrFamilyList = vrfs.getAddressFamiliesVrf();
1208                     for (AddressFamiliesVrf vrfAddrFamily : vrfAddrFamilyList) {
1209                         /*add to br the new vrfs arguments*/
1210                         br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(), vrfs.getExportRts(),
1211                                 vrfAddrFamily.getAfi(), vrfAddrFamily.getSafi());
1212                     }
1213                     /*add to br the vrfs contained in mapNewAdFamily*/
1214                     List<AddressFamiliesVrf> vrfAddrFamilyListFromMap = mapNewAdFamily.get(rd);
1215                     if (vrfAddrFamilyListFromMap == null) {
1216                         return;
1217                     }
1218
1219                     for (AddressFamiliesVrf adf : vrfAddrFamilyListFromMap) {
1220                         if (vrfAddrFamilyList.contains(adf)) {
1221                             mapNewAdFamily.remove(rd);
1222                         } else  if (adf != null) {
1223
1224                             br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(), vrfs.getExportRts(),
1225                                     adf.getAfi(), adf.getSafi());
1226                             // remove AddressFamiliesVrf which was already added to BGP
1227                             vrfAddrFamilyListFromMap.remove(adf);
1228                             if (vrfAddrFamilyListFromMap.isEmpty()) {
1229                                 // remove Vrf entry from temp mapNewAdFamily if all its AddressFamiliesVrf was
1230                                 // added to BGP
1231                                 mapNewAdFamily.remove(rd);
1232                             }
1233                         }
1234                     }
1235                 } catch (TException | BgpRouterException e) {
1236                     LOG.error("{} get {}, Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1237                 }
1238             }
1239         }
1240
1241         @Override
1242         protected VrfsReactor getDataTreeChangeListener() {
1243             return VrfsReactor.this;
1244         }
1245
1246         @Override
1247         protected InstanceIdentifier<Vrfs> getWildCardPath() {
1248             return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1249         }
1250
1251         @Override
1252         protected void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1253             if (!isBGPEntityOwner()) {
1254                 return;
1255             }
1256             LOG.debug("received remove Vrfs config val {}", val.getRd());
1257             synchronized (BgpConfigurationManager.this) {
1258                 String rd = val.getRd();
1259                 BgpRouter br = getClient(YANG_OBJ);
1260                 if (br == null) {
1261                     LOG.debug("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
1262                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1263                     return;
1264                 }
1265                 try {
1266                     List<AddressFamiliesVrf> adf = mapNewAdFamily.get(rd);
1267                     adf = adf != null ? adf : new ArrayList<>();
1268                     for (AddressFamiliesVrf s : val.getAddressFamiliesVrf()) {
1269                         br.delVrf(rd, s.getAfi(), s.getSafi());
1270                         adf.remove(s);// remove in the map the vrf in waiting for advertise quagga
1271                     }
1272                     if (adf.isEmpty()) {
1273                         mapNewAdFamily.remove(rd);
1274                     }
1275                 } catch (TException | BgpRouterException e) {
1276                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1277                 }
1278             }
1279         }
1280
1281         @Override
1282         protected void update(InstanceIdentifier<Vrfs> iid,
1283                 Vrfs oldval, Vrfs newval) {
1284             if (oldval != null && newval != null) {
1285                 LOG.debug("received update Vrfs config val {}, VRFS: Update getting triggered for VRFS rd {}",
1286                         newval.getRd(), oldval.getRd());
1287             } else {
1288                 LOG.debug("received update Vrfs config val {}, from old vrf {}",
1289                         newval, oldval);
1290             }
1291             if (!isBGPEntityOwner()) {
1292                 return;
1293             }
1294
1295             List<AddressFamiliesVrf> adFamilyVrfToDel = new ArrayList<>();
1296             List<AddressFamiliesVrf> adFamilyVrfToAdd = new ArrayList<>();
1297             List<AddressFamiliesVrf> oldlistAdFamilies = new ArrayList<>();
1298             List<AddressFamiliesVrf> newlistAdFamilies = new ArrayList<>();
1299             if (oldval != null) {
1300                 oldlistAdFamilies = oldval.getAddressFamiliesVrf() == null
1301                         ? new ArrayList<>() : oldval.getAddressFamiliesVrf();
1302             }
1303             if (newval != null) {
1304                 newlistAdFamilies = newval.getAddressFamiliesVrf() == null
1305                         ? new ArrayList<>() : newval.getAddressFamiliesVrf();
1306             }
1307             /*find old AddressFamily to remove from new configuration*/
1308             for (AddressFamiliesVrf adVrf : oldlistAdFamilies) {
1309                 if (!newlistAdFamilies.contains(adVrf)) {
1310                     adFamilyVrfToDel.add(adVrf);
1311                 }
1312             }
1313             /*find new AddressFamily to add to unexisting configuration*/
1314             for (AddressFamiliesVrf adVrf : newlistAdFamilies) {
1315                 if (!oldlistAdFamilies.contains(adVrf)) {
1316                     adFamilyVrfToAdd.add(adVrf);
1317                 }
1318             }
1319             String rd = newval != null ? newval.getRd() : null;
1320             if (rd != null) {
1321                 BgpRouter br = getClient(YANG_OBJ);
1322                 if (br == null) {
1323                     LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1324                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1325                     return;
1326                 }
1327
1328                 for (AddressFamiliesVrf adfvrf : adFamilyVrfToAdd) {
1329                     try {
1330                         LOG.debug("call addVRf rd {} afi {} safi {}", rd, adfvrf.getAfi(), adfvrf.getSafi());
1331                         br.addVrf(BgpUtil.getLayerType(adfvrf), rd, newval.getImportRts(),
1332                                 newval.getExportRts(), adfvrf.getAfi(), adfvrf.getSafi());
1333                     } catch (TException | BgpRouterException e) {
1334                         LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1335                     }
1336                 }
1337
1338                 for (AddressFamiliesVrf adfToDel : adFamilyVrfToDel) {
1339                     try {
1340                         LOG.debug("call delVRf rd {} afi {} safi {}", rd, adfToDel.getAfi(), adfToDel.getSafi());
1341                         br.delVrf(rd, adfToDel.getAfi(), adfToDel.getSafi());
1342                     } catch (TException | BgpRouterException e) {
1343                         LOG.error("{} delVrf received exception; {}", YANG_OBJ, ADD_WARN, e);
1344                     }
1345                 }
1346             }
1347         }
1348     }
1349
1350     protected void activateMIP() {
1351         try {
1352             LOG.trace("BgpReactor: Executing MIP Activate command");
1353             Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1354             Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1355             LOG.trace("bgpMIP Activated");
1356
1357         } catch (IOException io) {
1358             LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1359         }
1360     }
1361
1362     public class BgpReactor
1363             extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1364             implements ClusteredDataTreeChangeListener<Bgp> {
1365
1366         private static final String YANG_OBJ = "Bgp ";
1367
1368         public BgpReactor() {
1369             super(Bgp.class, BgpReactor.class);
1370         }
1371
1372
1373         @Override
1374         protected void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1375             LOG.debug("received add Bgp config");
1376
1377             try {
1378                 initer.await();
1379             } catch (InterruptedException e) {
1380                 // Ignored
1381             }
1382             synchronized (BgpConfigurationManager.this) {
1383                 config = val;
1384                 if (!isBGPEntityOwner()) {
1385                     return;
1386                 }
1387                 activateMIP();
1388             }
1389         }
1390
1391         @Override
1392         protected BgpReactor getDataTreeChangeListener() {
1393             return BgpReactor.this;
1394         }
1395
1396         @Override
1397         protected InstanceIdentifier<Bgp> getWildCardPath() {
1398             return InstanceIdentifier.create(Bgp.class);
1399         }
1400
1401         @Override
1402         protected void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1403             if (!isBGPEntityOwner()) {
1404                 return;
1405             }
1406             LOG.debug("received remove Bgp config");
1407
1408             config = null;
1409         }
1410
1411         @Override
1412         protected void update(InstanceIdentifier<Bgp> iid,
1413                 Bgp oldval, Bgp newval) {
1414             if (!isBGPEntityOwner()) {
1415                 return;
1416             }
1417
1418             config = newval;
1419         }
1420     }
1421
1422     @SuppressWarnings("deprecation")
1423     public class MultipathReactor
1424             extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1425             implements ClusteredDataTreeChangeListener<Multipath> {
1426
1427         private static final String YANG_OBJ = "multipath ";
1428
1429         public MultipathReactor() {
1430             super(Multipath.class, MultipathReactor.class);
1431         }
1432
1433
1434         @Override
1435         protected MultipathReactor getDataTreeChangeListener() {
1436             return MultipathReactor.this;
1437         }
1438
1439         @Override
1440         protected InstanceIdentifier<Multipath> getWildCardPath() {
1441             return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
1442         }
1443
1444         @Override
1445         protected void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1446             executor.execute(new MultipathStatusChange(val));
1447         }
1448
1449         @Override
1450         protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1451             executor.execute(new MultipathStatusChange(newval));
1452         }
1453
1454         @Override
1455         protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1456             executor.execute(new MultipathStatusChange(dataObjectModification));
1457         }
1458
1459         class MultipathStatusChange implements Runnable {
1460
1461             Multipath multipath;
1462
1463             MultipathStatusChange(Multipath multipath) {
1464                 this.multipath = multipath;
1465             }
1466
1467             @Override
1468             public void run() {
1469                 if (isBGPEntityOwner()) {
1470                     synchronized (BgpConfigurationManager.this) {
1471
1472                         BgpRouter br = getClient(YANG_OBJ);
1473
1474                         if (br != null) {
1475                             af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1476                             af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1477
1478                             try {
1479                                 if (multipath.isMultipathEnabled()) {
1480                                     br.enableMultipath(afi, safi);
1481                                 } else {
1482                                     br.disableMultipath(afi, safi);
1483                                 }
1484                             } catch (TException | BgpRouterException e) {
1485                                 LOG.error(YANG_OBJ + " received exception: \"" + e + "\"");
1486                             }
1487                         }
1488                     }
1489                 }
1490             }
1491
1492         }
1493
1494         @Override
1495         public void close() {
1496             super.close();
1497         }
1498     }
1499
1500     @SuppressWarnings("deprecation")
1501     public class VrfMaxpathReactor
1502             extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1503             implements ClusteredDataTreeChangeListener<VrfMaxpath> {
1504
1505         private static final String YANG_OBJ = "vrfMaxpath ";
1506
1507         public VrfMaxpathReactor() {
1508             super(VrfMaxpath.class, VrfMaxpathReactor.class);
1509         }
1510
1511
1512         @Override
1513         protected VrfMaxpathReactor getDataTreeChangeListener() {
1514             return VrfMaxpathReactor.this;
1515         }
1516
1517         @Override
1518         protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1519             return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
1520         }
1521
1522         class VrfMaxPathConfigurator implements Runnable {
1523
1524             VrfMaxpath vrfMaxpathVal;
1525
1526             VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1527                 this.vrfMaxpathVal = vrfMaxPathVal;
1528             }
1529
1530             @Override
1531             public void run() {
1532                 if (isBGPEntityOwner()) {
1533                     synchronized (BgpConfigurationManager.this) {
1534                         BgpRouter br = getClient(YANG_OBJ);
1535                         if (br != null) {
1536                             try {
1537                                 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
1538                                 LOG.debug("Maxpath for vrf: " + vrfMaxpathVal.getRd() + " : is "
1539                                         + vrfMaxpathVal.getMaxpaths());
1540                             } catch (TException | BgpRouterException e) {
1541                                 LOG.error(YANG_OBJ
1542                                         + " received exception: \"" + e + "\"");
1543                             }
1544                         }
1545                     }
1546                 }
1547             }
1548         }
1549
1550         @Override
1551         protected void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1552             executor.execute(new VrfMaxPathConfigurator(vrfMaxPathVal));
1553         }
1554
1555         @Override
1556         protected void update(InstanceIdentifier<VrfMaxpath> iid,
1557                               VrfMaxpath oldval, VrfMaxpath newval) {
1558             if (!Objects.equals(oldval.getMaxpaths(), newval.getMaxpaths())) {
1559                 executor.execute(new VrfMaxPathConfigurator(newval));
1560             }
1561         }
1562
1563         @Override
1564         protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1565             executor.execute(new VrfMaxPathConfigurator(vrfMaxpathVal));
1566         }
1567
1568         @Override
1569         public void close() {
1570             super.close();
1571         }
1572     }
1573
1574     public boolean isIpAvailable(String odlip) {
1575
1576         try {
1577             if (odlip != null) {
1578                 if ("127.0.0.1".equals(odlip)) {
1579                     return true;
1580                 }
1581                 Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1582                 while (networkInterfaceEnumeration.hasMoreElements()) {
1583                     NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
1584                     Enumeration<InetAddress>  inetAddressEnumeration = networkInterface.getInetAddresses();
1585                     while (inetAddressEnumeration.hasMoreElements()) {
1586                         InetAddress inetAddress = inetAddressEnumeration.nextElement();
1587                         if (odlip.equals(inetAddress.getHostAddress())) {
1588                             return true;
1589                         }
1590                     }
1591                 }
1592             }
1593         } catch (SocketException e) {
1594             // Ignored?
1595         }
1596         return false;
1597     }
1598
1599     public long getStalePathtime(int defValue, AsId asId) {
1600         long spt = 0;
1601         try {
1602             spt = getConfig().getGracefulRestart().getStalepathTime();
1603         } catch (NullPointerException e) {
1604             try {
1605                 spt = asId.getStalepathTime();
1606                 LOG.trace("BGP config/Stale-path time is not set using graceful");
1607             } catch (NullPointerException ignore) {
1608                 LOG.trace("BGP AS id is not set using graceful");
1609                 spt = defValue;
1610             }
1611         }
1612         if (spt == 0) {
1613             LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1614             spt = defValue;
1615         }
1616         return spt;
1617     }
1618
1619     public static boolean isValidConfigBgpHostPort(String bgpHost, int bgpPort) {
1620         if (!bgpHost.equals(DEF_CHOST) && bgpPort != Integer.parseInt(DEF_CPORT)) {
1621             return true;
1622         } else {
1623             return false;
1624         }
1625     }
1626
1627     public synchronized void bgpRestarted() {
1628         /*
1629          * If there a thread which in the process of stale cleanup, cancel it
1630          * and start a new thread (to avoid processing same again).
1631          */
1632         if (previousReplayJobInProgress()) {
1633             cancelPreviousReplayJob();
1634         }
1635         Runnable task = () -> {
1636             try {
1637                 LOG.info("running bgp replay task ");
1638                 if (get() == null) {
1639                     String host = getConfigHost();
1640                     int port = getConfigPort();
1641                     LOG.info("connecting  to bgp host {} ", host);
1642                     bgpRouter.connect(host, port);
1643                     LOG.info("no config to push in bgp replay task ");
1644                     return;
1645                 }
1646                 setStaleStartTime(System.currentTimeMillis());
1647                 LOG.info("started creating stale fibDSWriter  map ");
1648                 createStaleFibMap();
1649                 setStaleEndTime(System.currentTimeMillis());
1650                 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1651                 LOG.info("started bgp config replay ");
1652                 setCfgReplayStartTime(System.currentTimeMillis());
1653                 boolean replaySucceded = replay();
1654                 setCfgReplayEndTime(System.currentTimeMillis());
1655                 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1656                 if (replaySucceded) {
1657                     LOG.info("starting the stale cleanup timer");
1658                     long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1659                     setStaleCleanupTime(routeSyncTime);
1660                     routeCleanupFuture = executor.schedule(new RouteCleanup(), routeSyncTime, TimeUnit.SECONDS);
1661                 } else {
1662                     staledFibEntriesMap.clear();
1663                 }
1664             } catch (InterruptedException | TimeoutException | ExecutionException eCancel) {
1665                 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1666             }
1667         };
1668         lastReplayJobFt = executor.submit(task);
1669     }
1670
1671     private boolean previousReplayJobInProgress() {
1672         return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1673     }
1674
1675     private void cancelPreviousReplayJob() {
1676         try {
1677             LOG.error("cancelling already running bgp replay task");
1678             if (lastReplayJobFt != null) {
1679                 lastReplayJobFt.cancel(true);
1680                 lastReplayJobFt = null;
1681                 staledFibEntriesMap.clear();
1682             }
1683             if (routeCleanupFuture != null) {
1684                 routeCleanupFuture.cancel(true);
1685                 routeCleanupFuture = null;
1686                 staledFibEntriesMap.clear();
1687             }
1688             Thread.sleep(2000);
1689         } catch (InterruptedException e) {
1690             LOG.error("Failed to cancel previous replay job ", e);
1691         }
1692     }
1693
1694     private void doRouteSync() {
1695         LOG.error("Starting BGP route sync");
1696         try {
1697             bgpRouter.initRibSync(bgpSyncHandle);
1698         } catch (BgpRouterException e) {
1699             LOG.error("Route sync aborted, exception when initializing", e);
1700             return;
1701         }
1702         while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
1703             for (af_afi afi : af_afi.values()) {
1704                 Routes routes = null;
1705                 try {
1706                     routes = bgpRouter.doRibSync(bgpSyncHandle, afi);
1707                 } catch (TException | BgpRouterException e) {
1708                     LOG.error("Route sync aborted, exception when syncing", e);
1709                     return;
1710                 }
1711                 Iterator<Update> updates = routes.getUpdatesIterator();
1712                 while (updates.hasNext()) {
1713                     Update update = updates.next();
1714                     String rd = update.getRd();
1715                     String nexthop = update.getNexthop();
1716
1717                     // TODO: decide correct label here
1718                     int label = update.getL3label();
1719                     int l2label = update.getL2label();
1720
1721                     String prefix = update.getPrefix();
1722                     int plen = update.getPrefixlen();
1723
1724
1725                     // TODO: protocol type will not be available in "update"
1726                     // use "rd" to query vrf table and obtain the protocol_type.
1727                     // Currently using PROTOCOL_EVPN as default.
1728                     onUpdatePushRoute(
1729                            protocol_type.PROTOCOL_EVPN,
1730                            rd,
1731                            prefix,
1732                            plen,
1733                            nexthop,
1734                            update.getEthtag(),
1735                            update.getEsi(),
1736                            update.getMacaddress(),
1737                            label,
1738                            l2label,
1739                            update.getRoutermac(),
1740                            afi);
1741                 }
1742             }
1743         }
1744         try {
1745             LOG.error("Ending BGP route-sync");
1746             bgpRouter.endRibSync(bgpSyncHandle);
1747         } catch (BgpRouterException e) {
1748             // Ignored?
1749         }
1750     }
1751
1752     public void addTepToElanDS(String rd, String tepIp, String mac, Long l2vni) {
1753         boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
1754         if (needUpdate) {
1755             LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
1756             bgpUtil.addTepToElanInstance(rd, tepIp);
1757         } else {
1758             LOG.debug("Skipping the Elan update for RT2 from tep {} rd {}", tepIp, rd);
1759         }
1760     }
1761
1762     public void deleteTepfromElanDS(String rd, String tepIp, String mac) {
1763         boolean needUpdate = deleteFromRt2TepMap(rd, tepIp, mac);
1764         if (needUpdate) {
1765             LOG.info("Deleting tepIp {} with RD {} to ELan DS", tepIp, rd);
1766             bgpUtil.deleteTepFromElanInstance(rd, tepIp);
1767         } else {
1768             LOG.debug("Skipping the Elan update for RT2 withdraw from tep {} rd {}", tepIp, rd);
1769         }
1770     }
1771
1772     /* onUpdatePushRoute
1773      * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1774      *  - Entry compare shall include NextHop, Label.
1775      *  - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1776      *  - If entry not found, add to FIB Config DS.
1777      *  - If entry found, but either Label/NextHop doesn't match.
1778      *      - Update FIB Config DS with modified values.
1779      *      - delete from Stale Map.
1780      */
1781
1782     public void onUpdatePushRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1783             int ethtag, String esi, String macaddress, int label, int l2label, String routermac, af_afi afi) {
1784         boolean addroute = false;
1785         boolean macupdate = false;
1786         long l3vni = 0L;
1787         VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1788         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1789             encapType = VrfEntry.EncapType.Vxlan;
1790             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1791             if (vpnInstanceOpDataEntry != null) {
1792                 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1793                     LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
1794                             vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
1795                     addTepToElanDS(rd, nextHop, macaddress, (long)l2label);
1796                     macupdate = true;
1797                 } else {
1798                     l3vni = vpnInstanceOpDataEntry.getL3vni();
1799                 }
1800             } else {
1801                 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1802                 return;
1803             }
1804         }
1805
1806         if (!staledFibEntriesMap.isEmpty()) {
1807             // restart Scenario, as MAP is not empty.
1808             Map<String, Long> map = staledFibEntriesMap.get(rd);
1809             if (map != null) {
1810                 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1811                 Long labelInStaleMap = map.get(prefixNextHop);
1812                 if (null == labelInStaleMap) {
1813                     // New Entry, which happened to be added during restart.
1814                     addroute = true;
1815                 } else {
1816                     map.remove(prefixNextHop);
1817                     if (isRouteModified(label, labelInStaleMap)) {
1818                         LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1819                         // Existing entry, where in Label got modified during restart
1820                         addroute = true;
1821                     }
1822                 }
1823             } else {
1824                 LOG.debug("rd {} map is null while processing prefix {} ", rd, prefix);
1825                 addroute = true;
1826             }
1827         } else {
1828             LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1829             addroute = true;
1830         }
1831         if (macupdate) {
1832             LOG.info("ADD: Adding Mac Fib entry rd {} mac{} nexthop {} l2vni {}", rd, macaddress, nextHop, l2label);
1833             fibDSWriter.addMacEntryToDS(rd, macaddress, prefix, Collections.singletonList(nextHop),
1834                     encapType, l2label, routermac, RouteOrigin.BGP);
1835             LOG.info("ADD: Added Mac Fib entry rd {} prefix {} nexthop {} label {}", rd, macaddress, nextHop, l2label);
1836         } else if (addroute) {
1837             LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
1838                     rd, prefix, nextHop, label, afi);
1839             // TODO: modify addFibEntryToDS signature
1840             List<String> nextHopList = Collections.singletonList(nextHop);
1841             fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
1842                                         routermac, RouteOrigin.BGP);
1843             LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1844             String vpnName = bgpUtil.getVpnNameFromRd(rd);
1845             if (vpnName != null) {
1846                 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, nextHopList, label, RouteOrigin.BGP,
1847                                                  NwConstants.ADD_FLOW);
1848             }
1849         }
1850     }
1851
1852     public void onUpdateWithdrawRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1853             String macaddress) {
1854         long vni = 0L;
1855         boolean macupdate = false;
1856         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1857             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1858             if (vpnInstanceOpDataEntry != null) {
1859                 vni = vpnInstanceOpDataEntry.getL3vni();
1860                 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1861                     LOG.debug("Got RT2 withdraw for RD %s from tep %s with mac %s remote RD %s",
1862                             vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
1863                     deleteTepfromElanDS(rd, nextHop, macaddress);
1864                     LOG.debug("For rd %s. skipping fib update", rd);
1865                     macupdate = true;
1866                 }
1867             } else {
1868                 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1869                 return;
1870             }
1871         }
1872         if (macupdate) {
1873             LOG.info("Removing Mac Fib entry rd {} mac{} nexthop {} ", rd, macaddress, nextHop);
1874             fibDSWriter.removeMacEntryFromDS(rd, macaddress);
1875             LOG.info("Removed Mac Fib entry rd {} prefix {} nexthop {} ", rd, macaddress, nextHop);
1876         } else {
1877             LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
1878             fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nextHop);
1879             LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
1880         }
1881     }
1882
1883     //TODO: below function is for testing purpose with cli
1884     public void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
1885         LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
1886         fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
1887         String vpnName = bgpUtil.getVpnNameFromRd(rd);
1888         if (vpnName != null) {
1889             vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
1890                                              RouteOrigin.BGP, NwConstants.DEL_FLOW);
1891         }
1892     }
1893
1894     private static boolean isRouteModified(int label, Long labelInStaleMap) {
1895         return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
1896     }
1897
1898     static class ReplayNbr {
1899         Neighbors nbr;
1900         boolean shouldRetry = false;
1901
1902         public Neighbors getNbr() {
1903             return nbr;
1904         }
1905
1906         public boolean isShouldRetry() {
1907             return shouldRetry;
1908         }
1909
1910         public void setShouldRetry(boolean retryNbr) {
1911             this.shouldRetry = retryNbr;
1912         }
1913
1914         ReplayNbr(Neighbors nbr, boolean shouldRetry) {
1915             this.nbr = nbr;
1916             this.shouldRetry = shouldRetry;
1917         }
1918     }
1919
1920     private static boolean replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1921         if (neighbors == null || neighbors.isEmpty()) {
1922             LOG.error("Replaying nbr configuration, received NULL list ");
1923             return true;
1924         }
1925
1926         List<ReplayNbr> replayNbrList = new ArrayList<>();
1927         for (Neighbors nbr : neighbors) {
1928             if (nbr != null) {
1929                 replayNbrList.add(new ReplayNbr(nbr, true));
1930             }
1931         }
1932         final int numberOfNbrRetries = 3;
1933         RetryOnException nbrRetry = new RetryOnException(numberOfNbrRetries);
1934         do {
1935             for (ReplayNbr replayNbr : replayNbrList) {
1936                 if (!replayNbr.isShouldRetry()) {
1937                     continue;
1938                 }
1939                 boolean replayDone = false;
1940                 LOG.debug("Replaying addNbr {}", replayNbr.getNbr().getAddress().getValue());
1941                 replayDone = false;
1942                 try {
1943                     final String md5password = extractMd5Secret(replayNbr.getNbr());
1944                     br.addNeighbor(replayNbr.getNbr().getAddress().getValue(),
1945                             replayNbr.getNbr().getRemoteAs().longValue(), md5password);
1946                     UpdateSource us = replayNbr.getNbr().getUpdateSource();
1947                     if (us != null) {
1948                         LOG.debug("Replaying updatesource along with nbr: {} US-ip: {} to peer {}",
1949                                 replayNbr.getNbr().getAddress().getValue(),
1950                                 us.getSourceIp().getValue(),
1951                                 us.getPeerIp().getValue());
1952                         br.addUpdateSource(us.getPeerIp().getValue(),
1953                                 us.getSourceIp().getValue());
1954                     }
1955                     replayDone = true;
1956                 } catch (TException | BgpRouterException eNbr) {
1957                     LOG.debug("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), eNbr);
1958                 }
1959                 boolean replaySuccess = true;
1960                 replaySuccess = replaySuccess && replayDone;
1961                 LOG.debug("Replay addNbr {} successful", replayNbr.getNbr().getAddress().getValue());
1962
1963                 //Update Source handling
1964                 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1965                 if (replayDone == false && us != null) {
1966                     LOG.debug("Replaying updatesource {} to peer {}", us.getSourceIp().getValue(),
1967                             us.getPeerIp().getValue());
1968                     replayDone = false;
1969                     try {
1970                         br.addUpdateSource(us.getPeerIp().getValue(),
1971                                 us.getSourceIp().getValue());
1972                         replayDone = true;
1973                     } catch (TException | BgpRouterException eUs) {
1974                         LOG.debug("Replaying UpdateSource for Nbr {}, exception:",
1975                                 replayNbr.getNbr().getAddress().getValue(), eUs);
1976                     }
1977                     LOG.debug("Replay updatesource {} successful", us.getSourceIp().getValue());
1978                     replaySuccess = replaySuccess && replayDone;
1979                 }
1980                 //Ebgp Multihope
1981                 EbgpMultihop en = replayNbr.getNbr().getEbgpMultihop();
1982                 if (en != null) {
1983                     replayDone = false;
1984                     try {
1985                         br.addEbgpMultihop(en.getPeerIp().getValue(),
1986                                 en.getNhops().intValue());
1987                         replayDone = true;
1988                     } catch (TException | BgpRouterException eEbgpMhop) {
1989                         LOG.debug("Replaying EbgpMultihop for Nbr {}, exception: ",
1990                                 replayNbr.getNbr().getAddress().getValue(), eEbgpMhop);
1991                     }
1992                     replaySuccess = replaySuccess && replayDone;
1993                 }
1994
1995                 //afs
1996                 List<AddressFamilies> afs = replayNbr.getNbr().getAddressFamilies();
1997                 if (afs != null) {
1998                     for (AddressFamilies af : afs) {
1999                         af_afi afi = af_afi.findByValue(af.getAfi().intValue());
2000                         af_safi safi = af_safi.findByValue(af.getSafi().intValue());
2001                         replayDone = false;
2002                         try {
2003                             br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
2004                             replayDone = true;
2005                         } catch (TException | BgpRouterException eAFs) {
2006                             LOG.debug("Replaying AddressFamily for Nbr {}, exception:",
2007                                     replayNbr.getNbr().getAddress().getValue(), eAFs);
2008                         }
2009                         replaySuccess = replaySuccess && replayDone;
2010                     }
2011                 }
2012                 //replay is success --> no need to replay this nbr in next iteration.
2013                 replayNbr.setShouldRetry(replaySuccess ? false : true);
2014             }
2015         } while (nbrRetry.decrementAndRetry());
2016         boolean replaySuccess = true;
2017         for (ReplayNbr replayNbr : replayNbrList) {
2018             replaySuccess = replaySuccess && !replayNbr.isShouldRetry();
2019         }
2020         return replaySuccess;
2021     }
2022
2023     public String getConfigHost() {
2024         if (config == null) {
2025             return hostStartup;
2026         }
2027         ConfigServer ts = config.getConfigServer();
2028         return ts == null ? hostStartup : ts.getHost().getValue();
2029     }
2030
2031     public int getConfigPort() {
2032         if (config == null) {
2033             return Integer.parseInt(portStartup);
2034         }
2035         ConfigServer ts = config.getConfigServer();
2036         return ts == null ? Integer.parseInt(portStartup) :
2037                 ts.getPort().intValue();
2038     }
2039
2040     public Bgp getConfig() {
2041         AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COUNT);
2042         while (0 != bgpDSretryCount.decrementAndGet()) {
2043             try {
2044                 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
2045                         InstanceIdentifier.create(Bgp.class)).orNull();
2046             } catch (ReadFailedException e) {
2047                 //Config DS may not be up, so sleep for 1 second and retry
2048                 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
2049                 try {
2050                     Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
2051                 } catch (InterruptedException timerEx) {
2052                     LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
2053                             + "config DS availability", timerEx);
2054                 }
2055             }
2056         }
2057         LOG.error("failed to get bgp config");
2058         return null;
2059     }
2060
2061     @SuppressWarnings("checkstyle:IllegalCatch")
2062     public synchronized boolean replay() throws InterruptedException, TimeoutException, ExecutionException {
2063         boolean replaySucceded = true;
2064         String host = getConfigHost();
2065         int port = getConfigPort();
2066         LOG.error("connecting  to bgp host {} ", host);
2067         boolean res = bgpRouter.connect(host, port);
2068         if (!res) {
2069             String msg = "Cannot connect to BGP config server at " + host + ":" + port;
2070             if (config != null) {
2071                 msg += "; Configuration Replay aborted";
2072             }
2073             LOG.error(msg);
2074             return replaySucceded;
2075         }
2076         config = getConfig();
2077         if (config == null) {
2078             LOG.error("bgp config is empty nothing to push to bgp");
2079             return replaySucceded;
2080         }
2081         BgpRouter br = bgpRouter;
2082         AsId asId = config.getAsId();
2083         if (asId == null) {
2084             LOG.error("bgp as-id is null");
2085             return replaySucceded;
2086         }
2087         long asNum = asId.getLocalAs();
2088         IpAddress routerId = asId.getRouterId();
2089         String rid = routerId == null ? "" : new String(routerId.getValue());
2090         int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, config.getAsId());
2091         boolean announceFbit = true;
2092         boolean replayDone = false;
2093         final int numberOfStartBgpRetries = 3;
2094         RetryOnException startBgpRetry = new RetryOnException(numberOfStartBgpRetries);
2095         do {
2096             try {
2097                 LOG.debug("Replaying BGPConfig ");
2098                 br.startBgp(asNum, rid, stalepathTime, announceFbit);
2099                 LOG.debug("Replay BGPConfig successful");
2100                 replayDone = true;
2101                 break;
2102             } catch (BgpRouterException bre) {
2103                 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
2104                     LOG.debug("Starting the routesync for exception", bre);
2105                     startBgpRetry.errorOccured();
2106                     if (!startBgpRetry.shouldRetry()) {
2107                         LOG.debug("starting route sync for BgpRouter exception");
2108                         doRouteSync();
2109                     }
2110                 } else {
2111                     LOG.error("Replay: startBgp() received exception error {} : ",
2112                             bre.getErrorCode(), bre);
2113                     startBgpRetry.errorOccured();
2114                 }
2115             } catch (TApplicationException tae) {
2116                 if (tae.getType() == BgpRouterException.BGP_ERR_ACTIVE) {
2117                     LOG.debug("Starting the routesync for exception", tae);
2118                     startBgpRetry.errorOccured();
2119                     if (!startBgpRetry.shouldRetry()) {
2120                         LOG.debug("starting route sync for Thrift BGP_ERR_ACTIVE exception");
2121                         doRouteSync();
2122                     }
2123                 } else if (tae.getType() == BgpRouterException.BGP_ERR_COMMON_FAILURE) {
2124                     LOG.debug("Starting the routesync for AS-ID started exception", tae);
2125                     startBgpRetry.errorOccured();
2126                     if (!startBgpRetry.shouldRetry()) {
2127                         LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception");
2128                         doRouteSync();
2129                     }
2130                 } else {
2131                     LOG.error("Replay: startBgp() received exception type {}: ",
2132                             tae.getType(), tae);
2133                     startBgpRetry.errorOccured();
2134                 }
2135             } catch (Exception e) {
2136                 //not unusual. We may have restarted & BGP is already on
2137                 LOG.error("Replay:startBgp() received exception: ", e);
2138                 startBgpRetry.errorOccured();
2139             }
2140         } while (startBgpRetry.shouldRetry());
2141
2142         replaySucceded = replayDone;
2143
2144         startBgpCountersTask();
2145         startBgpAlarmsTask();
2146
2147         /*
2148          * commenting this due to a bug with QBGP. Will uncomment once QBGP fix is done.
2149          * This wont have any functional impacts
2150          */
2151         //try {
2152         //    br.delayEOR(delayEorSeconds);
2153         //} catch (TException | BgpRouterException e) {
2154         //    LOG.error("Replay: delayEOR() number of seconds to wait for EOR from ODL:", e);
2155         //}
2156
2157         List<Neighbors> neighbors = config.getNeighbors();
2158         if (neighbors != null) {
2159             LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
2160             boolean neighborConfigReplayResult = replayNbrConfig(neighbors, br);
2161             if (neighborConfigReplayResult == false) {
2162                 replaySucceded = false;
2163             }
2164         } else {
2165             LOG.error("no Neighbors present for replay config ");
2166         }
2167
2168         Logging logging = config.getLogging();
2169         if (logging != null) {
2170             try {
2171                 br.setLogging(logging.getFile(), logging.getLevel());
2172             } catch (TException | BgpRouterException e) {
2173                 LOG.error("Replay:setLogging() received exception", e);
2174             }
2175         }
2176
2177         GracefulRestart gracefulRestart = config.getGracefulRestart();
2178         if (gracefulRestart != null) {
2179             try {
2180                 br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
2181             } catch (TException | BgpRouterException e) {
2182                 LOG.error("Replay:addGr() received exception", e);
2183             }
2184         }
2185
2186         List<Vrfs> vrfs = config.getVrfs();
2187         if (vrfs == null) {
2188             vrfs = new ArrayList<>();
2189         }
2190         for (Vrfs vrf : vrfs) {
2191             for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf()) {
2192                 try {
2193                     br.addVrf(BgpUtil.getLayerType(adf), vrf.getRd(), vrf.getImportRts(),
2194                             vrf.getExportRts(), adf.getAfi(), adf.getSafi());
2195                 } catch (TException | BgpRouterException e) {
2196                     LOG.error("Replay:addVrf() received exception", e);
2197                 }
2198             }
2199         }
2200
2201         List<Networks> ln = config.getNetworks();
2202         if (ln != null) {
2203             for (Networks net : ln) {
2204                 String rd = net.getRd();
2205                 String pfxlen = net.getPrefixLen();
2206                 String nh = net.getNexthop().getValue();
2207                 Long label = net.getLabel();
2208                 int lbl = label == null ? 0 : label.intValue();
2209                 int l3vni = net.getL3vni() == null ? 0 : net.getL3vni().intValue();
2210                 int l2vni = net.getL2vni() == null ? 0 : net.getL2vni().intValue();
2211                 if (rd == null && lbl > 0) {
2212                     //LU prefix is being deleted.
2213                     rd = Integer.toString(lbl);
2214                 }
2215
2216                 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
2217                 int ethernetTag = net.getEthtag().intValue();
2218                 String esi = net.getEsi();
2219                 String macaddress = net.getMacaddress();
2220                 EncapType encapType = net.getEncapType();
2221                 String routerMac = net.getRoutermac();
2222
2223                 try {
2224                     br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni,
2225                             BgpUtil.convertToThriftProtocolType(protocolType),
2226                             ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
2227                 } catch (TException | BgpRouterException e) {
2228                     LOG.error("Replay:addPfx() received exception", e);
2229                 }
2230             }
2231         }
2232
2233
2234         List<Multipath> multipaths = config.getMultipath();
2235
2236         if (multipaths != null) {
2237             for (Multipath multipath : multipaths) {
2238                 if (multipath != null) {
2239                     af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
2240                     af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
2241
2242                     try {
2243                         if (multipath.isMultipathEnabled()) {
2244                             br.enableMultipath(afi, safi);
2245                         } else {
2246                             br.disableMultipath(afi, safi);
2247                         }
2248                     } catch (TException | BgpRouterException e) {
2249                         LOG.info("Replay:multipaths() received exception: \"" + e + "\"");
2250                     }
2251                 }
2252             }
2253         }
2254         List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
2255         if (vrfMaxpaths != null) {
2256             for (VrfMaxpath vrfMaxpath : vrfMaxpaths) {
2257                 try {
2258                     br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
2259                 } catch (TException | BgpRouterException e) {
2260                     LOG.info("Replay:vrfMaxPath() received exception: \"" + e + "\"");
2261                 }
2262             }
2263         }
2264
2265         //send End of Rib Marker to Qthriftd.
2266         final int numberOfEORRetries = 3;
2267         replayDone = false;
2268         RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
2269         do {
2270             try {
2271                 br.sendEOR();
2272                 LOG.debug("Replay sendEOR {} successful");
2273                 replayDone = true;
2274                 break;
2275             } catch (Exception e) {
2276                 eorRetry.errorOccured();
2277                 LOG.error("Replay:sedEOR() received exception:", e);
2278             }
2279         } while (eorRetry.shouldRetry());
2280
2281         return replaySucceded && replayDone;
2282     }
2283
2284     private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
2285         bgpUtil.update(LogicalDatastoreType.CONFIGURATION, iid, dto);
2286     }
2287
2288     private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
2289         bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, iid);
2290     }
2291
2292     public void startConfig(String bgpHost, int thriftPort) {
2293         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2294                 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2295         InstanceIdentifier<ConfigServer> iid = iib.build();
2296         Ipv4Address ipAddr = new Ipv4Address(bgpHost);
2297         ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
2298                 .setPort((long) thriftPort).build();
2299         update(iid, dto);
2300     }
2301
2302     public void startBgp(long as, String routerId, int spt, boolean fbit) {
2303         IpAddress rid = routerId == null ? null : new IpAddress(routerId.toCharArray());
2304         Long staleTime = (long) spt;
2305         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2306                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2307         InstanceIdentifier<AsId> iid = iib.build();
2308         AsId dto = new AsIdBuilder().setLocalAs(as)
2309                 .setRouterId(rid)
2310                 .setStalepathTime(staleTime)
2311                 .setAnnounceFbit(fbit).build();
2312         update(iid, dto);
2313     }
2314
2315     public void addLogging(String fileName, String logLevel) {
2316         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2317                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2318         InstanceIdentifier<Logging> iid = iib.build();
2319         Logging dto = new LoggingBuilder().setFile(fileName)
2320                 .setLevel(logLevel).build();
2321         update(iid, dto);
2322     }
2323
2324     public void addGracefulRestart(int staleTime) {
2325         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2326                 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2327         InstanceIdentifier<GracefulRestart> iid = iib.build();
2328         GracefulRestart dto = new GracefulRestartBuilder()
2329                 .setStalepathTime((long) staleTime).build();
2330         update(iid, dto);
2331     }
2332
2333     public void addNeighbor(
2334             String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2335         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2336         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2337                 InstanceIdentifier.builder(Bgp.class)
2338                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
2339         InstanceIdentifier<Neighbors> iid = iib.build();
2340         TcpSecurityOption tcpSecOption = null;
2341         if (md5Secret != null) {
2342             tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2343         } // else let tcpSecOption be null
2344         Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2345                 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2346         update(iid, dto);
2347     } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2348
2349     public void addUpdateSource(String nbrIp, String srcIp) {
2350         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2351         Ipv4Address srcAddr = new Ipv4Address(srcIp);
2352         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2353                 InstanceIdentifier.builder(Bgp.class)
2354                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2355                         .child(UpdateSource.class);
2356         InstanceIdentifier<UpdateSource> iid = iib.build();
2357         UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2358                 .setSourceIp(srcAddr).build();
2359         update(iid, dto);
2360     }
2361
2362     public void addEbgpMultihop(String nbrIp, int hops) {
2363         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2364         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2365                 InstanceIdentifier.builder(Bgp.class)
2366                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2367                         .child(EbgpMultihop.class);
2368         InstanceIdentifier<EbgpMultihop> iid = iib.build();
2369         EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2370                 .setNhops((long) hops).build();
2371         update(iid, dto);
2372     }
2373
2374     public void addAddressFamily(String nbrIp, int afi, int safi) {
2375         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2376         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2377                 InstanceIdentifier.builder(Bgp.class)
2378                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2379                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2380         InstanceIdentifier<AddressFamilies> iid = iib.build();
2381         AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2382                 .setAfi((long) afi).setSafi((long) safi).build();
2383         update(iid, dto);
2384     }
2385
2386     public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2387               VrfEntry.EncapType encapType, long lbl, long l3vni, long l2vni, String gatewayMac) {
2388         for (String nh : nhList) {
2389             Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2390             Long label = lbl;
2391             InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2392                     .child(Networks.class, new NetworksKey(pfx, rd)).build();
2393             NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2394                                                 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
2395             buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, l2vni, macAddress, gatewayMac);
2396             update(iid, networksBuilder.build());
2397         }
2398     }
2399
2400     private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
2401                                                   long l3vni, long l2vni, String macAddress, String gatewayMac) {
2402         if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2403             builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2404                     .setEncapType(EncapType.GRE);
2405         } else {
2406             builder.setL3vni(l3vni).setL2vni(l2vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2407                     .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2408         }
2409     }
2410
2411     // TODO: add LayerType as arg - supports command
2412     public void addVrf(String rd, List<String> irts, List<String> erts, AddressFamily addressFamily) {
2413         Vrfs vrf = bgpUtil.getVrfFromRd(rd);
2414         List<AddressFamiliesVrf> adfList = new ArrayList<>(1);
2415         if (vrf != null) {
2416             adfList = vrf.getAddressFamiliesVrf();
2417         }
2418         AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2419         if (addressFamily.equals(AddressFamily.IPV4)) {
2420             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2421             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2422         } else if (addressFamily.equals(AddressFamily.IPV6)) {
2423             adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2424             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2425         } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2426             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2427             adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2428         }
2429         AddressFamiliesVrf adf = adfBuilder.build();
2430         adfList.add(adf);
2431         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = InstanceIdentifier.builder(Bgp.class)
2432                 .child(Vrfs.class, new VrfsKey(rd));
2433         InstanceIdentifier<Vrfs> iid = iib.build();
2434         Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2435             .setExportRts(erts).setAddressFamiliesVrf(adfList).build();
2436
2437         List<AddressFamiliesVrf> listAdFamilies = mapNewAdFamily.get(rd);
2438         if (listAdFamilies != null) {
2439             listAdFamilies.add(adf);
2440         } else {
2441             mapNewAdFamily.put(rd, adfList);
2442         }
2443
2444         try {
2445             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2446         } catch (TransactionCommitFailedException e) {
2447             LOG.error("Error adding VRF to datastore", e);
2448             throw new RuntimeException(e);
2449         }
2450     }
2451
2452     public void stopConfig() {
2453         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2454                 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2455         InstanceIdentifier<ConfigServer> iid = iib.build();
2456         delete(iid);
2457     }
2458
2459     public void stopBgp() {
2460         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2461                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2462         InstanceIdentifier<AsId> iid = iib.build();
2463         delete(iid);
2464     }
2465
2466     public void delLogging() {
2467         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2468                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2469         InstanceIdentifier<Logging> iid = iib.build();
2470         delete(iid);
2471     }
2472
2473     public void delGracefulRestart() {
2474         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2475                 InstanceIdentifier.builder(Bgp.class)
2476                         .child(GracefulRestart.class);
2477         InstanceIdentifier<GracefulRestart> iid = iib.build();
2478         delete(iid);
2479     }
2480
2481     public void delNeighbor(String nbrIp) {
2482         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2483         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2484                 InstanceIdentifier.builder(Bgp.class)
2485                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
2486         InstanceIdentifier<Neighbors> iid = iib.build();
2487         delete(iid);
2488     }
2489
2490     public void delUpdateSource(String nbrIp) {
2491         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2492         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2493                 InstanceIdentifier.builder(Bgp.class)
2494                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2495                         .child(UpdateSource.class);
2496         InstanceIdentifier<UpdateSource> iid = iib.build();
2497         delete(iid);
2498     }
2499
2500     public void delEbgpMultihop(String nbrIp) {
2501         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2502         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2503                 InstanceIdentifier.builder(Bgp.class)
2504                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2505                         .child(EbgpMultihop.class);
2506         InstanceIdentifier<EbgpMultihop> iid = iib.build();
2507         delete(iid);
2508     }
2509
2510     public void delAddressFamily(String nbrIp, int afi, int safi) {
2511         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2512         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2513                 InstanceIdentifier.builder(Bgp.class)
2514                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2515                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2516         InstanceIdentifier<AddressFamilies> iid = iib.build();
2517         delete(iid);
2518     }
2519
2520     public void delPrefix(String rd, String pfx) {
2521         InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2522                 InstanceIdentifier.builder(Bgp.class)
2523                         .child(Networks.class, new NetworksKey(pfx, rd));
2524         InstanceIdentifier<Networks> iid = iib.build();
2525         delete(iid);
2526     }
2527
2528     public boolean delVrf(String rd, AddressFamily addressFamily) {
2529         if (addressFamily == null) {
2530             LOG.error("delVrf: vrf {}, addressFamily invalid", rd);
2531             return false;
2532         }
2533         AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2534         if (addressFamily.equals(AddressFamily.IPV4)) {
2535             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2536             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2537         } else if (addressFamily.equals(AddressFamily.IPV6)) {
2538             adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2539             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2540         } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2541             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2542             adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2543         }
2544         Vrfs vrfOriginal = bgpUtil.getVrfFromRd(rd);
2545         if (vrfOriginal == null) {
2546             LOG.error("delVrf: no vrf with existing rd {}. step aborted", rd);
2547             return false;
2548         }
2549
2550         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2551                 InstanceIdentifier.builder(Bgp.class)
2552                         .child(Vrfs.class, new VrfsKey(rd));
2553
2554         InstanceIdentifier<Vrfs> iid = iib.build();
2555
2556         @SuppressWarnings("static-access")
2557         InstanceIdentifier<Bgp> iid6 =  iid.builder(Bgp.class).build()
2558                 .child(Multipath.class, new MultipathKey(adfBuilder.getAfi(), adfBuilder.getSafi())).create(Bgp.class);
2559         InstanceIdentifierBuilder<Vrfs> iib3 = iid6.child(Vrfs.class, new VrfsKey(rd)).builder();
2560         InstanceIdentifier<Vrfs> iidFinal = iib3.build();
2561
2562         //** update or delete the vrfs with the rest of AddressFamilies already present in the last list
2563         AddressFamiliesVrf adfToDel = adfBuilder.build();
2564         List<AddressFamiliesVrf> adfListOriginal = vrfOriginal.getAddressFamiliesVrf() == null
2565                 ? new ArrayList<>() : vrfOriginal.getAddressFamiliesVrf();
2566         List<AddressFamiliesVrf> adfListToRemoveFromOriginal = new ArrayList<>();
2567         adfListOriginal.forEach(adf -> {
2568             if (adf.equals(adfToDel)) {
2569                 adfListToRemoveFromOriginal.add(adfToDel);
2570                 return;
2571             }
2572         });
2573         for (AddressFamiliesVrf adfToRemove : adfListToRemoveFromOriginal) {
2574             adfListOriginal.remove(adfToRemove);
2575             try {
2576                 SingleTransactionDataBroker.syncWrite(dataBroker,
2577                         LogicalDatastoreType.CONFIGURATION, iid, vrfOriginal);
2578             } catch (TransactionCommitFailedException e) {
2579                 LOG.error("delVrf: Error updating VRF to datastore", e);
2580                 throw new RuntimeException(e);
2581             }
2582         }
2583         if (adfListOriginal.isEmpty()) {
2584             delete(iidFinal);
2585             return true;
2586         }
2587         // not all is removed
2588         return false;
2589     }
2590
2591     public void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2592         long lafi = afi.getValue();
2593         long lsafi = safi.getValue();
2594
2595         InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2596                 InstanceIdentifier
2597                         .builder(Bgp.class)
2598                         .child(Multipath.class,
2599                                 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2600
2601         Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2602         update(iib.build(), dto);
2603     }
2604
2605     public void multipaths(String rd, int maxpath) {
2606         InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2607                 InstanceIdentifier
2608                         .builder(Bgp.class)
2609                         .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2610
2611         VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2612         update(iib.build(), dto);
2613     }
2614
2615     /*
2616     * Remove Stale Marked Routes after timer expiry.
2617     */
2618     private class RouteCleanup implements Callable<Integer> {
2619
2620         @Override
2621         public Integer call() {
2622             totalCleared = 0;
2623             try {
2624                 if (staledFibEntriesMap.isEmpty()) {
2625                     LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2626                 } else {
2627                     for (String rd : staledFibEntriesMap.keySet()) {
2628                         if (Thread.interrupted()) {
2629                             return 0;
2630                         }
2631                         Map<String, Long> map = staledFibEntriesMap.get(rd);
2632                         if (map != null) {
2633                             for (String key : map.keySet()) {
2634                                 if (Thread.interrupted()) {
2635                                     return 0;
2636                                 }
2637                                 String prefix = extractPrefix(key);
2638                                 String nextHop = extractNextHop(key);
2639                                 totalCleared++;
2640                                 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
2641                                         rd, prefix, nextHop);
2642                                 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
2643                             }
2644                         }
2645                     }
2646                 }
2647             } finally {
2648                 staledFibEntriesMap.clear();
2649             }
2650             LOG.error("cleared {} stale routes after bgp restart", totalCleared);
2651             return 0;
2652         }
2653     }
2654
2655     /*
2656      * BGP restart scenario, ODL-BGP manager was/is running.
2657      * On re-sync notification, Get a copy of FIB database.
2658      */
2659     public void createStaleFibMap() {
2660         totalStaledCount = 0;
2661         try {
2662             staledFibEntriesMap.clear();
2663             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2664
2665             Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2666                     LogicalDatastoreType.CONFIGURATION, id);
2667             if (fibEntries.isPresent()) {
2668                 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2669                 for (VrfTables vrfTable : staleVrfTables) {
2670                     Map<String, Long> staleFibEntMap = new HashMap<>();
2671                     for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2672                         if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2673                             //Stale marking and cleanup is only meant for the routes learned through BGP.
2674                             continue;
2675                         }
2676                         if (Thread.interrupted()) {
2677                             break;
2678                         }
2679                         totalStaledCount++;
2680                         //Create MAP from staleVrfTables.
2681                         vrfEntry.getRoutePaths()
2682                                 .forEach(
2683                                     routePath -> staleFibEntMap.put(
2684                                             appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2685                                                     routePath.getNexthopAddress()), routePath.getLabel()));
2686                     }
2687                     staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2688                 }
2689             } else {
2690                 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2691             }
2692         } catch (ReadFailedException e) {
2693             LOG.error("createStaleFibMap:: error ", e);
2694         }
2695         LOG.error("created {} staled entries ", totalStaledCount);
2696     }
2697
2698     /*
2699      * BGP config remove scenario, Need to remove all the
2700      * external routes from FIB.
2701      */
2702     public void deleteExternalFibRoutes() {
2703         totalExternalRoutes = 0;
2704         totalExternalMacRoutes = 0;
2705         try {
2706             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2707
2708             Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2709                     LogicalDatastoreType.CONFIGURATION, id);
2710             if (fibEntries.isPresent()) {
2711                 if (fibEntries.get().getVrfTables() == null) {
2712                     LOG.error("deleteExternalFibRoutes::getVrfTables is null");
2713                     return;
2714                 }
2715                 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2716                 for (VrfTables vrfTable : staleVrfTables) {
2717                     String rd = vrfTable.getRouteDistinguisher();
2718                     if (vrfTable.getVrfEntry() != null) {
2719                         for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2720                             if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2721                                 //route cleanup is only meant for the routes learned through BGP.
2722                                 continue;
2723                             }
2724                             totalExternalRoutes++;
2725                             fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
2726                         }
2727                     } else if (vrfTable.getMacVrfEntry() != null) {
2728                         for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
2729                             if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
2730                                 //route cleanup is only meant for the routes learned through BGP.
2731                                 continue;
2732                             }
2733                             totalExternalMacRoutes++;
2734                             fibDSWriter.removeMacEntryFromDS(rd, macEntry.getMac());
2735                         }
2736                     }
2737                 }
2738             } else {
2739                 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
2740             }
2741         } catch (ReadFailedException e) {
2742             LOG.error("deleteExternalFibRoutes:: error ", e);
2743         }
2744         LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
2745     }
2746
2747     public boolean addToRt2TepMap(String rd, String tepIp, String mac, Long l2vni) {
2748         boolean isFirstMacUpdateFromTep = false;
2749         if (rt2TepMap.containsKey(rd)) {
2750             if (rt2TepMap.get(rd).containsKey(tepIp)) {
2751                 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and tep-ip {}. No Elan DS write required",
2752                         mac, l2vni, rd, tepIp);
2753                 rt2TepMap.get(rd).get(tepIp).put(mac, l2vni);
2754             } else {
2755                 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
2756                         mac, rd, tepIp);
2757                 isFirstMacUpdateFromTep = true;
2758                 Map<String, Long> macList = new HashMap<>();
2759                 macList.put(mac, l2vni);
2760                 rt2TepMap.get(rd).put(tepIp, macList);
2761             }
2762         } else {
2763             LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
2764                     mac, l2vni, rd, tepIp);
2765             isFirstMacUpdateFromTep = true;
2766             Map<String, Long> macList = new HashMap<>();
2767             macList.put(mac, l2vni);
2768             Map<String, Map<String, Long>> tepIpMacMap = new HashMap<>();
2769             tepIpMacMap.put(tepIp, macList);
2770             rt2TepMap.put(rd, tepIpMacMap);
2771         }
2772         return isFirstMacUpdateFromTep;
2773     }
2774
2775     public boolean deleteFromRt2TepMap(String rd, String tepIp, String mac) {
2776         boolean isLastMacUpdateFromTep = false;
2777         LOG.debug("RT2 withdraw with rd {} mac {} tep-ip {} ", rd, mac, tepIp);
2778         if (rt2TepMap.containsKey(rd)) {
2779             if (rt2TepMap.get(rd).containsKey(tepIp)) {
2780                 if (rt2TepMap.get(rd).get(tepIp).containsKey(mac)) {
2781                     LOG.debug("RT2 Withdraw : Removing the mac {} from Map", mac);
2782                     rt2TepMap.get(rd).get(tepIp).remove(mac);
2783                     if (rt2TepMap.get(rd).get(tepIp).isEmpty()) {
2784                         isLastMacUpdateFromTep = true;
2785                         LOG.debug("RT2 Withdraw : Removing the tep-ip {} from Map", tepIp);
2786                         rt2TepMap.get(rd).remove(tepIp);
2787                         if (rt2TepMap.get(rd).isEmpty()) {
2788                             LOG.debug("RT2 Withdraw : Removing the rd {} from Map", rd);
2789                             rt2TepMap.remove(rd);
2790                         }
2791                     }
2792                 }
2793             }
2794         }
2795         return isLastMacUpdateFromTep;
2796     }
2797
2798     public Collection<String> getTepIPs(String rd) {
2799         final Map<String, Map<String, Long>> tepIpMap = rt2TepMap.get(rd);
2800         return tepIpMap != null ? tepIpMap.keySet() : Collections.emptyList();
2801     }
2802
2803     public boolean isBgpConnected() {
2804         return bgpRouter.isBgpConnected();
2805     }
2806
2807     public long getLastConnectedTS() {
2808         return bgpRouter.getLastConnectedTS();
2809     }
2810
2811     public long getConnectTS() {
2812         return bgpRouter.getConnectTS();
2813     }
2814
2815     public long getStartTS() {
2816         return bgpRouter.getStartTS();
2817     }
2818
2819     public TTransport getTransport() {
2820         return bgpRouter.getTransport();
2821     }
2822
2823     public int getTotalStaledCount() {
2824         return totalStaledCount;
2825     }
2826
2827     public int getTotalCleared() {
2828         return totalCleared;
2829     }
2830
2831     public BgpCounters getBgpCounters() {
2832         return bgpCountersReference.get();
2833     }
2834
2835     private void startBgpCountersTask() {
2836         if (getBgpCounters() == null && bgpCountersReference.compareAndSet(null,
2837                 new BgpCounters(getBgpSdncMipIp(), metricProvider))) {
2838             bgpCountersTask = executor.scheduleAtFixedRate(bgpCountersReference.get(), 0, 120 * 1000,
2839                     TimeUnit.MILLISECONDS);
2840             LOG.info("Bgp Counters task scheduled for every two minutes.");
2841
2842             bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2843         }
2844     }
2845
2846     private void stopBgpCountersTask() {
2847         final BgpCounters bgpCounters = bgpCountersReference.getAndSet(null);
2848         if (bgpCounters != null) {
2849             bgpCountersTask.cancel(true);
2850             bgpCounters.close();
2851         }
2852     }
2853
2854     private void startBgpAlarmsTask() {
2855         if (getBgpAlarms() == null && bgpAlarmsReference.compareAndSet(null, new BgpAlarms(this))) {
2856             bgpAlarmsReference.get().init();
2857             bgpAlarmsTask = executor.scheduleAtFixedRate(bgpAlarmsReference.get(), 0, 60 * 1000, TimeUnit.MILLISECONDS);
2858             LOG.info("Bgp Alarms task scheduled for every minute.");
2859         }
2860     }
2861
2862     private void stopBgpAlarmsTask() {
2863         final BgpAlarms bgpAlarms = bgpAlarmsReference.getAndSet(null);
2864         if (bgpAlarms != null) {
2865             bgpAlarmsTask.cancel(true);
2866             bgpAlarms.close();
2867         }
2868     }
2869
2870     public BgpAlarms getBgpAlarms() {
2871         return bgpAlarmsReference.get();
2872     }
2873
2874     private static String appendNextHopToPrefix(String prefix, String nextHop) {
2875         return prefix + ":" + nextHop;
2876     }
2877
2878     private static String extractPrefix(String prefixNextHop) {
2879         return prefixNextHop.split(":")[0];
2880     }
2881
2882     private static String extractNextHop(String prefixNextHop) {
2883         return prefixNextHop.split(":")[1];
2884     }
2885
2886     private static String extractMd5Secret(final Neighbors val) {
2887         String md5Secret = null;
2888         TcpSecurityOption tcpSecOpt = val.getTcpSecurityOption();
2889         if (tcpSecOpt != null) {
2890             if (tcpSecOpt instanceof TcpMd5SignatureOption) {
2891                 md5Secret = ((TcpMd5SignatureOption) tcpSecOpt).getTcpMd5SignaturePassword().getValue();
2892             } else { // unknown TcpSecurityOption
2893                 LOG.debug("neighbors  Ignored unknown tcp-security-option of peer {}", val.getAddress().getValue());
2894             }
2895         }
2896         return md5Secret;
2897     } // private method extractMd5Secret
2898 }