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