Yang changes for Inter DC connectivity using BGPVPNv6
[netvirt.git] / vpnservice / bgpmanager / 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 io.netty.util.concurrent.GlobalEventExecutor;
12 import java.io.BufferedReader;
13 import java.io.File;
14 import java.io.FileNotFoundException;
15 import java.io.FileReader;
16 import java.io.IOException;
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.InvocationTargetException;
19 import java.net.InetAddress;
20 import java.net.NetworkInterface;
21 import java.net.SocketException;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Timer;
29 import java.util.TimerTask;
30 import java.util.concurrent.Callable;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.concurrent.CountDownLatch;
33 import java.util.concurrent.ExecutionException;
34 import java.util.concurrent.Executors;
35 import java.util.concurrent.Future;
36 import java.util.concurrent.ScheduledExecutorService;
37 import java.util.concurrent.TimeoutException;
38 import java.util.concurrent.atomic.AtomicBoolean;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import org.apache.thrift.TException;
41 import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
42 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
43 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
44 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
45 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
46 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
49 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
50 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
51 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
52 import org.opendaylight.genius.utils.batching.DefaultBatchHandler;
53 import org.opendaylight.genius.utils.clustering.EntityOwnerUtils;
54 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
55 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
56 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
57 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
58 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
59 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
60 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
61 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
62 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
63 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
64 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
65 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
66 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
67 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
68 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
69 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
70 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
71 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
72 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
73 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
74 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
75 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
76 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
77 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
78 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
79 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
80 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
81 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
82 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
83 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
84 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
85 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
86 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
87 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
88 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
89 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
90 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
91 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
98 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
99 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
104 import org.opendaylight.yangtools.concepts.ListenerRegistration;
105 import org.opendaylight.yangtools.yang.binding.DataObject;
106 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
107 import org.osgi.framework.BundleContext;
108 import org.slf4j.Logger;
109 import org.slf4j.LoggerFactory;
110
111 public class BgpConfigurationManager {
112     private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
113     private static DataBroker dataBroker;
114     private static FibDSWriter fibDSWriter;
115     public static IBgpManager bgpManager;
116     private final BundleContext bundleContext;
117     private static Bgp config;
118     private static BgpRouter bgpRouter;
119     private static BgpThriftService updateServer;
120     private BgpCounters bgpCounters;
121     private BgpAlarms bgpAlarms;
122     private Timer bgpCountersTimer;
123     private Timer bgpAlarmsTimer;
124     private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
125     private static final String DEF_LOGLEVEL = "errors";
126     private static final String UPDATE_PORT = "bgp.thrift.service.port";
127     private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
128     private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
129     private static final String DEF_UPORT = "6644";
130     private static final String DEF_CHOST = "127.0.0.1";
131     private static final String DEF_CPORT = "7644";
132     private static final String SDNC_BGP_MIP = "sdnc_bgp_mip";
133     private static final String BGP_SDNC_MIP = "bgp_sdnc_mip";
134     private static final String CLUSTER_CONF_FILE = "/cluster/etc/cluster.conf";
135     private static final Timer IP_ACTIVATION_CHECK_TIMER = new Timer();
136     private static final int STALE_FIB_WAIT = 60;
137     private static final int RESTART_DEFAULT_GR = 90;
138     private long staleStartTime = 0;
139     private long staleEndTime = 0;
140     private long cfgReplayStartTime = 0;
141     private long cfgReplayEndTime = 0;
142     private long staleCleanupTime = 0;
143     private static final int DS_RETRY_COOUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
144     private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
145
146     public String getBgpSdncMipIp() {
147         return readThriftIpForCommunication(BGP_SDNC_MIP);
148     }
149
150     public long getStaleCleanupTime() {
151         return staleCleanupTime;
152     }
153
154     public void setStaleCleanupTime(long staleCleanupTime) {
155         this.staleCleanupTime = staleCleanupTime;
156     }
157
158     public long getCfgReplayEndTime() {
159         return cfgReplayEndTime;
160     }
161
162     public void setCfgReplayEndTime(long cfgReplayEndTime) {
163         this.cfgReplayEndTime = cfgReplayEndTime;
164     }
165
166     public long getCfgReplayStartTime() {
167         return cfgReplayStartTime;
168     }
169
170     public void setCfgReplayStartTime(long cfgReplayStartTime) {
171         this.cfgReplayStartTime = cfgReplayStartTime;
172     }
173
174     public long getStaleEndTime() {
175         return staleEndTime;
176     }
177
178     public void setStaleEndTime(long staleEndTime) {
179         this.staleEndTime = staleEndTime;
180     }
181
182     public long getStaleStartTime() {
183         return staleStartTime;
184     }
185
186     public void setStaleStartTime(long staleStartTime) {
187         this.staleStartTime = staleStartTime;
188     }
189
190
191     // to have stale FIB map (RD, Prefix)
192     //  number of seconds wait for route sync-up between ODL and BGP
193     private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
194
195     static String odlThriftIp = "127.0.0.1";
196     static String bgpThriftIp = "127.0.0.1";
197     private static String cHostStartup;
198     private static String cPortStartup;
199     private static CountDownLatch initer = new CountDownLatch(1);
200     //static IITMProvider itmProvider;
201     //map<rd, map<prefix/len:nexthop, label>>
202     private static Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
203
204     static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
205     static final String BGP_ENTITY_NAME = "bgp";
206
207     static int totalStaledCount = 0;
208     static int totalCleared = 0;
209
210     private static final Class[] REACTORS = {
211         ConfigServerReactor.class, AsIdReactor.class,
212         GracefulRestartReactor.class, LoggingReactor.class,
213         NeighborsReactor.class, UpdateSourceReactor.class,
214         EbgpMultihopReactor.class, AddressFamiliesReactor.class,
215         NetworksReactor.class, VrfsReactor.class, BgpReactor.class
216     };
217
218     private ListenerRegistration<DataChangeListener>[] registrations;
219
220     final BgpConfigurationManager bgpConfigurationManager;
221
222     public BgpConfigurationManager(final DataBroker dataBroker,
223             final EntityOwnershipService entityOwnershipService,
224             final FibDSWriter fibDSWriter,
225             final BundleContext bundleContext)
226             throws InterruptedException, ExecutionException, TimeoutException {
227         BgpConfigurationManager.dataBroker = dataBroker;
228         BgpConfigurationManager.fibDSWriter = fibDSWriter;
229         this.bundleContext = bundleContext;
230         String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
231         cHostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
232         cPortStartup = getProperty(CONFIG_PORT, DEF_CPORT);
233         LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
234                 + cHostStartup + ":" + cPortStartup);
235         VtyshCli.setHostAddr(cHostStartup);
236         ClearBgpCli.setHostAddr(cHostStartup);
237         setEntityOwnershipService(entityOwnershipService);
238         bgpRouter = BgpRouter.getInstance();
239         odlThriftIp = readThriftIpForCommunication(SDNC_BGP_MIP);
240         bgpThriftIp = readThriftIpForCommunication(BGP_SDNC_MIP);
241         registerCallbacks();
242
243         LOG.info("BGP Configuration manager initialized");
244         initer.countDown();
245
246         bgpConfigurationManager = this;
247         BgpUtil.batchSize = BgpUtil.BATCH_SIZE;
248         if (Integer.getInteger("batch.size") != null) {
249             BgpUtil.batchSize = Integer.getInteger("batch.size");
250         }
251         BgpUtil.batchInterval = BgpUtil.PERIODICITY;
252         if (Integer.getInteger("batch.wait.time") != null) {
253             BgpUtil.batchInterval = Integer.getInteger("batch.wait.time");
254         }
255         BgpUtil.registerWithBatchManager(
256                 new DefaultBatchHandler(dataBroker, LogicalDatastoreType.CONFIGURATION, BgpUtil.batchSize,
257                         BgpUtil.batchInterval));
258
259         GlobalEventExecutor.INSTANCE.execute(() -> {
260             final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
261                     IBgpManager.class, bundleContext);
262             bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
263             updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, fibDSWriter);
264             updateServer.start();
265             LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
266         });
267     }
268
269     private Object createListener(Class<?> cls) {
270         Constructor<?> ctor;
271         Object obj = null;
272
273         try {
274             ctor = cls.getConstructor(BgpConfigurationManager.class);
275             obj = ctor.newInstance(this);
276         } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
277                 e) {
278             LOG.error("Failed to create listener object", e);
279         }
280         return obj;
281     }
282
283     private void registerCallbacks() {
284         String emsg = "Failed to register listener";
285         registrations = new ListenerRegistration[REACTORS.length];
286         InstanceIdentifier<?> iid = InstanceIdentifier.create(Bgp.class);
287         for (Class reactor : REACTORS) {
288             Object obj = createListener(reactor);
289             AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
290             dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
291         }
292     }
293
294     public void close() {
295         if (updateServer != null) {
296             updateServer.stop();
297         }
298         LOG.info("{} close", getClass().getSimpleName());
299     }
300
301     private boolean configExists() throws ReadFailedException {
302         InstanceIdentifier.InstanceIdentifierBuilder<Bgp> iib =
303                 InstanceIdentifier.builder(Bgp.class);
304         InstanceIdentifier<Bgp> iid = iib.build();
305         return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
306                 iid).isPresent();
307     }
308
309     private String getProperty(String var, String def) {
310         String property = bundleContext.getProperty(var);
311         return (property == null ? def : property);
312     }
313
314     boolean ignoreClusterDcnEventForFollower() {
315         return !EntityOwnerUtils.amIEntityOwner(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME);
316     }
317
318     public Bgp get() {
319         config = getConfig();
320         return config;
321     }
322
323     public void setEntityOwnershipService(final EntityOwnershipService entityOwnershipService) {
324         try {
325             EntityOwnerUtils.registerEntityCandidateForOwnerShip(entityOwnershipService,
326                 BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME, ownershipChange -> {
327                     LOG.trace("entity owner change event fired");
328                     if (ownershipChange.hasOwner() && ownershipChange.isOwner()) {
329                         LOG.trace("This PL is the Owner");
330                         activateMIP();
331                         bgpRestarted();
332                     } else {
333                         LOG.info("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.hasOwner(),
334                                 ownershipChange.isOwner());
335                     }
336                 });
337         } catch (CandidateAlreadyRegisteredException e) {
338             LOG.error("failed to register bgp entity", e);
339         }
340     }
341
342     private static final String ADD_WARN =
343             "Config store updated; undo with Delete if needed.";
344     private static final String DEL_WARN =
345             "Config store updated; undo with Add if needed.";
346     private static final String UPD_WARN =
347             "Update operation not supported; Config store updated;"
348                     + " restore with another Update if needed.";
349
350     public class ConfigServerReactor
351             extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
352             implements AutoCloseable, ClusteredDataTreeChangeListener<ConfigServer> {
353         private static final String YANG_OBJ = "config-server ";
354
355         public ConfigServerReactor() {
356             super(ConfigServer.class, ConfigServerReactor.class);
357         }
358
359         @Override
360         protected synchronized void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
361             LOG.trace("received bgp connect config host {}", val.getHost().getValue());
362             if (ignoreClusterDcnEventForFollower()) {
363                 return;
364             }
365
366             try {
367                 initer.await();
368             } catch (InterruptedException e) {
369                 // Ignored
370             }
371             LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
372             synchronized (BgpConfigurationManager.this) {
373                 boolean res = bgpRouter.connect(val.getHost().getValue(),
374                         val.getPort().intValue());
375                 if (!res) {
376                     LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
377                 }
378             }
379         }
380
381         @Override
382         protected ConfigServerReactor getDataTreeChangeListener() {
383             return ConfigServerReactor.this;
384         }
385
386         @Override
387         protected InstanceIdentifier<ConfigServer> getWildCardPath() {
388             return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
389         }
390
391         @Override
392         protected synchronized void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
393             LOG.trace("received bgp disconnect");
394             if (ignoreClusterDcnEventForFollower()) {
395                 return;
396             }
397             synchronized (BgpConfigurationManager.this) {
398                 bgpRouter.disconnect();
399             }
400         }
401
402         @Override
403         protected void update(InstanceIdentifier<ConfigServer> iid,
404                 ConfigServer oldval, ConfigServer newval) {
405             LOG.trace("received bgp Connection update");
406             if (ignoreClusterDcnEventForFollower()) {
407                 return;
408             }
409             LOG.error(YANG_OBJ + UPD_WARN);
410         }
411     }
412
413     private BgpRouter getClient(String yangObj) {
414         if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
415             LOG.warn("{}: configuration received when BGP is inactive", yangObj);
416             return null;
417         }
418         return bgpRouter;
419     }
420
421     public class AsIdReactor
422             extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
423             implements AutoCloseable, ClusteredDataTreeChangeListener<AsId> {
424
425         private static final String YANG_OBJ = "as-id ";
426
427         public AsIdReactor() {
428             super(AsId.class, AsIdReactor.class);
429         }
430
431         @Override
432         protected synchronized void add(InstanceIdentifier<AsId> iid, AsId val) {
433             LOG.error("received bgp add asid {}", val);
434             if (ignoreClusterDcnEventForFollower()) {
435                 return;
436             }
437             LOG.debug("received add router config asNum {}", val.getLocalAs());
438             synchronized (BgpConfigurationManager.this) {
439                 IpAddress routerId = val.getRouterId();
440                 BgpRouter br = getClient(YANG_OBJ);
441                 long asNum = val.getLocalAs();
442                 if (br == null) {
443                     LOG.error("{} Unable to process add for routerId {} asNum {}; {}", YANG_OBJ, routerId, asNum,
444                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
445                     return;
446                 }
447                 Boolean afb = val.isAnnounceFbit();
448                 String rid = (routerId == null) ? "" : new String(routerId.getValue());
449                 int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, val);
450                 boolean announceFbit = true;
451                 try {
452                     br.startBgp(asNum, rid, stalepathTime, announceFbit);
453                     if (getBgpCounters() == null) {
454                         startBgpCountersTask();
455                     }
456                     if (getBgpAlarms() == null) {
457                         startBgpAlarmsTask();
458                     }
459                 } catch (BgpRouterException bre) {
460                     if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
461                         LOG.error(YANG_OBJ + "Add requested when BGP is already active");
462                     } else {
463                         LOG.error(YANG_OBJ + "Add received exception: \""
464                                 + bre + "\"; " + ADD_WARN);
465                     }
466                 } catch (TException e) {
467                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
468                 }
469             }
470         }
471
472         @Override
473         protected AsIdReactor getDataTreeChangeListener() {
474             return AsIdReactor.this;
475         }
476
477         @Override
478         protected InstanceIdentifier<AsId> getWildCardPath() {
479             return InstanceIdentifier.create(Bgp.class).child(AsId.class);
480         }
481
482         @Override
483         protected synchronized void remove(InstanceIdentifier<AsId> iid, AsId val) {
484             LOG.error("received delete router config asNum {}", val.getLocalAs());
485             if (ignoreClusterDcnEventForFollower()) {
486                 return;
487             }
488             synchronized (BgpConfigurationManager.this) {
489                 long asNum = val.getLocalAs();
490                 BgpRouter br = getClient(YANG_OBJ);
491                 if (br == null) {
492                     LOG.error("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
493                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
494                     return;
495                 }
496                 try {
497                     br.stopBgp(asNum);
498                 } catch (TException | BgpRouterException e) {
499                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
500                 }
501                 if (getBgpCounters() != null) {
502                     stopBgpCountersTask();
503                 }
504                 if (getBgpAlarms() != null) {
505                     stopBgpAlarmsTask();
506                 }
507             }
508         }
509
510         @Override
511         protected void update(InstanceIdentifier<AsId> iid,
512                 AsId oldval, AsId newval) {
513             if (ignoreClusterDcnEventForFollower()) {
514                 return;
515             }
516             LOG.error(YANG_OBJ + UPD_WARN);
517         }
518     }
519
520     public class GracefulRestartReactor
521             extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
522             implements AutoCloseable, ClusteredDataTreeChangeListener<GracefulRestart> {
523
524         private static final String YANG_OBJ = "graceful-restart ";
525
526         public GracefulRestartReactor() {
527             super(GracefulRestart.class, GracefulRestartReactor.class);
528         }
529
530         @Override
531         protected synchronized void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
532             if (ignoreClusterDcnEventForFollower()) {
533                 return;
534             }
535             synchronized (BgpConfigurationManager.this) {
536                 int stalePathTime = val.getStalepathTime().intValue();
537                 BgpRouter br = getClient(YANG_OBJ);
538                 if (br == null) {
539                     LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
540                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
541                     return;
542                 }
543                 try {
544                     br.addGracefulRestart(stalePathTime);
545                 } catch (TException | BgpRouterException e) {
546                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
547                 }
548             }
549         }
550
551         @Override
552         protected GracefulRestartReactor getDataTreeChangeListener() {
553             return GracefulRestartReactor.this;
554         }
555
556         @Override
557         protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
558             return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
559         }
560
561         @Override
562         protected synchronized void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
563             if (ignoreClusterDcnEventForFollower()) {
564                 return;
565             }
566             LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
567             synchronized (BgpConfigurationManager.this) {
568                 BgpRouter br = getClient(YANG_OBJ);
569                 if (br == null) {
570                     LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
571                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
572                     return;
573                 }
574                 try {
575                     br.delGracefulRestart();
576                 } catch (TException | BgpRouterException e) {
577                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
578                 }
579             }
580         }
581
582         @Override
583         protected void update(InstanceIdentifier<GracefulRestart> iid,
584                 GracefulRestart oldval, GracefulRestart newval) {
585             if (ignoreClusterDcnEventForFollower()) {
586                 return;
587             }
588             LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
589             synchronized (BgpConfigurationManager.this) {
590                 int stalePathTime = newval.getStalepathTime().intValue();
591                 BgpRouter br = getClient(YANG_OBJ);
592                 if (br == null) {
593                     LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
594                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
595                     return;
596                 }
597                 try {
598                     br.addGracefulRestart(stalePathTime);
599                 } catch (TException | BgpRouterException e) {
600                     LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
601                 }
602             }
603         }
604     }
605
606     public class LoggingReactor
607             extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
608             implements AutoCloseable, ClusteredDataTreeChangeListener<Logging> {
609
610         private static final String YANG_OBJ = "logging ";
611
612         public LoggingReactor() {
613             super(Logging.class, LoggingReactor.class);
614         }
615
616         @Override
617         protected synchronized void add(InstanceIdentifier<Logging> iid, Logging val) {
618             if (ignoreClusterDcnEventForFollower()) {
619                 return;
620             }
621             synchronized (BgpConfigurationManager.this) {
622                 BgpRouter br = getClient(YANG_OBJ);
623                 if (br == null) {
624                     LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
625                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
626                     return;
627                 }
628                 try {
629                     br.setLogging(val.getFile(), val.getLevel());
630                 } catch (TException | BgpRouterException e) {
631                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
632                 }
633             }
634         }
635
636         @Override
637         protected LoggingReactor getDataTreeChangeListener() {
638             return LoggingReactor.this;
639         }
640
641         @Override
642         protected InstanceIdentifier<Logging> getWildCardPath() {
643             return InstanceIdentifier.create(Bgp.class).child(Logging.class);
644         }
645
646         @Override
647         protected synchronized void remove(InstanceIdentifier<Logging> iid, Logging val) {
648             if (ignoreClusterDcnEventForFollower()) {
649                 return;
650             }
651             LOG.debug("received remove Logging config val {}", val.getLevel());
652             synchronized (BgpConfigurationManager.this) {
653                 BgpRouter br = getClient(YANG_OBJ);
654                 if (br == null) {
655                     LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
656                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
657                     return;
658                 }
659                 try {
660                     br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
661                 } catch (TException | BgpRouterException e) {
662                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
663                 }
664             }
665         }
666
667         @Override
668         protected void update(InstanceIdentifier<Logging> iid,
669                 Logging oldval, Logging newval) {
670             if (ignoreClusterDcnEventForFollower()) {
671                 return;
672             }
673             synchronized (BgpConfigurationManager.this) {
674                 BgpRouter br = getClient(YANG_OBJ);
675                 if (br == null) {
676                     LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
677                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
678                     return;
679                 }
680                 try {
681                     br.setLogging(newval.getFile(), newval.getLevel());
682                 } catch (TException | BgpRouterException e) {
683                     LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
684                 }
685             }
686         }
687     }
688
689     public class NeighborsReactor
690             extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
691             implements AutoCloseable, ClusteredDataTreeChangeListener<Neighbors> {
692
693         private static final String YANG_OBJ = "neighbors ";
694
695         public NeighborsReactor() {
696             super(Neighbors.class, NeighborsReactor.class);
697         }
698
699         @Override
700         protected synchronized void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
701             if (ignoreClusterDcnEventForFollower()) {
702                 return;
703             }
704             LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
705             synchronized (BgpConfigurationManager.this) {
706                 String peerIp = val.getAddress().getValue();
707                 long as = val.getRemoteAs();
708                 BgpRouter br = getClient(YANG_OBJ);
709                 if (br == null) {
710                     LOG.error("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
711                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
712                     return;
713                 }
714                 try {
715                     //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
716                     br.addNeighbor(peerIp, as);
717
718                 } catch (TException | BgpRouterException e) {
719                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
720                 }
721             }
722         }
723
724         @Override
725         protected NeighborsReactor getDataTreeChangeListener() {
726             return NeighborsReactor.this;
727         }
728
729         @Override
730         protected InstanceIdentifier<Neighbors> getWildCardPath() {
731             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
732         }
733
734         @Override
735         protected synchronized void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
736             if (ignoreClusterDcnEventForFollower()) {
737                 return;
738             }
739             LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
740             synchronized (BgpConfigurationManager.this) {
741                 String peerIp = val.getAddress().getValue();
742                 BgpRouter br = getClient(YANG_OBJ);
743                 if (br == null) {
744                     LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
745                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
746                     return;
747                 }
748                 try {
749                     //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
750                     br.delNeighbor(peerIp);
751                 } catch (TException | BgpRouterException e) {
752                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
753                 }
754             }
755         }
756
757         @Override
758         protected void update(InstanceIdentifier<Neighbors> iid,
759                 Neighbors oldval, Neighbors newval) {
760             if (ignoreClusterDcnEventForFollower()) {
761                 return;
762             }
763             //purposefully nothing to do.
764         }
765     }
766
767     public class EbgpMultihopReactor
768             extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
769             implements AutoCloseable, ClusteredDataTreeChangeListener<EbgpMultihop> {
770
771         private static final String YANG_OBJ = "ebgp-multihop ";
772
773         public EbgpMultihopReactor() {
774             super(EbgpMultihop.class, EbgpMultihopReactor.class);
775         }
776
777         @Override
778         protected synchronized void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
779             if (ignoreClusterDcnEventForFollower()) {
780                 return;
781             }
782             LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
783             synchronized (BgpConfigurationManager.this) {
784                 String peerIp = val.getPeerIp().getValue();
785                 BgpRouter br = getClient(YANG_OBJ);
786                 if (br == null) {
787                     LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
788                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
789                     return;
790                 }
791                 try {
792                     br.addEbgpMultihop(peerIp, val.getNhops().intValue());
793                 } catch (TException | BgpRouterException e) {
794                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
795                 }
796             }
797         }
798
799         @Override
800         protected EbgpMultihopReactor getDataTreeChangeListener() {
801             return EbgpMultihopReactor.this;
802         }
803
804         @Override
805         protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
806             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
807         }
808
809         @Override
810         protected synchronized void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
811             if (ignoreClusterDcnEventForFollower()) {
812                 return;
813             }
814             LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
815             synchronized (BgpConfigurationManager.this) {
816                 String peerIp = val.getPeerIp().getValue();
817                 BgpRouter br = getClient(YANG_OBJ);
818                 if (br == null) {
819                     LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
820                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
821                     return;
822                 }
823                 try {
824                     br.delEbgpMultihop(peerIp);
825                 } catch (TException | BgpRouterException e) {
826                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
827                 }
828             }
829         }
830
831         @Override
832         protected void update(InstanceIdentifier<EbgpMultihop> iid,
833                 EbgpMultihop oldval, EbgpMultihop newval) {
834             if (ignoreClusterDcnEventForFollower()) {
835                 return;
836             }
837             LOG.error(YANG_OBJ + UPD_WARN);
838         }
839     }
840
841     public class UpdateSourceReactor
842             extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
843             implements AutoCloseable, ClusteredDataTreeChangeListener<UpdateSource> {
844
845         private static final String YANG_OBJ = "update-source ";
846
847         public UpdateSourceReactor() {
848             super(UpdateSource.class, UpdateSourceReactor.class);
849         }
850
851         @Override
852         protected synchronized void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
853             if (ignoreClusterDcnEventForFollower()) {
854                 return;
855             }
856             LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
857             synchronized (BgpConfigurationManager.this) {
858                 String peerIp = val.getPeerIp().getValue();
859                 BgpRouter br = getClient(YANG_OBJ);
860                 if (br == null) {
861                     LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
862                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
863                     return;
864                 }
865                 try {
866                     br.addUpdateSource(peerIp, val.getSourceIp().getValue());
867                 } catch (TException | BgpRouterException e) {
868                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
869                 }
870             }
871         }
872
873         @Override
874         protected UpdateSourceReactor getDataTreeChangeListener() {
875             return UpdateSourceReactor.this;
876         }
877
878         @Override
879         protected InstanceIdentifier<UpdateSource> getWildCardPath() {
880             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
881         }
882
883         @Override
884         protected synchronized void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
885             if (ignoreClusterDcnEventForFollower()) {
886                 return;
887             }
888             LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
889             synchronized (BgpConfigurationManager.this) {
890                 String peerIp = val.getPeerIp().getValue();
891                 BgpRouter br = getClient(YANG_OBJ);
892                 if (br == null) {
893                     LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
894                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
895                     return;
896                 }
897                 try {
898                     br.delUpdateSource(peerIp);
899                 } catch (TException | BgpRouterException e) {
900                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
901                 }
902             }
903         }
904
905         @Override
906         protected void update(InstanceIdentifier<UpdateSource> iid,
907                 UpdateSource oldval, UpdateSource newval) {
908             if (ignoreClusterDcnEventForFollower()) {
909                 return;
910             }
911             LOG.error(YANG_OBJ + UPD_WARN);
912         }
913     }
914
915     public class AddressFamiliesReactor
916             extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
917             implements AutoCloseable, ClusteredDataTreeChangeListener<AddressFamilies> {
918
919         private static final String YANG_OBJ = "address-families ";
920
921         public AddressFamiliesReactor() {
922             super(AddressFamilies.class, AddressFamiliesReactor.class);
923         }
924
925         @Override
926         protected synchronized void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
927             if (ignoreClusterDcnEventForFollower()) {
928                 return;
929             }
930             LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
931             synchronized (BgpConfigurationManager.this) {
932                 String peerIp = val.getPeerIp().getValue();
933                 BgpRouter br = getClient(YANG_OBJ);
934                 if (br == null) {
935                     LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
936                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
937                     return;
938                 }
939                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
940                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
941                 try {
942                     br.addAddressFamily(peerIp, afi, safi);
943                 } catch (TException | BgpRouterException e) {
944                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
945                 }
946             }
947         }
948
949         @Override
950         protected AddressFamiliesReactor getDataTreeChangeListener() {
951             return AddressFamiliesReactor.this;
952         }
953
954         @Override
955         protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
956             return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
957         }
958
959         @Override
960         protected synchronized void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
961             if (ignoreClusterDcnEventForFollower()) {
962                 return;
963             }
964             LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
965             synchronized (BgpConfigurationManager.this) {
966                 String peerIp = val.getPeerIp().getValue();
967                 BgpRouter br = getClient(YANG_OBJ);
968                 if (br == null) {
969                     LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
970                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
971                     return;
972                 }
973                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
974                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
975                 try {
976                     br.delAddressFamily(peerIp, afi, safi);
977                 } catch (TException | BgpRouterException e) {
978                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
979                 }
980             }
981         }
982
983         @Override
984         protected void update(InstanceIdentifier<AddressFamilies> iid,
985                 AddressFamilies oldval, AddressFamilies newval) {
986             if (ignoreClusterDcnEventForFollower()) {
987                 return;
988             }
989             LOG.error(YANG_OBJ + UPD_WARN);
990         }
991     }
992
993     public class NetworksReactor
994             extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
995             implements AutoCloseable, ClusteredDataTreeChangeListener<Networks> {
996
997         private static final String YANG_OBJ = "networks ";
998
999         public NetworksReactor() {
1000             super(Networks.class, NetworksReactor.class);
1001         }
1002
1003         @Override
1004         public NetworksReactor getDataTreeChangeListener() {
1005             return NetworksReactor.this;
1006         }
1007
1008         @Override
1009         protected synchronized void add(InstanceIdentifier<Networks> iid, Networks val) {
1010             if (ignoreClusterDcnEventForFollower()) {
1011                 return;
1012             }
1013             LOG.debug("received add Networks config val {}", val.getPrefixLen());
1014             synchronized (BgpConfigurationManager.this) {
1015                 String rd = val.getRd();
1016                 String pfxlen = val.getPrefixLen();
1017                 String nh = val.getNexthop().getValue();
1018                 BgpRouter br = getClient(YANG_OBJ);
1019                 if (br == null) {
1020                     LOG.error("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
1021                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1022                     return;
1023                 }
1024                 Long label = val.getLabel();
1025                 int lbl = (label == null) ? qbgpConstants.LBL_NO_LABEL
1026                         : label.intValue();
1027                 int l3vni = (val.getL3vni() == null) ? qbgpConstants.LBL_NO_LABEL
1028                         : val.getL3vni().intValue();
1029
1030                 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1031                 int ethernetTag = val.getEthtag().intValue();
1032                 String esi = val.getEsi();
1033                 String macaddress = val.getMacaddress();
1034                 EncapType encapType = val.getEncapType();
1035                 String routerMac = val.getRoutermac();
1036
1037                 try {
1038                     br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
1039                             ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1040                 } catch (TException | BgpRouterException e) {
1041                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1042                 }
1043             }
1044         }
1045
1046         @Override
1047         protected InstanceIdentifier<Networks> getWildCardPath() {
1048             return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1049         }
1050
1051         @Override
1052         protected synchronized void remove(InstanceIdentifier<Networks> iid, Networks val) {
1053             if (ignoreClusterDcnEventForFollower()) {
1054                 return;
1055             }
1056             LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1057             synchronized (BgpConfigurationManager.this) {
1058                 String rd = val.getRd();
1059                 String pfxlen = val.getPrefixLen();
1060                 BgpRouter br = getClient(YANG_OBJ);
1061                 if (br == null) {
1062                     LOG.error("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
1063                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1064                     return;
1065                 }
1066                 Long label = val.getLabel();
1067                 int lbl = (label == null) ? 0 : label.intValue();
1068                 if (rd == null && lbl > 0) {
1069                     //LU prefix is being deleted.
1070                     rd = Integer.toString(lbl);
1071                 }
1072                 try {
1073                     br.delPrefix(rd, pfxlen);
1074                 } catch (TException | BgpRouterException e) {
1075                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1076                 }
1077             }
1078         }
1079
1080         @Override
1081         protected void update(final InstanceIdentifier<Networks> iid,
1082                 final Networks oldval, final Networks newval) {
1083             if (ignoreClusterDcnEventForFollower()) {
1084                 return;
1085             }
1086             if (oldval.equals(newval)) {
1087                 //Update: OLD and New values are same, no need to trigger remove/add.
1088                 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1089                         oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1090                 return;
1091             }
1092             LOG.debug("received update networks config val {}", newval.getPrefixLen());
1093             remove(iid, oldval);
1094             timer.schedule(new TimerTask() {
1095                 @Override
1096                 public void run() {
1097                     add(iid, newval);
1098                 }
1099             }, Integer.getInteger("bgp.nexthop.update.delay.in.secs", 5) * 1000);
1100         }
1101     }
1102
1103     static Timer timer = new Timer();
1104
1105     public class VrfsReactor
1106             extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1107             implements AutoCloseable, ClusteredDataTreeChangeListener<Vrfs> {
1108
1109         private static final String YANG_OBJ = "vrfs ";
1110
1111         public VrfsReactor() {
1112             super(Vrfs.class, VrfsReactor.class);
1113         }
1114
1115         @Override
1116         protected synchronized void add(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1117             if (ignoreClusterDcnEventForFollower()) {
1118                 return;
1119             }
1120             LOG.debug("received add Vrfs config val {}", val.getRd());
1121             synchronized (BgpConfigurationManager.this) {
1122                 String rd = val.getRd();
1123                 BgpRouter br = getClient(YANG_OBJ);
1124                 if (br == null) {
1125                     LOG.error("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1126                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1127                     return;
1128                 }
1129                 try {
1130                     br.addVrf(val.getLayerType(), rd, val.getImportRts(),
1131                             val.getExportRts());
1132                 } catch (TException | BgpRouterException e) {
1133                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1134                 }
1135             }
1136         }
1137
1138         @Override
1139         protected VrfsReactor getDataTreeChangeListener() {
1140             return VrfsReactor.this;
1141         }
1142
1143         @Override
1144         protected InstanceIdentifier<Vrfs> getWildCardPath() {
1145             return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1146         }
1147
1148         @Override
1149         protected synchronized void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1150             if (ignoreClusterDcnEventForFollower()) {
1151                 return;
1152             }
1153             LOG.debug("received remove Vrfs config val {}", val.getRd());
1154             synchronized (BgpConfigurationManager.this) {
1155                 String rd = val.getRd();
1156                 BgpRouter br = getClient(YANG_OBJ);
1157                 if (br == null) {
1158                     LOG.error("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
1159                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1160                     return;
1161                 }
1162                 try {
1163                     br.delVrf(rd);
1164                 } catch (TException | BgpRouterException e) {
1165                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1166                 }
1167             }
1168         }
1169
1170         @Override
1171         protected void update(InstanceIdentifier<Vrfs> iid,
1172                 Vrfs oldval, Vrfs newval) {
1173             if (ignoreClusterDcnEventForFollower()) {
1174                 return;
1175             }
1176             LOG.debug("VRFS: Update getting triggered for VRFS rd {}", oldval.getRd());
1177             LOG.error(YANG_OBJ + UPD_WARN);
1178         }
1179     }
1180
1181     Future lastCleanupJob;
1182     Future lastReplayJobFt = null;
1183
1184     protected void activateMIP() {
1185         try {
1186             LOG.trace("BgpReactor: Executing MIP Activate command");
1187             Process processBgp = Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1188             Process processOs = Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1189             LOG.trace("bgpMIP Activated");
1190
1191         } catch (IOException io) {
1192             LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1193         }
1194     }
1195
1196     AtomicBoolean started = new AtomicBoolean(false);
1197
1198     public class BgpReactor
1199             extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1200             implements AutoCloseable, ClusteredDataTreeChangeListener<Bgp> {
1201
1202         private static final String YANG_OBJ = "Bgp ";
1203
1204         public BgpReactor() {
1205             super(Bgp.class, BgpReactor.class);
1206         }
1207
1208
1209         @Override
1210         protected synchronized void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1211             LOG.error("received add Bgp config replaying the config");
1212
1213             try {
1214                 initer.await();
1215             } catch (InterruptedException e) {
1216                 // Ignored
1217             }
1218             synchronized (BgpConfigurationManager.this) {
1219                 config = val;
1220                 if (ignoreClusterDcnEventForFollower()) {
1221                     return;
1222                 }
1223                 activateMIP();
1224                 if (isIpAvailable(odlThriftIp)) {
1225                     bgpRestarted();
1226                 } else {
1227                     IP_ACTIVATION_CHECK_TIMER.scheduleAtFixedRate(new TimerTask() {
1228                         @Override
1229                         public void run() {
1230                             if (isIpAvailable(odlThriftIp)) {
1231                                 bgpRestarted();
1232                                 IP_ACTIVATION_CHECK_TIMER.cancel();
1233                             } else {
1234                                 LOG.trace("waiting for odlThriftIP: {} to be present", odlThriftIp);
1235                             }
1236                         }
1237                     }, 10000L, 10000L);
1238                 }
1239             }
1240         }
1241
1242         @Override
1243         protected BgpReactor getDataTreeChangeListener() {
1244             return BgpReactor.this;
1245         }
1246
1247         @Override
1248         protected InstanceIdentifier<Bgp> getWildCardPath() {
1249             return InstanceIdentifier.create(Bgp.class);
1250         }
1251
1252         @Override
1253         protected synchronized void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1254             if (ignoreClusterDcnEventForFollower()) {
1255                 return;
1256             }
1257             LOG.debug("received remove Bgp config");
1258             synchronized (BgpConfigurationManager.this) {
1259                 config = null;
1260             }
1261         }
1262
1263         @Override
1264         protected void update(InstanceIdentifier<Bgp> iid,
1265                 Bgp oldval, Bgp newval) {
1266             if (ignoreClusterDcnEventForFollower()) {
1267                 return;
1268             }
1269             synchronized (BgpConfigurationManager.this) {
1270                 config = newval;
1271             }
1272         }
1273     }
1274
1275     public String readThriftIpForCommunication(String mipAddr) {
1276         File file = new File(CLUSTER_CONF_FILE);
1277         if (!file.exists()) {
1278             return DEF_CHOST;
1279         }
1280
1281         try (BufferedReader br = new BufferedReader(new FileReader(file))) {
1282             String line;
1283             while ((line = br.readLine()) != null) {
1284                 if (line.contains(mipAddr)) {
1285                     line = line.trim();
1286                     return line.substring(line.lastIndexOf(" ") + 1);
1287                 }
1288             }
1289         } catch (FileNotFoundException e) {
1290             return DEF_CHOST;
1291         } catch (IOException e) {
1292             LOG.error("Error reading {}", CLUSTER_CONF_FILE, e);
1293         }
1294         return DEF_CHOST;
1295     }
1296
1297     public boolean isIpAvailable(String odlip) {
1298
1299         try {
1300             if (odlip != null) {
1301                 if ("127.0.0.1".equals(odlip)) {
1302                     return true;
1303                 }
1304                 Enumeration networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1305                 while (networkInterfaceEnumeration.hasMoreElements()) {
1306                     NetworkInterface networkInterface = (NetworkInterface) networkInterfaceEnumeration.nextElement();
1307                     Enumeration inetAddressEnumeration = networkInterface.getInetAddresses();
1308                     while (inetAddressEnumeration.hasMoreElements()) {
1309                         InetAddress inetAddress = (InetAddress) inetAddressEnumeration.nextElement();
1310                         if (odlip.equals(inetAddress.getHostAddress())) {
1311                             return true;
1312                         }
1313                     }
1314                 }
1315             }
1316         } catch (SocketException e) {
1317             // Ignored?
1318         }
1319         return false;
1320     }
1321
1322     public static long getStalePathtime(int defValue, AsId asId) {
1323         long spt = 0;
1324         try {
1325             spt = getConfig().getGracefulRestart().getStalepathTime();
1326         } catch (NullPointerException e) {
1327             try {
1328                 spt = asId.getStalepathTime();
1329                 LOG.trace("BGP config/Stale-path time is not set using graceful");
1330             } catch (NullPointerException ignore) {
1331                 LOG.trace("BGP AS id is not set using graceful");
1332                 spt = defValue;
1333             }
1334         }
1335         if (spt == 0) {
1336             LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1337             spt = defValue;
1338         }
1339         return spt;
1340     }
1341
1342     public synchronized void bgpRestarted() {
1343         /*
1344          * If there a thread which in the process of stale cleanup, cancel it
1345          * and start a new thread (to avoid processing same again).
1346          */
1347         if (previousReplayJobInProgress()) {
1348             cancelPreviousReplayJob();
1349         }
1350         Runnable task = () -> {
1351             try {
1352                 LOG.info("running bgp replay task ");
1353                 if (get() == null) {
1354                     String host = getConfigHost();
1355                     int port = getConfigPort();
1356                     LOG.info("connecting  to bgp host {} ", host);
1357
1358                     boolean res = bgpRouter.connect(host, port);
1359                     LOG.info("no config to push in bgp replay task ");
1360                     return;
1361                 }
1362                 setStaleStartTime(System.currentTimeMillis());
1363                 LOG.info("started creating stale fibDSWriter  map ");
1364                 createStaleFibMap();
1365                 setStaleEndTime(System.currentTimeMillis());
1366                 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1367                 LOG.info("started bgp config replay ");
1368                 setCfgReplayStartTime(System.currentTimeMillis());
1369                 try {
1370                     replay();
1371                 } catch (TimeoutException | ExecutionException e) {
1372                     LOG.error("Error while replaying routes. {}", e);
1373                 }
1374                 setCfgReplayEndTime(System.currentTimeMillis());
1375                 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1376                 long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1377                 Thread.sleep(routeSyncTime * 1000L);
1378                 setStaleCleanupTime(routeSyncTime);
1379                 new RouteCleanup().call();
1380             } catch (InterruptedException eCancel) {
1381                 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1382             }
1383         };
1384         lastReplayJobFt = executor.submit(task);
1385     }
1386
1387     private boolean previousReplayJobInProgress() {
1388         return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1389     }
1390
1391     private void cancelPreviousReplayJob() {
1392         try {
1393             LOG.error("cancelling already running bgp replay task");
1394             lastReplayJobFt.cancel(true);
1395             lastReplayJobFt = null;
1396             Thread.sleep(2000);
1397         } catch (InterruptedException e) {
1398             LOG.error("Failed to cancel previous replay job ", e);
1399         }
1400     }
1401
1402     private static void doRouteSync() throws InterruptedException, TimeoutException, ExecutionException {
1403         BgpSyncHandle bsh = BgpSyncHandle.getInstance();
1404         LOG.error("Starting BGP route sync");
1405         try {
1406             bgpRouter.initRibSync(bsh);
1407         } catch (TException | BgpRouterException e) {
1408             LOG.error("Route sync aborted, exception when initializing", e);
1409             return;
1410         }
1411         while (bsh.getState() != bsh.DONE) {
1412             Routes routes = null;
1413             try {
1414                 routes = bgpRouter.doRibSync(bsh);
1415             } catch (TException | BgpRouterException e) {
1416                 LOG.error("Route sync aborted, exception when syncing", e);
1417                 return;
1418             }
1419             Iterator<Update> updates = routes.getUpdatesIterator();
1420             while (updates.hasNext()) {
1421                 Update update = updates.next();
1422                 Map<String, Map<String, Long>> staleFibRdMap = BgpConfigurationManager.getStaledFibEntriesMap();
1423                 String rd = update.getRd();
1424                 String nexthop = update.getNexthop();
1425
1426                 // TODO: decide correct label here
1427                 int label = update.getL3label();
1428
1429                 String prefix = update.getPrefix();
1430                 int plen = update.getPrefixlen();
1431
1432
1433                 // TODO: protocol type will not be available in "update"
1434                 // use "rd" to query vrf table and obtain the protocol_type. Currently using PROTOCOL_EVPN as default.
1435                 onUpdatePushRoute(
1436                         protocol_type.PROTOCOL_EVPN,
1437                         rd,
1438                         prefix,
1439                         plen,
1440                         nexthop,
1441                         update.getEthtag(),
1442                         update.getEsi(),
1443                         update.getMacaddress(),
1444                         label,
1445                         update.getRoutermac()
1446                 );
1447             }
1448         }
1449         try {
1450             LOG.error("Ending BGP route-sync");
1451             bgpRouter.endRibSync(bsh);
1452         } catch (TException | BgpRouterException e) {
1453             // Ignored?
1454         }
1455     }
1456
1457     /* onUpdatePushRoute
1458      * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1459      *  - Entry compare shall include NextHop, Label.
1460      *  - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1461      *  - If entry not found, add to FIB Config DS.
1462      *  - If entry found, but either Label/NextHop doesn't match.
1463      *      - Update FIB Config DS with modified values.
1464      *      - delete from Stale Map.
1465      */
1466
1467     public static void onUpdatePushRoute(protocol_type protocolType,
1468                                          String rd,
1469                                          String prefix,
1470                                          int plen,
1471                                          String nextHop,
1472                                          int ethtag,
1473                                          String esi,
1474                                          String macaddress,
1475                                          int label,
1476                                          String routermac)
1477             throws InterruptedException, ExecutionException, TimeoutException {
1478         boolean addroute = false;
1479         long l3vni = 0L;
1480         VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1481         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1482             encapType = VrfEntry.EncapType.Vxlan;
1483             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = BgpUtil.getVpnInstanceOpData(dataBroker, rd);
1484             if (vpnInstanceOpDataEntry != null) {
1485                 l3vni = vpnInstanceOpDataEntry.getL3vni();
1486             } else {
1487                 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1488                 return;
1489             }
1490         }
1491         if (!staledFibEntriesMap.isEmpty()) {
1492             // restart Scenario, as MAP is not empty.
1493             Map<String, Long> map = staledFibEntriesMap.get(rd);
1494             if (map != null) {
1495                 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1496                 Long labelInStaleMap = map.get(prefixNextHop);
1497                 if (null == labelInStaleMap) {
1498                     // New Entry, which happened to be added during restart.
1499                     addroute = true;
1500                 } else {
1501                     map.remove(prefixNextHop);
1502                     if (isRouteModified(label, labelInStaleMap)) {
1503                         LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1504                         // Existing entry, where in Label got modified during restart
1505                         addroute = true;
1506                     }
1507                 }
1508             }
1509         } else {
1510             LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1511             addroute = true;
1512         }
1513         if (addroute) {
1514             LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1515             // TODO: modify addFibEntryToDS signature
1516             fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, Collections.singletonList(nextHop),
1517                     encapType, label, l3vni, routermac, RouteOrigin.BGP);
1518             LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1519         }
1520     }
1521
1522     private static boolean isRouteModified(int label, Long labelInStaleMap) {
1523         return labelInStaleMap != null && !labelInStaleMap.equals(label);
1524     }
1525
1526     private static void replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1527         for (Neighbors nbr : neighbors) {
1528             try {
1529                 br.addNeighbor(nbr.getAddress().getValue(),
1530                         nbr.getRemoteAs());
1531                 //itmProvider.buildTunnelsToDCGW(new IpAddress(nbr.getAddress().getValue().toCharArray()));
1532             } catch (TException | BgpRouterException e) {
1533                 LOG.error("Replay:addNbr() received exception", e);
1534                 continue;
1535             }
1536             EbgpMultihop en = nbr.getEbgpMultihop();
1537             if (en != null) {
1538                 try {
1539                     br.addEbgpMultihop(en.getPeerIp().getValue(),
1540                             en.getNhops().intValue());
1541                 } catch (TException | BgpRouterException e) {
1542                     LOG.error("Replay:addEBgp() received exception", e);
1543                 }
1544             }
1545             UpdateSource us = nbr.getUpdateSource();
1546             if (us != null) {
1547                 try {
1548                     br.addUpdateSource(us.getPeerIp().getValue(),
1549                             us.getSourceIp().getValue());
1550                 } catch (TException | BgpRouterException e) {
1551                     LOG.error("Replay:addUS() received exception", e);
1552                 }
1553             }
1554             List<AddressFamilies> afs = nbr.getAddressFamilies();
1555             if (afs != null) {
1556                 for (AddressFamilies af : afs) {
1557                     af_afi afi = af_afi.findByValue(af.getAfi().intValue());
1558                     af_safi safi = af_safi.findByValue(af.getSafi().intValue());
1559                     try {
1560                         br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
1561                     } catch (TException | BgpRouterException e) {
1562                         LOG.error("Replay:addAf() received exception", e);
1563                     }
1564                 }
1565             }
1566         }
1567     }
1568
1569     public static String getConfigHost() {
1570         if (config == null) {
1571             return cHostStartup;
1572         }
1573         ConfigServer ts = config.getConfigServer();
1574         return (ts == null ? cHostStartup : ts.getHost().getValue());
1575     }
1576
1577     public static int getConfigPort() {
1578         if (config == null) {
1579             return Integer.parseInt(cPortStartup);
1580         }
1581         ConfigServer ts = config.getConfigServer();
1582         return (ts == null ? Integer.parseInt(cPortStartup) :
1583                 ts.getPort().intValue());
1584     }
1585
1586     public static Bgp getConfig() {
1587         AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COOUNT);
1588         while (0 != bgpDSretryCount.decrementAndGet()) {
1589             try {
1590                 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1591                         InstanceIdentifier.create(Bgp.class)).orNull();
1592             } catch (ReadFailedException e) {
1593                 //Config DS may not be up, so sleep for 1 second and retry
1594                 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
1595                 try {
1596                     Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
1597                 } catch (InterruptedException timerEx) {
1598                     LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
1599                             + "config DS availability", timerEx);
1600                 }
1601             }
1602         }
1603         LOG.error("failed to get bgp config");
1604         return null;
1605     }
1606
1607     @SuppressWarnings("checkstyle:IllegalCatch")
1608     public synchronized void replay() throws InterruptedException, TimeoutException, ExecutionException {
1609         synchronized (bgpConfigurationManager) {
1610             String host = getConfigHost();
1611             int port = getConfigPort();
1612             LOG.error("connecting  to bgp host {} ", host);
1613
1614             boolean res = bgpRouter.connect(host, port);
1615             if (!res) {
1616                 String msg = "Cannot connect to BGP config server at " + host + ":" + port;
1617                 if (config != null) {
1618                     msg += "; Configuration Replay aborted";
1619                 }
1620                 LOG.error(msg);
1621                 return;
1622             }
1623             config = getConfig();
1624             if (config == null) {
1625                 LOG.error("bgp config is empty nothing to push to bgp");
1626                 return;
1627             }
1628             BgpRouter br = bgpRouter;
1629             AsId asId = config.getAsId();
1630             if (asId == null) {
1631                 return;
1632             }
1633             long asNum = asId.getLocalAs();
1634             IpAddress routerId = asId.getRouterId();
1635             Long spt = asId.getStalepathTime();
1636             Boolean afb = asId.isAnnounceFbit();
1637             String rid = (routerId == null) ? "" : new String(routerId.getValue());
1638             int stalepathTime = (int) getStalePathtime(0, config.getAsId());
1639             boolean announceFbit = true;
1640             try {
1641                 br.startBgp(asNum, rid, stalepathTime, announceFbit);
1642             } catch (BgpRouterException bre) {
1643                 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
1644                     doRouteSync();
1645                 } else {
1646                     LOG.error("Replay: startBgp() received exception: \""
1647                             + bre + "\"; " + ADD_WARN);
1648                 }
1649             } catch (TException e) {
1650                 //not unusual. We may have restarted & BGP is already on
1651                 LOG.error("Replay:startBgp() received exception: \"" + e + "\"");
1652             }
1653
1654             if (getBgpCounters() == null) {
1655                 startBgpCountersTask();
1656             }
1657
1658             if (getBgpAlarms() == null) {
1659                 startBgpAlarmsTask();
1660             }
1661
1662             Logging logging = config.getLogging();
1663             if (logging != null) {
1664                 try {
1665                     br.setLogging(logging.getFile(), logging.getLevel());
1666                 } catch (TException | BgpRouterException e) {
1667                     LOG.error("Replay:setLogging() received exception", e);
1668                 }
1669             }
1670
1671             GracefulRestart gracefulRestart = config.getGracefulRestart();
1672             if (gracefulRestart != null) {
1673                 try {
1674                     br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
1675                 } catch (TException | BgpRouterException e) {
1676                     LOG.error("Replay:addGr() received exception", e);
1677                 }
1678             }
1679
1680             List<Vrfs> vrfs = config.getVrfs();
1681             if (vrfs != null) {
1682                 for (Vrfs vrf : vrfs) {
1683                     try {
1684                         br.addVrf(vrf.getLayerType(), vrf.getRd(), vrf.getImportRts(),
1685                                 vrf.getExportRts());
1686                     } catch (TException | BgpRouterException e) {
1687                         LOG.error("Replay:addVrf() received exception", e);
1688                     }
1689                 }
1690             }
1691
1692             List<Networks> ln = config.getNetworks();
1693             if (ln != null) {
1694                 for (Networks net : ln) {
1695                     String rd = net.getRd();
1696                     String pfxlen = net.getPrefixLen();
1697                     String nh = net.getNexthop().getValue();
1698                     Long label = net.getLabel();
1699                     int lbl = (label == null) ? 0 : label.intValue();
1700                     int l3vni = (net.getL3vni() == null) ? 0 : net.getL3vni().intValue();
1701                     if (rd == null && lbl > 0) {
1702                         //LU prefix is being deleted.
1703                         rd = Integer.toString(lbl);
1704                     }
1705
1706                     BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
1707                     int ethernetTag = net.getEthtag().intValue();
1708                     String esi = net.getEsi();
1709                     String macaddress = net.getMacaddress();
1710                     EncapType encapType = net.getEncapType();
1711                     String routerMac = net.getRoutermac();
1712
1713                     try {
1714                         br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
1715                                 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1716                     } catch (Exception e) {
1717                         LOG.error("Replay:addPfx() received exception", e);
1718                     }
1719                 }
1720             }
1721             List<Neighbors> neighbors = config.getNeighbors();
1722             if (neighbors != null) {
1723                 LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
1724                 replayNbrConfig(neighbors, br);
1725             } else {
1726                 LOG.error("no Neighbors present for replay config ");
1727             }
1728         }
1729     }
1730
1731     private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
1732         BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1733     }
1734
1735     private <T extends DataObject> void asyncWrite(InstanceIdentifier<T> iid, T dto) {
1736         BgpUtil.write(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1737     }
1738
1739     private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
1740         BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, iid);
1741     }
1742
1743     public synchronized void startConfig(String bgpHost, int thriftPort) {
1744         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
1745                 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
1746         InstanceIdentifier<ConfigServer> iid = iib.build();
1747         Ipv4Address ipAddr = new Ipv4Address(bgpHost);
1748         ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
1749                 .setPort((long) thriftPort).build();
1750         update(iid, dto);
1751     }
1752
1753     public synchronized void startBgp(long as, String routerId, int spt, boolean fbit) {
1754         IpAddress rid = (routerId == null) ? null : new IpAddress(routerId.toCharArray());
1755         Long staleTime = (long) spt;
1756         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
1757                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
1758         InstanceIdentifier<AsId> iid = iib.build();
1759         AsId dto = new AsIdBuilder().setLocalAs(as)
1760                 .setRouterId(rid)
1761                 .setStalepathTime(staleTime)
1762                 .setAnnounceFbit(fbit).build();
1763         update(iid, dto);
1764     }
1765
1766     public synchronized void addLogging(String fileName, String logLevel) {
1767         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
1768                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
1769         InstanceIdentifier<Logging> iid = iib.build();
1770         Logging dto = new LoggingBuilder().setFile(fileName)
1771                 .setLevel(logLevel).build();
1772         update(iid, dto);
1773     }
1774
1775     public synchronized void addGracefulRestart(int staleTime) {
1776         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
1777                 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
1778         InstanceIdentifier<GracefulRestart> iid = iib.build();
1779         GracefulRestart dto = new GracefulRestartBuilder()
1780                 .setStalepathTime((long) staleTime).build();
1781         update(iid, dto);
1782     }
1783
1784     public synchronized void addNeighbor(String nbrIp, long remoteAs) {
1785         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1786         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
1787                 InstanceIdentifier.builder(Bgp.class)
1788                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
1789         InstanceIdentifier<Neighbors> iid = iib.build();
1790         Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
1791                 .setRemoteAs(remoteAs).build();
1792         update(iid, dto);
1793     }
1794
1795     public synchronized void addUpdateSource(String nbrIp, String srcIp) {
1796         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1797         Ipv4Address srcAddr = new Ipv4Address(srcIp);
1798         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
1799                 InstanceIdentifier.builder(Bgp.class)
1800                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
1801                         .child(UpdateSource.class);
1802         InstanceIdentifier<UpdateSource> iid = iib.build();
1803         UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
1804                 .setSourceIp(srcAddr).build();
1805         update(iid, dto);
1806     }
1807
1808     public synchronized void addEbgpMultihop(String nbrIp, int hops) {
1809         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1810         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
1811                 InstanceIdentifier.builder(Bgp.class)
1812                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
1813                         .child(EbgpMultihop.class);
1814         InstanceIdentifier<EbgpMultihop> iid = iib.build();
1815         EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
1816                 .setNhops((long) hops).build();
1817         update(iid, dto);
1818     }
1819
1820     public synchronized void addAddressFamily(String nbrIp, int afi, int safi) {
1821         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1822         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
1823                 InstanceIdentifier.builder(Bgp.class)
1824                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
1825                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
1826         InstanceIdentifier<AddressFamilies> iid = iib.build();
1827         AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
1828                 .setAfi((long) afi).setSafi((long) safi).build();
1829         update(iid, dto);
1830     }
1831
1832     public synchronized void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
1833               VrfEntry.EncapType encapType, int lbl, long l3vni, String gatewayMac, int addressFamily) {
1834         for (String nh : nhList) {
1835             Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
1836             Long label = (long) lbl;
1837             Long afi = (long) addressFamily;
1838             InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
1839                     .child(Networks.class, new NetworksKey(pfx, rd)).build();
1840             NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
1841                                                 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG)
1842                                                 .setAfi(afi);
1843             buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, macAddress, gatewayMac);
1844             update(iid, networksBuilder.build());
1845         }
1846     }
1847
1848     private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
1849                                                   long l3vni, String macAddress, String gatewayMac) {
1850         if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
1851             builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
1852                     .setEncapType(EncapType.GRE);
1853         } else {
1854             builder.setL3vni(l3vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
1855                     .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
1856         }
1857     }
1858
1859     // TODO: add LayerType as arg - supports command
1860     public synchronized void addVrf(String rd, List<String> irts, List<String> erts, LayerType layerType) {
1861         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
1862                 InstanceIdentifier.builder(Bgp.class)
1863                         .child(Vrfs.class, new VrfsKey(rd));
1864         InstanceIdentifier<Vrfs> iid = iib.build();
1865         Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
1866                 .setExportRts(erts).setLayerType(layerType).build();
1867         try {
1868             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1869         } catch (TransactionCommitFailedException e) {
1870             LOG.error("Error adding VRF to datastore", e);
1871             throw new RuntimeException(e);
1872         }
1873     }
1874
1875     public synchronized void stopConfig() {
1876         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
1877                 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
1878         InstanceIdentifier<ConfigServer> iid = iib.build();
1879         delete(iid);
1880     }
1881
1882     public synchronized void stopBgp() {
1883         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
1884                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
1885         InstanceIdentifier<AsId> iid = iib.build();
1886         delete(iid);
1887     }
1888
1889     public synchronized void delLogging() {
1890         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
1891                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
1892         InstanceIdentifier<Logging> iid = iib.build();
1893         delete(iid);
1894     }
1895
1896     public synchronized void delGracefulRestart() {
1897         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
1898                 InstanceIdentifier.builder(Bgp.class)
1899                         .child(GracefulRestart.class);
1900         InstanceIdentifier<GracefulRestart> iid = iib.build();
1901         delete(iid);
1902     }
1903
1904     public synchronized void delNeighbor(String nbrIp) {
1905         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1906         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
1907                 InstanceIdentifier.builder(Bgp.class)
1908                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
1909         InstanceIdentifier<Neighbors> iid = iib.build();
1910         delete(iid);
1911     }
1912
1913     public synchronized void delUpdateSource(String nbrIp) {
1914         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1915         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
1916                 InstanceIdentifier.builder(Bgp.class)
1917                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
1918                         .child(UpdateSource.class);
1919         InstanceIdentifier<UpdateSource> iid = iib.build();
1920         delete(iid);
1921     }
1922
1923     public synchronized void delEbgpMultihop(String nbrIp) {
1924         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1925         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
1926                 InstanceIdentifier.builder(Bgp.class)
1927                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
1928                         .child(EbgpMultihop.class);
1929         InstanceIdentifier<EbgpMultihop> iid = iib.build();
1930         delete(iid);
1931     }
1932
1933     public synchronized void delAddressFamily(String nbrIp, int afi, int safi) {
1934         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
1935         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
1936                 InstanceIdentifier.builder(Bgp.class)
1937                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
1938                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
1939         InstanceIdentifier<AddressFamilies> iid = iib.build();
1940         delete(iid);
1941     }
1942
1943     public synchronized void delPrefix(String rd, String pfx, int afi) {
1944         InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
1945                 InstanceIdentifier.builder(Bgp.class)
1946                         .child(Networks.class, new NetworksKey(pfx, rd));
1947         InstanceIdentifier<Networks> iid = iib.build();
1948         delete(iid);
1949     }
1950
1951     public synchronized void delVrf(String rd) {
1952         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
1953                 InstanceIdentifier.builder(Bgp.class)
1954                         .child(Vrfs.class, new VrfsKey(rd));
1955         InstanceIdentifier<Vrfs> iid = iib.build();
1956         delete(iid);
1957     }
1958
1959     static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
1960
1961     /*
1962     * Remove Stale Marked Routes after timer expiry.
1963     */
1964     class RouteCleanup implements Callable<Integer> {
1965
1966         @Override
1967         public Integer call() {
1968             totalCleared = 0;
1969             try {
1970                 if (staledFibEntriesMap.isEmpty()) {
1971                     LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
1972                 } else {
1973                     for (String rd : staledFibEntriesMap.keySet()) {
1974                         if (Thread.interrupted()) {
1975                             return 0;
1976                         }
1977                         Map<String, Long> map = staledFibEntriesMap.get(rd);
1978                         if (map != null) {
1979                             for (String key : map.keySet()) {
1980                                 if (Thread.interrupted()) {
1981                                     return 0;
1982                                 }
1983                                 String prefix = extractPrefix(key);
1984                                 String nextHop = extractNextHop(key);
1985                                 totalCleared++;
1986                                 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
1987                                         rd, prefix, nextHop);
1988                                 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
1989                             }
1990                         }
1991                     }
1992                 }
1993             } finally {
1994                 staledFibEntriesMap.clear();
1995             }
1996             LOG.error("cleared {} stale routes after bgp restart", totalCleared);
1997             return 0;
1998         }
1999     }
2000
2001     /*
2002      * BGP restart scenario, ODL-BGP manager was/is running.
2003      * On re-sync notification, Get a copy of FIB database.
2004      */
2005     public static void createStaleFibMap() {
2006         totalStaledCount = 0;
2007         try {
2008             /*
2009             * at the time Stale FIB creation, Wait till all PENDING write transaction
2010              * to complete (or)wait for max timeout value of STALE_FIB_WAIT Seconds.
2011              */
2012             int retry = STALE_FIB_WAIT;
2013             while ((BgpUtil.getGetPendingWrTransaction() != 0) && (retry > 0)) {
2014                 Thread.sleep(1000);
2015                 retry--;
2016                 if (retry == 0) {
2017                     LOG.error("TimeOut occured {} seconds, in waiting stale fibDSWriter create", STALE_FIB_WAIT);
2018                 }
2019             }
2020             staledFibEntriesMap.clear();
2021             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2022             DataBroker db = BgpUtil.getBroker();
2023             if (db == null) {
2024                 LOG.error("Couldn't find BgpUtil dataBroker while creating createStaleFibMap");
2025                 return;
2026             }
2027
2028             Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(BgpUtil.getBroker(),
2029                     LogicalDatastoreType.CONFIGURATION, id);
2030             if (fibEntries.isPresent()) {
2031                 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2032                 for (VrfTables vrfTable : staleVrfTables) {
2033                     Map<String, Long> staleFibEntMap = new HashMap<>();
2034                     for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2035                         if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2036                             //Stale marking and cleanup is only meant for the routes learned through BGP.
2037                             continue;
2038                         }
2039                         if (Thread.interrupted()) {
2040                             break;
2041                         }
2042                         totalStaledCount++;
2043                         //Create MAP from staleVrfTables.
2044                         vrfEntry.getRoutePaths()
2045                                 .forEach(
2046                                     routePath -> staleFibEntMap.put(
2047                                             appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2048                                                     routePath.getNexthopAddress()), routePath.getLabel()));
2049                     }
2050                     staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2051                 }
2052             } else {
2053                 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2054             }
2055         } catch (InterruptedException | ReadFailedException e) {
2056             LOG.error("createStaleFibMap:: error ", e);
2057         }
2058         LOG.error("created {} staled entries ", totalStaledCount);
2059     }
2060
2061     //map<rd, map<prefix/len:nexthop, label>>
2062     public static Map<String, Map<String, Long>> getStaledFibEntriesMap() {
2063         return staledFibEntriesMap;
2064     }
2065
2066     //TODO: below function is for testing purpose with cli
2067     public static void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
2068         LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
2069         fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
2070     }
2071
2072     public boolean isBgpConnected() {
2073         return bgpRouter.isBgpConnected();
2074     }
2075
2076     public long getLastConnectedTS() {
2077         return bgpRouter.getLastConnectedTS();
2078     }
2079
2080     public long getConnectTS() {
2081         return bgpRouter.getConnectTS();
2082     }
2083
2084     public long getStartTS() {
2085         return bgpRouter.getStartTS();
2086     }
2087
2088     public static int getTotalStaledCount() {
2089         return totalStaledCount;
2090     }
2091
2092     public static int getTotalCleared() {
2093         return totalCleared;
2094     }
2095
2096     public Timer getBgpCountersTimer() {
2097         return bgpCountersTimer;
2098     }
2099
2100     public BgpCounters getBgpCounters() {
2101         return bgpCounters;
2102     }
2103
2104     public void setBgpCountersTimer(Timer timer) {
2105         bgpCountersTimer = timer;
2106     }
2107
2108     public void setBgpAlarmsTimer(Timer timer) {
2109         bgpAlarmsTimer = timer;
2110     }
2111
2112     public void startBgpCountersTask() {
2113         if (getBgpCounters() == null) {
2114             bgpCounters = new BgpCounters(bgpConfigurationManager.getBgpSdncMipIp());
2115             setBgpCountersTimer(new Timer(true));
2116             getBgpCountersTimer().scheduleAtFixedRate(bgpCounters, 0, 120 * 1000);
2117             LOG.info("Bgp Counters task scheduled for every two minutes.");
2118
2119             bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2120         }
2121     }
2122
2123     public void stopBgpCountersTask() {
2124         Timer timer = getBgpCountersTimer();
2125         if (getBgpCounters() != null) {
2126             timer.cancel();
2127             setBgpCountersTimer(null);
2128             bgpCounters = null;
2129         }
2130     }
2131
2132     public void startBgpAlarmsTask() {
2133         if (getBgpAlarms() == null) {
2134             bgpAlarms = new BgpAlarms(this);
2135             setBgpAlarmsTimer(new Timer(true));
2136             getBgpAlarmsTimer().scheduleAtFixedRate(bgpAlarms, 0, 60 * 1000);
2137             LOG.info("Bgp Alarms task scheduled for every minute.");
2138         }
2139     }
2140
2141     public void stopBgpAlarmsTask() {
2142         Timer timer = getBgpAlarmsTimer();
2143         if (getBgpAlarms() != null) {
2144             timer.cancel();
2145             setBgpAlarmsTimer(null);
2146             bgpAlarms = null;
2147         }
2148     }
2149
2150     public Timer getBgpAlarmsTimer() {
2151         return bgpAlarmsTimer;
2152     }
2153
2154     public BgpAlarms getBgpAlarms() {
2155         return bgpAlarms;
2156     }
2157
2158     private static String appendNextHopToPrefix(String prefix, String nextHop) {
2159         return prefix + ":" + nextHop;
2160     }
2161
2162     private static String extractPrefix(String prefixNextHop) {
2163         return prefixNextHop.split(":")[0];
2164     }
2165
2166     private static String extractNextHop(String prefixNextHop) {
2167         return prefixNextHop.split(":")[1];
2168     }
2169 }