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