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