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