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