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