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