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