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