2 * Copyright © 2015, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.bgpmanager;
10 import com.google.common.base.Optional;
11 import io.netty.util.concurrent.GlobalEventExecutor;
12 import java.io.BufferedReader;
14 import java.io.FileNotFoundException;
15 import java.io.FileReader;
16 import java.io.IOException;
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.InvocationTargetException;
19 import java.net.InetAddress;
20 import java.net.NetworkInterface;
21 import java.net.SocketException;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
28 import java.util.Timer;
29 import java.util.TimerTask;
30 import java.util.concurrent.Callable;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.concurrent.CountDownLatch;
33 import java.util.concurrent.ExecutionException;
34 import java.util.concurrent.ExecutorService;
35 import java.util.concurrent.Executors;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.ScheduledExecutorService;
38 import java.util.concurrent.TimeoutException;
39 import java.util.concurrent.atomic.AtomicBoolean;
40 import java.util.concurrent.atomic.AtomicInteger;
41 import javax.annotation.Nullable;
44 import org.apache.thrift.TException;
45 import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
46 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
47 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
48 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
49 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
50 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
51 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
52 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
53 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
54 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
55 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.utils.batching.DefaultBatchHandler;
58 import org.opendaylight.genius.utils.clustering.EntityOwnerUtils;
59 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
60 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
61 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
62 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
63 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
64 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
65 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
66 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
67 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
68 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
69 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
70 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
71 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
72 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
73 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
74 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
75 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
76 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
77 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
78 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
79 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
80 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
81 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
82 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
83 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
84 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
85 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
86 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
87 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
88 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
89 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Multipath;
90 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathBuilder;
91 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathKey;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpath;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathBuilder;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathKey;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
102 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
103 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
104 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
105 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
107 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
108 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
109 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
110 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
111 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
112 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOption;
113 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
114 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
115 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
120 import org.opendaylight.yangtools.concepts.ListenerRegistration;
121 import org.opendaylight.yangtools.yang.binding.DataObject;
122 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
123 import org.osgi.framework.BundleContext;
124 import org.slf4j.Logger;
125 import org.slf4j.LoggerFactory;
129 public class BgpConfigurationManager {
130 private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
131 private static DataBroker dataBroker;
132 private static FibDSWriter fibDSWriter;
133 public static IBgpManager bgpManager;
134 private static IVpnLinkService vpnLinkService;
135 private final BundleContext bundleContext;
136 private static Bgp config;
137 private static BgpRouter bgpRouter;
138 private static BgpThriftService updateServer;
139 private BgpCounters bgpCounters;
140 private BgpAlarms bgpAlarms;
141 private Timer bgpCountersTimer;
142 private Timer bgpAlarmsTimer;
143 private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
144 private static final String DEF_LOGLEVEL = "errors";
145 private static final String UPDATE_PORT = "bgp.thrift.service.port";
146 private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
147 private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
148 private static final String DEF_UPORT = "6644";
149 private static final String DEF_CHOST = "127.0.0.1";
150 private static final String DEF_CPORT = "7644";
151 private static final String DEF_SDNC_BGP_MIP = "127.0.0.1";
152 private static final String DEF_BGP_SDNC_MIP = "127.0.0.1";
153 private static final String SDNC_BGP_MIP = "vpnservice.bgp.thrift.bgp.mip";
154 private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.sdnc.mip";
155 private static final String CLUSTER_CONF_FILE = "/cluster/etc/cluster.conf";
156 private static final Timer IP_ACTIVATION_CHECK_TIMER = new Timer();
157 private static final int STALE_FIB_WAIT = 60;
158 private static final int RESTART_DEFAULT_GR = 90;
159 private long staleStartTime = 0;
160 private long staleEndTime = 0;
161 private long cfgReplayStartTime = 0;
162 private long cfgReplayEndTime = 0;
163 private long staleCleanupTime = 0;
164 private static final int DS_RETRY_COOUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
165 private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
167 public String getBgpSdncMipIp() {
168 return getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
171 public long getStaleCleanupTime() {
172 return staleCleanupTime;
175 public void setStaleCleanupTime(long staleCleanupTime) {
176 this.staleCleanupTime = staleCleanupTime;
179 public long getCfgReplayEndTime() {
180 return cfgReplayEndTime;
183 public void setCfgReplayEndTime(long cfgReplayEndTime) {
184 this.cfgReplayEndTime = cfgReplayEndTime;
187 public long getCfgReplayStartTime() {
188 return cfgReplayStartTime;
191 public void setCfgReplayStartTime(long cfgReplayStartTime) {
192 this.cfgReplayStartTime = cfgReplayStartTime;
195 public long getStaleEndTime() {
199 public void setStaleEndTime(long staleEndTime) {
200 this.staleEndTime = staleEndTime;
203 public long getStaleStartTime() {
204 return staleStartTime;
207 public void setStaleStartTime(long staleStartTime) {
208 this.staleStartTime = staleStartTime;
212 // to have stale FIB map (RD, Prefix)
213 // number of seconds wait for route sync-up between ODL and BGP
214 private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
216 static String odlThriftIp = "127.0.0.1";
217 static String bgpThriftIp = "127.0.0.1";
218 private static String cHostStartup;
219 private static String cPortStartup;
220 private static CountDownLatch initer = new CountDownLatch(1);
221 //static IITMProvider itmProvider;
222 //map<rd, map<prefix/len:nexthop, label>>
223 private static Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
225 static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
226 static final String BGP_ENTITY_NAME = "bgp";
228 static int totalStaledCount = 0;
229 static int totalCleared = 0;
230 static int totalExternalRoutes = 0;
232 private static final Class[] REACTORS = {
233 ConfigServerReactor.class, AsIdReactor.class,
234 GracefulRestartReactor.class, LoggingReactor.class,
235 NeighborsReactor.class, UpdateSourceReactor.class,
236 EbgpMultihopReactor.class, AddressFamiliesReactor.class,
237 NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
238 MultipathReactor.class, VrfMaxpathReactor.class
241 private ListenerRegistration<DataChangeListener>[] registrations;
243 final BgpConfigurationManager bgpConfigurationManager;
245 public BgpConfigurationManager(final DataBroker dataBroker,
246 final EntityOwnershipService entityOwnershipService,
247 final FibDSWriter fibDSWriter,
248 final IVpnLinkService vpnLinkSrvce,
249 final BundleContext bundleContext)
250 throws InterruptedException, ExecutionException, TimeoutException {
251 BgpConfigurationManager.dataBroker = dataBroker;
252 BgpConfigurationManager.fibDSWriter = fibDSWriter;
253 BgpConfigurationManager.vpnLinkService = vpnLinkService;
254 this.bundleContext = bundleContext;
255 String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
256 cHostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
257 cPortStartup = getProperty(CONFIG_PORT, DEF_CPORT);
258 LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
259 + cHostStartup + ":" + cPortStartup);
260 VtyshCli.setHostAddr(cHostStartup);
261 ClearBgpCli.setHostAddr(cHostStartup);
262 setEntityOwnershipService(entityOwnershipService);
263 bgpRouter = BgpRouter.getInstance();
264 odlThriftIp = getProperty(SDNC_BGP_MIP, DEF_SDNC_BGP_MIP);
265 bgpThriftIp = getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
268 LOG.info("BGP Configuration manager initialized");
271 bgpConfigurationManager = this;
272 BgpUtil.batchSize = BgpUtil.BATCH_SIZE;
273 if (Integer.getInteger("batch.size") != null) {
274 BgpUtil.batchSize = Integer.getInteger("batch.size");
276 BgpUtil.batchInterval = BgpUtil.PERIODICITY;
277 if (Integer.getInteger("batch.wait.time") != null) {
278 BgpUtil.batchInterval = Integer.getInteger("batch.wait.time");
280 BgpUtil.registerWithBatchManager(
281 new DefaultBatchHandler(dataBroker, LogicalDatastoreType.CONFIGURATION, BgpUtil.batchSize,
282 BgpUtil.batchInterval));
284 GlobalEventExecutor.INSTANCE.execute(() -> {
285 final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
286 IBgpManager.class, bundleContext);
287 bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
288 updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, fibDSWriter);
289 updateServer.start();
290 LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
294 private Object createListener(Class<?> cls) {
299 ctor = cls.getConstructor(BgpConfigurationManager.class);
300 obj = ctor.newInstance(this);
301 } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
303 LOG.error("Failed to create listener object", e);
308 private void registerCallbacks() {
309 String emsg = "Failed to register listener";
310 registrations = new ListenerRegistration[REACTORS.length];
311 InstanceIdentifier<?> iid = InstanceIdentifier.create(Bgp.class);
312 for (Class reactor : REACTORS) {
313 Object obj = createListener(reactor);
314 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
315 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
319 public void close() {
320 if (updateServer != null) {
323 LOG.info("{} close", getClass().getSimpleName());
326 private boolean configExists() throws ReadFailedException {
327 InstanceIdentifier.InstanceIdentifierBuilder<Bgp> iib =
328 InstanceIdentifier.builder(Bgp.class);
329 InstanceIdentifier<Bgp> iid = iib.build();
330 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
334 private String getProperty(String var, String def) {
335 String property = bundleContext.getProperty(var);
336 return (property == null ? def : property);
339 boolean ignoreClusterDcnEventForFollower() {
340 return !EntityOwnerUtils.amIEntityOwner(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME);
344 config = getConfig();
348 public void setEntityOwnershipService(final EntityOwnershipService entityOwnershipService) {
350 EntityOwnerUtils.registerEntityCandidateForOwnerShip(entityOwnershipService,
351 BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME, ownershipChange -> {
352 LOG.trace("entity owner change event fired");
353 if (ownershipChange.hasOwner() && ownershipChange.isOwner()) {
354 LOG.trace("This PL is the Owner");
358 LOG.info("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.hasOwner(),
359 ownershipChange.isOwner());
362 } catch (CandidateAlreadyRegisteredException e) {
363 LOG.error("failed to register bgp entity", e);
367 private static final String ADD_WARN =
368 "Config store updated; undo with Delete if needed.";
369 private static final String DEL_WARN =
370 "Config store updated; undo with Add if needed.";
371 private static final String UPD_WARN =
372 "Update operation not supported; Config store updated;"
373 + " restore with another Update if needed.";
375 public class ConfigServerReactor
376 extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
377 implements AutoCloseable, ClusteredDataTreeChangeListener<ConfigServer> {
378 private static final String YANG_OBJ = "config-server ";
380 public ConfigServerReactor() {
381 super(ConfigServer.class, ConfigServerReactor.class);
385 protected synchronized void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
386 LOG.trace("received bgp connect config host {}", val.getHost().getValue());
387 if (ignoreClusterDcnEventForFollower()) {
393 } catch (InterruptedException e) {
396 LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
397 synchronized (BgpConfigurationManager.this) {
398 boolean res = bgpRouter.connect(val.getHost().getValue(),
399 val.getPort().intValue());
401 LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
407 protected ConfigServerReactor getDataTreeChangeListener() {
408 return ConfigServerReactor.this;
412 protected InstanceIdentifier<ConfigServer> getWildCardPath() {
413 return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
417 protected synchronized void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
418 LOG.trace("received bgp disconnect");
419 if (ignoreClusterDcnEventForFollower()) {
422 synchronized (BgpConfigurationManager.this) {
423 bgpRouter.disconnect();
428 protected void update(InstanceIdentifier<ConfigServer> iid,
429 ConfigServer oldval, ConfigServer newval) {
430 LOG.trace("received bgp Connection update");
431 if (ignoreClusterDcnEventForFollower()) {
434 LOG.error(YANG_OBJ + UPD_WARN);
438 private BgpRouter getClient(String yangObj) {
439 if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
440 LOG.warn("{}: configuration received when BGP is inactive", yangObj);
446 public class AsIdReactor
447 extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
448 implements AutoCloseable, ClusteredDataTreeChangeListener<AsId> {
450 private static final String YANG_OBJ = "as-id ";
452 public AsIdReactor() {
453 super(AsId.class, AsIdReactor.class);
457 protected synchronized void add(InstanceIdentifier<AsId> iid, AsId val) {
458 LOG.error("received bgp add asid {}", val);
459 if (ignoreClusterDcnEventForFollower()) {
462 LOG.debug("received add router config asNum {}", val.getLocalAs());
463 synchronized (BgpConfigurationManager.this) {
464 BgpRouter br = getClient(YANG_OBJ);
466 LOG.error("{} Unable to process add for asNum {}; {}", YANG_OBJ, val.getLocalAs(),
467 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
470 if (isIpAvailable(odlThriftIp)) {
473 IP_ACTIVATION_CHECK_TIMER.scheduleAtFixedRate(new TimerTask() {
476 if (isIpAvailable(odlThriftIp)) {
478 IP_ACTIVATION_CHECK_TIMER.cancel();
480 LOG.trace("waiting for odlThriftIP: {} to be present", odlThriftIp);
485 if (getBgpCounters() == null) {
486 startBgpCountersTask();
488 if (getBgpAlarms() == null) {
489 startBgpAlarmsTask();
495 protected AsIdReactor getDataTreeChangeListener() {
496 return AsIdReactor.this;
500 protected InstanceIdentifier<AsId> getWildCardPath() {
501 return InstanceIdentifier.create(Bgp.class).child(AsId.class);
505 protected synchronized void remove(InstanceIdentifier<AsId> iid, AsId val) {
506 LOG.error("received delete router config asNum {}", val.getLocalAs());
507 if (ignoreClusterDcnEventForFollower()) {
510 synchronized (BgpConfigurationManager.this) {
511 long asNum = val.getLocalAs();
512 BgpRouter br = getClient(YANG_OBJ);
514 LOG.error("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
515 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
520 } catch (TException | BgpRouterException e) {
521 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
523 if (getBgpCounters() != null) {
524 stopBgpCountersTask();
526 if (getBgpAlarms() != null) {
529 Bgp conf = getConfig();
531 LOG.error("Config Null while removing the as-id");
534 LOG.debug("Removing external routes from FIB");
535 deleteExternalFibRoutes();
536 List<Neighbors> nbrs = conf.getNeighbors();
537 if (nbrs != null && nbrs.size() > 0) {
538 LOG.error("Tring to remove the as-id when neighbor config is already present");
539 for (Neighbors nbr : nbrs) {
540 LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
541 delNeighbor(nbr.getAddress().getValue());
548 protected void update(InstanceIdentifier<AsId> iid,
549 AsId oldval, AsId newval) {
550 if (ignoreClusterDcnEventForFollower()) {
553 LOG.error(YANG_OBJ + UPD_WARN);
557 public class GracefulRestartReactor
558 extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
559 implements AutoCloseable, ClusteredDataTreeChangeListener<GracefulRestart> {
561 private static final String YANG_OBJ = "graceful-restart ";
563 public GracefulRestartReactor() {
564 super(GracefulRestart.class, GracefulRestartReactor.class);
568 protected synchronized void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
569 if (ignoreClusterDcnEventForFollower()) {
572 synchronized (BgpConfigurationManager.this) {
573 int stalePathTime = val.getStalepathTime().intValue();
574 BgpRouter br = getClient(YANG_OBJ);
576 LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
577 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
581 br.addGracefulRestart(stalePathTime);
582 } catch (TException | BgpRouterException e) {
583 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
589 protected GracefulRestartReactor getDataTreeChangeListener() {
590 return GracefulRestartReactor.this;
594 protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
595 return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
599 protected synchronized void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
600 if (ignoreClusterDcnEventForFollower()) {
603 LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
604 synchronized (BgpConfigurationManager.this) {
605 BgpRouter br = getClient(YANG_OBJ);
607 LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
608 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
612 br.delGracefulRestart();
613 } catch (TException | BgpRouterException e) {
614 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
620 protected void update(InstanceIdentifier<GracefulRestart> iid,
621 GracefulRestart oldval, GracefulRestart newval) {
622 if (ignoreClusterDcnEventForFollower()) {
625 LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
626 synchronized (BgpConfigurationManager.this) {
627 int stalePathTime = newval.getStalepathTime().intValue();
628 BgpRouter br = getClient(YANG_OBJ);
630 LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
631 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
635 br.addGracefulRestart(stalePathTime);
636 } catch (TException | BgpRouterException e) {
637 LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
643 public class LoggingReactor
644 extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
645 implements AutoCloseable, ClusteredDataTreeChangeListener<Logging> {
647 private static final String YANG_OBJ = "logging ";
649 public LoggingReactor() {
650 super(Logging.class, LoggingReactor.class);
654 protected synchronized void add(InstanceIdentifier<Logging> iid, Logging val) {
655 if (ignoreClusterDcnEventForFollower()) {
658 synchronized (BgpConfigurationManager.this) {
659 BgpRouter br = getClient(YANG_OBJ);
661 LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
662 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
666 br.setLogging(val.getFile(), val.getLevel());
667 } catch (TException | BgpRouterException e) {
668 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
674 protected LoggingReactor getDataTreeChangeListener() {
675 return LoggingReactor.this;
679 protected InstanceIdentifier<Logging> getWildCardPath() {
680 return InstanceIdentifier.create(Bgp.class).child(Logging.class);
684 protected synchronized void remove(InstanceIdentifier<Logging> iid, Logging val) {
685 if (ignoreClusterDcnEventForFollower()) {
688 LOG.debug("received remove Logging config val {}", val.getLevel());
689 synchronized (BgpConfigurationManager.this) {
690 BgpRouter br = getClient(YANG_OBJ);
692 LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
693 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
697 br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
698 } catch (TException | BgpRouterException e) {
699 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
705 protected void update(InstanceIdentifier<Logging> iid,
706 Logging oldval, Logging newval) {
707 if (ignoreClusterDcnEventForFollower()) {
710 synchronized (BgpConfigurationManager.this) {
711 BgpRouter br = getClient(YANG_OBJ);
713 LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
714 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
718 br.setLogging(newval.getFile(), newval.getLevel());
719 } catch (TException | BgpRouterException e) {
720 LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
726 public class NeighborsReactor
727 extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
728 implements AutoCloseable, ClusteredDataTreeChangeListener<Neighbors> {
730 private static final String YANG_OBJ = "neighbors ";
732 public NeighborsReactor() {
733 super(Neighbors.class, NeighborsReactor.class);
737 protected synchronized void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
738 if (ignoreClusterDcnEventForFollower()) {
741 LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
742 synchronized (BgpConfigurationManager.this) {
743 String peerIp = val.getAddress().getValue();
744 long as = val.getRemoteAs();
745 final String md5Secret = extractMd5Secret(val);
746 BgpRouter br = getClient(YANG_OBJ);
748 LOG.error("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
749 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
753 //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
754 br.addNeighbor(peerIp, as, md5Secret);
756 } catch (TException | BgpRouterException e) {
757 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
763 protected NeighborsReactor getDataTreeChangeListener() {
764 return NeighborsReactor.this;
768 protected InstanceIdentifier<Neighbors> getWildCardPath() {
769 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
773 protected synchronized void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
774 if (ignoreClusterDcnEventForFollower()) {
777 LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
778 synchronized (BgpConfigurationManager.this) {
779 String peerIp = val.getAddress().getValue();
780 BgpRouter br = getClient(YANG_OBJ);
782 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
783 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
787 //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
788 br.delNeighbor(peerIp);
789 } catch (TException | BgpRouterException e) {
790 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
796 protected void update(InstanceIdentifier<Neighbors> iid,
797 Neighbors oldval, Neighbors newval) {
798 if (ignoreClusterDcnEventForFollower()) {
801 //purposefully nothing to do.
805 public class EbgpMultihopReactor
806 extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
807 implements AutoCloseable, ClusteredDataTreeChangeListener<EbgpMultihop> {
809 private static final String YANG_OBJ = "ebgp-multihop ";
811 public EbgpMultihopReactor() {
812 super(EbgpMultihop.class, EbgpMultihopReactor.class);
816 protected synchronized void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
817 if (ignoreClusterDcnEventForFollower()) {
820 LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
821 synchronized (BgpConfigurationManager.this) {
822 String peerIp = val.getPeerIp().getValue();
823 BgpRouter br = getClient(YANG_OBJ);
825 LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
826 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
830 br.addEbgpMultihop(peerIp, val.getNhops().intValue());
831 } catch (TException | BgpRouterException e) {
832 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
838 protected EbgpMultihopReactor getDataTreeChangeListener() {
839 return EbgpMultihopReactor.this;
843 protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
844 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
848 protected synchronized void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
849 if (ignoreClusterDcnEventForFollower()) {
852 LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
853 synchronized (BgpConfigurationManager.this) {
854 String peerIp = val.getPeerIp().getValue();
855 BgpRouter br = getClient(YANG_OBJ);
857 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
858 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
862 br.delEbgpMultihop(peerIp);
863 } catch (TException | BgpRouterException e) {
864 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
870 protected void update(InstanceIdentifier<EbgpMultihop> iid,
871 EbgpMultihop oldval, EbgpMultihop newval) {
872 if (ignoreClusterDcnEventForFollower()) {
875 LOG.error(YANG_OBJ + UPD_WARN);
879 public class UpdateSourceReactor
880 extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
881 implements AutoCloseable, ClusteredDataTreeChangeListener<UpdateSource> {
883 private static final String YANG_OBJ = "update-source ";
885 public UpdateSourceReactor() {
886 super(UpdateSource.class, UpdateSourceReactor.class);
890 protected synchronized void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
891 if (ignoreClusterDcnEventForFollower()) {
894 LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
895 synchronized (BgpConfigurationManager.this) {
896 String peerIp = val.getPeerIp().getValue();
897 BgpRouter br = getClient(YANG_OBJ);
899 LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
900 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
904 br.addUpdateSource(peerIp, val.getSourceIp().getValue());
905 } catch (TException | BgpRouterException e) {
906 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
912 protected UpdateSourceReactor getDataTreeChangeListener() {
913 return UpdateSourceReactor.this;
917 protected InstanceIdentifier<UpdateSource> getWildCardPath() {
918 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
922 protected synchronized void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
923 if (ignoreClusterDcnEventForFollower()) {
926 LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
927 synchronized (BgpConfigurationManager.this) {
928 String peerIp = val.getPeerIp().getValue();
929 BgpRouter br = getClient(YANG_OBJ);
931 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
932 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
936 br.delUpdateSource(peerIp);
937 } catch (TException | BgpRouterException e) {
938 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
944 protected void update(InstanceIdentifier<UpdateSource> iid,
945 UpdateSource oldval, UpdateSource newval) {
946 if (ignoreClusterDcnEventForFollower()) {
949 LOG.error(YANG_OBJ + UPD_WARN);
953 public class AddressFamiliesReactor
954 extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
955 implements AutoCloseable, ClusteredDataTreeChangeListener<AddressFamilies> {
957 private static final String YANG_OBJ = "address-families ";
959 public AddressFamiliesReactor() {
960 super(AddressFamilies.class, AddressFamiliesReactor.class);
964 protected synchronized void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
965 if (ignoreClusterDcnEventForFollower()) {
968 LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
969 synchronized (BgpConfigurationManager.this) {
970 String peerIp = val.getPeerIp().getValue();
971 BgpRouter br = getClient(YANG_OBJ);
973 LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
974 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
977 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
978 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
980 br.addAddressFamily(peerIp, afi, safi);
981 } catch (TException | BgpRouterException e) {
982 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
988 protected AddressFamiliesReactor getDataTreeChangeListener() {
989 return AddressFamiliesReactor.this;
993 protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
994 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
998 protected synchronized void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
999 if (ignoreClusterDcnEventForFollower()) {
1002 LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
1003 synchronized (BgpConfigurationManager.this) {
1004 String peerIp = val.getPeerIp().getValue();
1005 BgpRouter br = getClient(YANG_OBJ);
1007 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
1008 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1011 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1012 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1014 br.delAddressFamily(peerIp, afi, safi);
1015 } catch (TException | BgpRouterException e) {
1016 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1022 protected void update(InstanceIdentifier<AddressFamilies> iid,
1023 AddressFamilies oldval, AddressFamilies newval) {
1024 if (ignoreClusterDcnEventForFollower()) {
1027 LOG.error(YANG_OBJ + UPD_WARN);
1031 public class NetworksReactor
1032 extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1033 implements AutoCloseable, ClusteredDataTreeChangeListener<Networks> {
1035 private static final String YANG_OBJ = "networks ";
1037 public NetworksReactor() {
1038 super(Networks.class, NetworksReactor.class);
1042 public NetworksReactor getDataTreeChangeListener() {
1043 return NetworksReactor.this;
1047 protected synchronized void add(InstanceIdentifier<Networks> iid, Networks val) {
1048 if (ignoreClusterDcnEventForFollower()) {
1051 LOG.debug("received add Networks config val {}", val.getPrefixLen());
1052 synchronized (BgpConfigurationManager.this) {
1053 String rd = val.getRd();
1054 String pfxlen = val.getPrefixLen();
1055 String nh = val.getNexthop().getValue();
1056 BgpRouter br = getClient(YANG_OBJ);
1058 LOG.error("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
1059 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1062 Long label = val.getLabel();
1063 int lbl = (label == null) ? qbgpConstants.LBL_NO_LABEL
1065 int l3vni = (val.getL3vni() == null) ? qbgpConstants.LBL_NO_LABEL
1066 : val.getL3vni().intValue();
1068 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1069 int ethernetTag = val.getEthtag().intValue();
1070 String esi = val.getEsi();
1071 String macaddress = val.getMacaddress();
1072 EncapType encapType = val.getEncapType();
1073 String routerMac = val.getRoutermac();
1074 int afiInt = testValueAFI(pfxlen);
1077 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
1078 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType),
1080 } catch (TException | BgpRouterException e) {
1081 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1087 protected InstanceIdentifier<Networks> getWildCardPath() {
1088 return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1092 protected synchronized void remove(InstanceIdentifier<Networks> iid, Networks val) {
1093 if (ignoreClusterDcnEventForFollower()) {
1096 LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1097 synchronized (BgpConfigurationManager.this) {
1098 String rd = val.getRd();
1099 String pfxlen = val.getPrefixLen();
1100 BgpRouter br = getClient(YANG_OBJ);
1102 LOG.error("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
1103 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1106 Long label = val.getLabel();
1107 int lbl = (label == null) ? 0 : label.intValue();
1108 int afiInt = testValueAFI(pfxlen);
1109 if (rd == null && lbl > 0) {
1110 //LU prefix is being deleted.
1111 rd = Integer.toString(lbl);
1114 br.delPrefix(rd, pfxlen);
1115 } catch (TException | BgpRouterException e) {
1116 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1121 /**get the value AFI from a prefix as "x.x.x.x/x".
1123 * @param pfxlen the prefix to get an afi
1124 * @return the afi value as you are need
1126 public int testValueAFI(String pfxlen) {
1127 int afiNew = af_afi.AFI_IP.getValue();
1129 String ipOnly = pfxlen.substring(0, pfxlen.lastIndexOf("/"));
1130 java.net.Inet6Address.getByName(ipOnly);
1131 afiNew = af_afi.AFI_IPV6.getValue();
1132 } catch (java.net.UnknownHostException e) {
1133 //ce n'est pas de l'ipv6
1140 protected void update(final InstanceIdentifier<Networks> iid,
1141 final Networks oldval, final Networks newval) {
1142 if (ignoreClusterDcnEventForFollower()) {
1145 if (oldval.equals(newval)) {
1146 //Update: OLD and New values are same, no need to trigger remove/add.
1147 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1148 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1151 LOG.debug("received update networks config val {}", newval.getPrefixLen());
1152 remove(iid, oldval);
1153 timer.schedule(new TimerTask() {
1158 }, Integer.getInteger("bgp.nexthop.update.delay.in.secs", 5) * 1000);
1162 static Timer timer = new Timer();
1164 public class VrfsReactor
1165 extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1166 implements AutoCloseable, ClusteredDataTreeChangeListener<Vrfs> {
1168 private static final String YANG_OBJ = "vrfs ";
1170 public VrfsReactor() {
1171 super(Vrfs.class, VrfsReactor.class);
1175 protected synchronized void add(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1176 if (ignoreClusterDcnEventForFollower()) {
1179 LOG.debug("received add Vrfs config val {}", val.getRd());
1180 synchronized (BgpConfigurationManager.this) {
1181 String rd = val.getRd();
1182 BgpRouter br = getClient(YANG_OBJ);
1184 LOG.error("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1185 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1189 br.addVrf(val.getLayerType(), rd, val.getImportRts(),
1190 val.getExportRts());
1191 } catch (TException | BgpRouterException e) {
1192 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1198 protected VrfsReactor getDataTreeChangeListener() {
1199 return VrfsReactor.this;
1203 protected InstanceIdentifier<Vrfs> getWildCardPath() {
1204 return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1208 protected synchronized void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1209 if (ignoreClusterDcnEventForFollower()) {
1212 LOG.debug("received remove Vrfs config val {}", val.getRd());
1213 synchronized (BgpConfigurationManager.this) {
1214 String rd = val.getRd();
1215 BgpRouter br = getClient(YANG_OBJ);
1217 LOG.error("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
1218 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1223 } catch (TException | BgpRouterException e) {
1224 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1230 protected void update(InstanceIdentifier<Vrfs> iid,
1231 Vrfs oldval, Vrfs newval) {
1232 if (ignoreClusterDcnEventForFollower()) {
1235 LOG.debug("VRFS: Update getting triggered for VRFS rd {}", oldval.getRd());
1236 LOG.error(YANG_OBJ + UPD_WARN);
1240 Future lastCleanupJob;
1241 Future lastReplayJobFt = null;
1243 protected void activateMIP() {
1245 LOG.trace("BgpReactor: Executing MIP Activate command");
1246 Process processBgp = Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1247 Process processOs = Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1248 LOG.trace("bgpMIP Activated");
1250 } catch (IOException io) {
1251 LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1255 AtomicBoolean started = new AtomicBoolean(false);
1257 public class BgpReactor
1258 extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1259 implements AutoCloseable, ClusteredDataTreeChangeListener<Bgp> {
1261 private static final String YANG_OBJ = "Bgp ";
1263 public BgpReactor() {
1264 super(Bgp.class, BgpReactor.class);
1269 protected synchronized void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1270 LOG.error("received add Bgp config");
1274 } catch (InterruptedException e) {
1277 synchronized (BgpConfigurationManager.this) {
1279 if (ignoreClusterDcnEventForFollower()) {
1287 protected BgpReactor getDataTreeChangeListener() {
1288 return BgpReactor.this;
1292 protected InstanceIdentifier<Bgp> getWildCardPath() {
1293 return InstanceIdentifier.create(Bgp.class);
1297 protected synchronized void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1298 if (ignoreClusterDcnEventForFollower()) {
1301 LOG.debug("received remove Bgp config");
1302 synchronized (BgpConfigurationManager.this) {
1308 protected void update(InstanceIdentifier<Bgp> iid,
1309 Bgp oldval, Bgp newval) {
1310 if (ignoreClusterDcnEventForFollower()) {
1313 synchronized (BgpConfigurationManager.this) {
1319 @SuppressWarnings("deprecation")
1320 public class MultipathReactor
1321 extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1322 implements AutoCloseable, ClusteredDataTreeChangeListener<Multipath> {
1324 private static final String YANG_OBJ = "multipath ";
1326 public MultipathReactor() {
1327 super(Multipath.class, MultipathReactor.class);
1332 protected MultipathReactor getDataTreeChangeListener() {
1333 return MultipathReactor.this;
1337 protected InstanceIdentifier<Multipath> getWildCardPath() {
1338 return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
1342 protected synchronized void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1343 ExecutorService executor = Executors.newSingleThreadExecutor();
1344 executor.submit(new MultipathStatusChange(val));
1345 executor.shutdown();
1349 protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1350 ExecutorService executor = Executors.newSingleThreadExecutor();
1351 executor.submit(new MultipathStatusChange(newval));
1352 executor.shutdown();
1356 protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1357 ExecutorService executor = Executors.newSingleThreadExecutor();
1358 executor.submit(new MultipathStatusChange(dataObjectModification));
1359 executor.shutdown();
1362 class MultipathStatusChange implements Callable<Void> {
1364 Multipath multipath;
1366 MultipathStatusChange(Multipath multipath) {
1367 this.multipath = multipath;
1371 public Void call() throws Exception {
1372 if (!ignoreClusterDcnEventForFollower()) {
1373 synchronized (BgpConfigurationManager.this) {
1375 BgpRouter br = getClient(YANG_OBJ);
1378 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1379 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1382 if (multipath.isMultipathEnabled()) {
1383 br.enableMultipath(afi, safi);
1385 br.disableMultipath(afi, safi);
1387 } catch (TException | BgpRouterException e) {
1388 LOG.error(YANG_OBJ + " received exception: \"" + e + "\"");
1399 public void close() {
1404 @SuppressWarnings("deprecation")
1405 public class VrfMaxpathReactor
1406 extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1407 implements AutoCloseable, ClusteredDataTreeChangeListener<VrfMaxpath> {
1409 private static final String YANG_OBJ = "vrfMaxpath ";
1411 public VrfMaxpathReactor() {
1412 super(VrfMaxpath.class, VrfMaxpathReactor.class);
1417 protected VrfMaxpathReactor getDataTreeChangeListener() {
1418 return VrfMaxpathReactor.this;
1422 protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1423 return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
1426 class VrfMaxPathConfigurator implements Callable<Void> {
1428 VrfMaxpath vrfMaxpathVal;
1430 VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1431 this.vrfMaxpathVal = vrfMaxPathVal;
1435 public Void call() throws Exception {
1436 if (!ignoreClusterDcnEventForFollower()) {
1437 synchronized (BgpConfigurationManager.this) {
1438 BgpRouter br = getClient(YANG_OBJ);
1441 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
1442 LOG.debug("Maxpath for vrf: " + vrfMaxpathVal.getRd() + " : is "
1443 + vrfMaxpathVal.getMaxpaths());
1444 } catch (TException | BgpRouterException e) {
1446 + " received exception: \"" + e + "\"");
1456 protected synchronized void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1457 ExecutorService executor = Executors.newSingleThreadExecutor();
1458 executor.submit(new VrfMaxPathConfigurator(vrfMaxPathVal));
1459 executor.shutdown();
1463 protected void update(InstanceIdentifier<VrfMaxpath> iid,
1464 VrfMaxpath oldval, VrfMaxpath newval) {
1465 if (oldval.getMaxpaths() != newval.getMaxpaths()) {
1466 ExecutorService executor = Executors.newSingleThreadExecutor();
1467 executor.submit(new VrfMaxPathConfigurator(newval));
1468 executor.shutdown();
1473 protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1474 ExecutorService executor = Executors.newSingleThreadExecutor();
1475 executor.submit(new VrfMaxPathConfigurator(vrfMaxpathVal));
1476 executor.shutdown();
1480 public void close() {
1485 public String readThriftIpForCommunication(String mipAddr) {
1486 File file = new File(CLUSTER_CONF_FILE);
1487 if (!file.exists()) {
1491 try (BufferedReader br = new BufferedReader(new FileReader(file))) {
1493 while ((line = br.readLine()) != null) {
1494 if (line.contains(mipAddr)) {
1496 return line.substring(line.lastIndexOf(" ") + 1);
1499 } catch (FileNotFoundException e) {
1501 } catch (IOException e) {
1502 LOG.error("Error reading {}", CLUSTER_CONF_FILE, e);
1507 public boolean isIpAvailable(String odlip) {
1510 if (odlip != null) {
1511 if ("127.0.0.1".equals(odlip)) {
1514 Enumeration networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1515 while (networkInterfaceEnumeration.hasMoreElements()) {
1516 NetworkInterface networkInterface = (NetworkInterface) networkInterfaceEnumeration.nextElement();
1517 Enumeration inetAddressEnumeration = networkInterface.getInetAddresses();
1518 while (inetAddressEnumeration.hasMoreElements()) {
1519 InetAddress inetAddress = (InetAddress) inetAddressEnumeration.nextElement();
1520 if (odlip.equals(inetAddress.getHostAddress())) {
1526 } catch (SocketException e) {
1532 public static long getStalePathtime(int defValue, AsId asId) {
1535 spt = getConfig().getGracefulRestart().getStalepathTime();
1536 } catch (NullPointerException e) {
1538 spt = asId.getStalepathTime();
1539 LOG.trace("BGP config/Stale-path time is not set using graceful");
1540 } catch (NullPointerException ignore) {
1541 LOG.trace("BGP AS id is not set using graceful");
1546 LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1552 public synchronized void bgpRestarted() {
1554 * If there a thread which in the process of stale cleanup, cancel it
1555 * and start a new thread (to avoid processing same again).
1557 if (previousReplayJobInProgress()) {
1558 cancelPreviousReplayJob();
1560 Runnable task = () -> {
1562 LOG.info("running bgp replay task ");
1563 if (get() == null) {
1564 String host = getConfigHost();
1565 int port = getConfigPort();
1566 LOG.info("connecting to bgp host {} ", host);
1568 boolean res = bgpRouter.connect(host, port);
1569 LOG.info("no config to push in bgp replay task ");
1572 setStaleStartTime(System.currentTimeMillis());
1573 LOG.info("started creating stale fibDSWriter map ");
1574 createStaleFibMap();
1575 setStaleEndTime(System.currentTimeMillis());
1576 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1577 LOG.info("started bgp config replay ");
1578 setCfgReplayStartTime(System.currentTimeMillis());
1581 } catch (TimeoutException | ExecutionException e) {
1582 LOG.error("Error while replaying routes. {}", e);
1584 setCfgReplayEndTime(System.currentTimeMillis());
1585 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1586 long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1587 Thread.sleep(routeSyncTime * 1000L);
1588 setStaleCleanupTime(routeSyncTime);
1589 new RouteCleanup().call();
1590 } catch (InterruptedException eCancel) {
1591 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1594 lastReplayJobFt = executor.submit(task);
1597 private boolean previousReplayJobInProgress() {
1598 return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1601 private void cancelPreviousReplayJob() {
1603 LOG.error("cancelling already running bgp replay task");
1604 lastReplayJobFt.cancel(true);
1605 lastReplayJobFt = null;
1607 } catch (InterruptedException e) {
1608 LOG.error("Failed to cancel previous replay job ", e);
1612 private static void doRouteSync() throws InterruptedException, TimeoutException, ExecutionException {
1613 BgpSyncHandle bsh = BgpSyncHandle.getInstance();
1614 LOG.error("Starting BGP route sync");
1616 bgpRouter.initRibSync(bsh);
1617 } catch (TException | BgpRouterException e) {
1618 LOG.error("Route sync aborted, exception when initializing", e);
1621 while (bsh.getState() != bsh.DONE) {
1622 for (af_afi afi : af_afi.values()) {
1623 Routes routes = null;
1625 routes = bgpRouter.doRibSync(bsh, afi);
1626 } catch (TException | BgpRouterException e) {
1627 LOG.error("Route sync aborted, exception when syncing", e);
1630 Iterator<Update> updates = routes.getUpdatesIterator();
1631 while (updates.hasNext()) {
1632 Update update = updates.next();
1633 Map<String, Map<String, Long>> staleFibRdMap = BgpConfigurationManager.getStaledFibEntriesMap();
1634 String rd = update.getRd();
1635 String nexthop = update.getNexthop();
1637 // TODO: decide correct label here
1638 int label = update.getL3label();
1640 String prefix = update.getPrefix();
1641 int plen = update.getPrefixlen();
1644 // TODO: protocol type will not be available in "update"
1645 // use "rd" to query vrf table and obtain the protocol_type.
1646 // Currently using PROTOCOL_EVPN as default.
1648 protocol_type.PROTOCOL_EVPN,
1655 update.getMacaddress(),
1657 update.getRoutermac(),
1664 LOG.error("Ending BGP route-sync");
1665 bgpRouter.endRibSync(bsh);
1666 } catch (TException | BgpRouterException e) {
1671 /* onUpdatePushRoute
1672 * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1673 * - Entry compare shall include NextHop, Label.
1674 * - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1675 * - If entry not found, add to FIB Config DS.
1676 * - If entry found, but either Label/NextHop doesn't match.
1677 * - Update FIB Config DS with modified values.
1678 * - delete from Stale Map.
1681 public static void onUpdatePushRoute(protocol_type protocolType,
1692 throws InterruptedException, ExecutionException, TimeoutException {
1693 boolean addroute = false;
1695 VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1696 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1697 encapType = VrfEntry.EncapType.Vxlan;
1698 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = BgpUtil.getVpnInstanceOpData(dataBroker, rd);
1699 if (vpnInstanceOpDataEntry != null) {
1700 l3vni = vpnInstanceOpDataEntry.getL3vni();
1702 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1706 if (!staledFibEntriesMap.isEmpty()) {
1707 // restart Scenario, as MAP is not empty.
1708 Map<String, Long> map = staledFibEntriesMap.get(rd);
1710 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1711 Long labelInStaleMap = map.get(prefixNextHop);
1712 if (null == labelInStaleMap) {
1713 // New Entry, which happened to be added during restart.
1716 map.remove(prefixNextHop);
1717 if (isRouteModified(label, labelInStaleMap)) {
1718 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1719 // Existing entry, where in Label got modified during restart
1725 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1729 LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
1730 rd, prefix, nextHop, label, afi);
1731 // TODO: modify addFibEntryToDS signature
1732 List<String> nextHopList = Collections.singletonList(nextHop);
1733 fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
1734 routermac, RouteOrigin.BGP);
1735 LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1736 String vpnName = BgpUtil.getVpnNameFromRd(dataBroker, rd);
1737 if (vpnName != null) {
1738 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, nextHopList, label, RouteOrigin.BGP,
1739 NwConstants.ADD_FLOW);
1744 private static boolean isRouteModified(int label, Long labelInStaleMap) {
1745 return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
1748 private static void replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1749 for (Neighbors nbr : neighbors) {
1751 final String md5password = extractMd5Secret(nbr);
1752 br.addNeighbor(nbr.getAddress().getValue(),
1753 nbr.getRemoteAs(), md5password);
1754 //itmProvider.buildTunnelsToDCGW(new IpAddress(nbr.getAddress().getValue().toCharArray()));
1755 } catch (TException | BgpRouterException e) {
1756 LOG.error("Replay:addNbr() received exception", e);
1759 EbgpMultihop en = nbr.getEbgpMultihop();
1762 br.addEbgpMultihop(en.getPeerIp().getValue(),
1763 en.getNhops().intValue());
1764 } catch (TException | BgpRouterException e) {
1765 LOG.error("Replay:addEBgp() received exception", e);
1768 UpdateSource us = nbr.getUpdateSource();
1771 br.addUpdateSource(us.getPeerIp().getValue(),
1772 us.getSourceIp().getValue());
1773 } catch (TException | BgpRouterException e) {
1774 LOG.error("Replay:addUS() received exception", e);
1777 List<AddressFamilies> afs = nbr.getAddressFamilies();
1779 for (AddressFamilies af : afs) {
1780 af_afi afi = af_afi.findByValue(af.getAfi().intValue());
1781 af_safi safi = af_safi.findByValue(af.getSafi().intValue());
1783 br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
1784 } catch (TException | BgpRouterException e) {
1785 LOG.error("Replay:addAf() received exception", e);
1792 public static String getConfigHost() {
1793 if (config == null) {
1794 return cHostStartup;
1796 ConfigServer ts = config.getConfigServer();
1797 return (ts == null ? cHostStartup : ts.getHost().getValue());
1800 public static int getConfigPort() {
1801 if (config == null) {
1802 return Integer.parseInt(cPortStartup);
1804 ConfigServer ts = config.getConfigServer();
1805 return (ts == null ? Integer.parseInt(cPortStartup) :
1806 ts.getPort().intValue());
1809 public static Bgp getConfig() {
1810 AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COOUNT);
1811 while (0 != bgpDSretryCount.decrementAndGet()) {
1813 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1814 InstanceIdentifier.create(Bgp.class)).orNull();
1815 } catch (ReadFailedException e) {
1816 //Config DS may not be up, so sleep for 1 second and retry
1817 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
1819 Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
1820 } catch (InterruptedException timerEx) {
1821 LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
1822 + "config DS availability", timerEx);
1826 LOG.error("failed to get bgp config");
1830 @SuppressWarnings("checkstyle:IllegalCatch")
1831 public synchronized void replay() throws InterruptedException, TimeoutException, ExecutionException {
1832 synchronized (bgpConfigurationManager) {
1833 String host = getConfigHost();
1834 int port = getConfigPort();
1835 LOG.error("connecting to bgp host {} ", host);
1837 boolean res = bgpRouter.connect(host, port);
1839 String msg = "Cannot connect to BGP config server at " + host + ":" + port;
1840 if (config != null) {
1841 msg += "; Configuration Replay aborted";
1846 config = getConfig();
1847 if (config == null) {
1848 LOG.error("bgp config is empty nothing to push to bgp");
1851 BgpRouter br = bgpRouter;
1852 AsId asId = config.getAsId();
1856 long asNum = asId.getLocalAs();
1857 IpAddress routerId = asId.getRouterId();
1858 Long spt = asId.getStalepathTime();
1859 Boolean afb = asId.isAnnounceFbit();
1860 String rid = (routerId == null) ? "" : new String(routerId.getValue());
1861 int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, config.getAsId());
1862 boolean announceFbit = true;
1864 br.startBgp(asNum, rid, stalepathTime, announceFbit);
1865 } catch (BgpRouterException bre) {
1866 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
1869 LOG.error("Replay: startBgp() received exception: \""
1870 + bre + "\"; " + ADD_WARN);
1872 } catch (TException e) {
1873 //not unusual. We may have restarted & BGP is already on
1874 LOG.error("Replay:startBgp() received exception: \"" + e + "\"");
1877 if (getBgpCounters() == null) {
1878 startBgpCountersTask();
1881 if (getBgpAlarms() == null) {
1882 startBgpAlarmsTask();
1885 Logging logging = config.getLogging();
1886 if (logging != null) {
1888 br.setLogging(logging.getFile(), logging.getLevel());
1889 } catch (TException | BgpRouterException e) {
1890 LOG.error("Replay:setLogging() received exception", e);
1894 GracefulRestart gracefulRestart = config.getGracefulRestart();
1895 if (gracefulRestart != null) {
1897 br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
1898 } catch (TException | BgpRouterException e) {
1899 LOG.error("Replay:addGr() received exception", e);
1903 List<Vrfs> vrfs = config.getVrfs();
1905 for (Vrfs vrf : vrfs) {
1907 br.addVrf(vrf.getLayerType(), vrf.getRd(), vrf.getImportRts(),
1908 vrf.getExportRts());
1909 } catch (TException | BgpRouterException e) {
1910 LOG.error("Replay:addVrf() received exception", e);
1915 List<Networks> ln = config.getNetworks();
1917 for (Networks net : ln) {
1918 String rd = net.getRd();
1919 String pfxlen = net.getPrefixLen();
1920 String nh = net.getNexthop().getValue();
1921 Long label = net.getLabel();
1922 int lbl = (label == null) ? 0 : label.intValue();
1923 int l3vni = (net.getL3vni() == null) ? 0 : net.getL3vni().intValue();
1924 Long afi = net.getAfi();
1925 int afint = (afi == null) ? (int) af_afi.AFI_IP.getValue() : afi.intValue();
1926 if (rd == null && lbl > 0) {
1927 //LU prefix is being deleted.
1928 rd = Integer.toString(lbl);
1931 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
1932 int ethernetTag = net.getEthtag().intValue();
1933 String esi = net.getEsi();
1934 String macaddress = net.getMacaddress();
1935 EncapType encapType = net.getEncapType();
1936 String routerMac = net.getRoutermac();
1939 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
1940 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType),
1942 } catch (Exception e) {
1943 LOG.error("Replay:addPfx() received exception", e);
1947 List<Neighbors> neighbors = config.getNeighbors();
1948 if (neighbors != null) {
1949 LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
1950 replayNbrConfig(neighbors, br);
1952 LOG.error("no Neighbors present for replay config ");
1955 List<Multipath> multipaths = config.getMultipath();
1957 if (multipaths != null) {
1958 for (Multipath multipath: multipaths) {
1959 if (multipath != null) {
1960 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1961 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1964 if (multipath.isMultipathEnabled()) {
1965 br.enableMultipath(afi, safi);
1967 br.disableMultipath(afi, safi);
1969 } catch (TException | BgpRouterException e) {
1970 LOG.info("Replay:multipaths() received exception: \"" + e + "\"");
1975 List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
1976 if (vrfMaxpaths != null) {
1977 for (VrfMaxpath vrfMaxpath: vrfMaxpaths) {
1979 br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
1980 } catch (TException | BgpRouterException e) {
1981 LOG.info("Replay:vrfMaxPath() received exception: \"" + e + "\"");
1988 private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
1989 BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1992 private <T extends DataObject> void asyncWrite(InstanceIdentifier<T> iid, T dto) {
1993 BgpUtil.write(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1996 private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
1997 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, iid);
2000 public void startConfig(String bgpHost, int thriftPort) {
2001 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2002 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2003 InstanceIdentifier<ConfigServer> iid = iib.build();
2004 Ipv4Address ipAddr = new Ipv4Address(bgpHost);
2005 ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
2006 .setPort((long) thriftPort).build();
2010 public void startBgp(long as, String routerId, int spt, boolean fbit) {
2011 IpAddress rid = (routerId == null) ? null : new IpAddress(routerId.toCharArray());
2012 Long staleTime = (long) spt;
2013 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2014 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2015 InstanceIdentifier<AsId> iid = iib.build();
2016 AsId dto = new AsIdBuilder().setLocalAs(as)
2018 .setStalepathTime(staleTime)
2019 .setAnnounceFbit(fbit).build();
2023 public void addLogging(String fileName, String logLevel) {
2024 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2025 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2026 InstanceIdentifier<Logging> iid = iib.build();
2027 Logging dto = new LoggingBuilder().setFile(fileName)
2028 .setLevel(logLevel).build();
2032 public void addGracefulRestart(int staleTime) {
2033 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2034 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2035 InstanceIdentifier<GracefulRestart> iid = iib.build();
2036 GracefulRestart dto = new GracefulRestartBuilder()
2037 .setStalepathTime((long) staleTime).build();
2041 public void addNeighbor(
2042 String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2043 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2044 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2045 InstanceIdentifier.builder(Bgp.class)
2046 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2047 InstanceIdentifier<Neighbors> iid = iib.build();
2048 TcpSecurityOption tcpSecOption = null;
2049 if (md5Secret != null) {
2050 tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2051 } // else let tcpSecOption be null
2052 Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2053 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2055 } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2057 public void addUpdateSource(String nbrIp, String srcIp) {
2058 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2059 Ipv4Address srcAddr = new Ipv4Address(srcIp);
2060 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2061 InstanceIdentifier.builder(Bgp.class)
2062 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2063 .child(UpdateSource.class);
2064 InstanceIdentifier<UpdateSource> iid = iib.build();
2065 UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2066 .setSourceIp(srcAddr).build();
2070 public void addEbgpMultihop(String nbrIp, int hops) {
2071 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2072 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2073 InstanceIdentifier.builder(Bgp.class)
2074 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2075 .child(EbgpMultihop.class);
2076 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2077 EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2078 .setNhops((long) hops).build();
2082 public void addAddressFamily(String nbrIp, int afi, int safi) {
2083 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2084 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2085 InstanceIdentifier.builder(Bgp.class)
2086 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2087 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2088 InstanceIdentifier<AddressFamilies> iid = iib.build();
2089 AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2090 .setAfi((long) afi).setSafi((long) safi).build();
2094 public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2095 VrfEntry.EncapType encapType, long lbl, long l3vni, long l2vni, String gatewayMac) {
2096 for (String nh : nhList) {
2097 Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2099 InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2100 .child(Networks.class, new NetworksKey(pfx, rd)).build();
2101 NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2102 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
2103 buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, l2vni, macAddress, gatewayMac);
2104 update(iid, networksBuilder.build());
2108 private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
2109 long l3vni, long l2vni, String macAddress, String gatewayMac) {
2110 if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2111 builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2112 .setEncapType(EncapType.GRE);
2114 builder.setL3vni(l3vni).setL2vni(l2vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2115 .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2119 // TODO: add LayerType as arg - supports command
2120 public void addVrf(String rd, List<String> irts, List<String> erts, LayerType layerType) {
2121 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2122 InstanceIdentifier.builder(Bgp.class)
2123 .child(Vrfs.class, new VrfsKey(rd));
2124 InstanceIdentifier<Vrfs> iid = iib.build();
2125 Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2126 .setExportRts(erts).setLayerType(layerType).build();
2128 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2129 } catch (TransactionCommitFailedException e) {
2130 LOG.error("Error adding VRF to datastore", e);
2131 throw new RuntimeException(e);
2135 public void stopConfig() {
2136 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2137 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2138 InstanceIdentifier<ConfigServer> iid = iib.build();
2142 public void stopBgp() {
2143 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2144 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2145 InstanceIdentifier<AsId> iid = iib.build();
2149 public void delLogging() {
2150 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2151 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2152 InstanceIdentifier<Logging> iid = iib.build();
2156 public void delGracefulRestart() {
2157 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2158 InstanceIdentifier.builder(Bgp.class)
2159 .child(GracefulRestart.class);
2160 InstanceIdentifier<GracefulRestart> iid = iib.build();
2164 public void delNeighbor(String nbrIp) {
2165 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2166 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2167 InstanceIdentifier.builder(Bgp.class)
2168 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2169 InstanceIdentifier<Neighbors> iid = iib.build();
2173 public void delUpdateSource(String nbrIp) {
2174 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2175 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2176 InstanceIdentifier.builder(Bgp.class)
2177 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2178 .child(UpdateSource.class);
2179 InstanceIdentifier<UpdateSource> iid = iib.build();
2183 public void delEbgpMultihop(String nbrIp) {
2184 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2185 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2186 InstanceIdentifier.builder(Bgp.class)
2187 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2188 .child(EbgpMultihop.class);
2189 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2193 public void delAddressFamily(String nbrIp, int afi, int safi) {
2194 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2195 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2196 InstanceIdentifier.builder(Bgp.class)
2197 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2198 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2199 InstanceIdentifier<AddressFamilies> iid = iib.build();
2203 public void delPrefix(String rd, String pfx) {
2204 InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2205 InstanceIdentifier.builder(Bgp.class)
2206 .child(Networks.class, new NetworksKey(pfx, rd));
2207 InstanceIdentifier<Networks> iid = iib.build();
2211 public void delVrf(String rd) {
2212 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2213 InstanceIdentifier.builder(Bgp.class)
2214 .child(Vrfs.class, new VrfsKey(rd));
2215 InstanceIdentifier<Vrfs> iid = iib.build();
2219 public void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2220 long lafi = afi.getValue();
2221 long lsafi = safi.getValue();
2223 InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2226 .child(Multipath.class,
2227 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2229 Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2230 update(iib.build(), dto);
2233 public void multipaths(String rd, int maxpath) {
2234 InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2237 .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2239 VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2240 update(iib.build(), dto);
2243 static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
2246 * Remove Stale Marked Routes after timer expiry.
2248 class RouteCleanup implements Callable<Integer> {
2251 public Integer call() {
2254 if (staledFibEntriesMap.isEmpty()) {
2255 LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2257 for (String rd : staledFibEntriesMap.keySet()) {
2258 if (Thread.interrupted()) {
2261 Map<String, Long> map = staledFibEntriesMap.get(rd);
2263 for (String key : map.keySet()) {
2264 if (Thread.interrupted()) {
2267 String prefix = extractPrefix(key);
2268 String nextHop = extractNextHop(key);
2270 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
2271 rd, prefix, nextHop);
2272 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
2278 staledFibEntriesMap.clear();
2280 LOG.error("cleared {} stale routes after bgp restart", totalCleared);
2286 * BGP restart scenario, ODL-BGP manager was/is running.
2287 * On re-sync notification, Get a copy of FIB database.
2289 public static void createStaleFibMap() {
2290 totalStaledCount = 0;
2293 * at the time Stale FIB creation, Wait till all PENDING write transaction
2294 * to complete (or)wait for max timeout value of STALE_FIB_WAIT Seconds.
2296 int retry = STALE_FIB_WAIT;
2297 while ((BgpUtil.getGetPendingWrTransaction() != 0) && (retry > 0)) {
2301 LOG.error("TimeOut occured {} seconds, in waiting stale fibDSWriter create", STALE_FIB_WAIT);
2304 staledFibEntriesMap.clear();
2305 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2306 DataBroker db = BgpUtil.getBroker();
2308 LOG.error("Couldn't find BgpUtil dataBroker while creating createStaleFibMap");
2312 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(BgpUtil.getBroker(),
2313 LogicalDatastoreType.CONFIGURATION, id);
2314 if (fibEntries.isPresent()) {
2315 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2316 for (VrfTables vrfTable : staleVrfTables) {
2317 Map<String, Long> staleFibEntMap = new HashMap<>();
2318 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2319 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2320 //Stale marking and cleanup is only meant for the routes learned through BGP.
2323 if (Thread.interrupted()) {
2327 //Create MAP from staleVrfTables.
2328 vrfEntry.getRoutePaths()
2330 routePath -> staleFibEntMap.put(
2331 appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2332 routePath.getNexthopAddress()), routePath.getLabel()));
2334 staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2337 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2339 } catch (InterruptedException | ReadFailedException e) {
2340 LOG.error("createStaleFibMap:: error ", e);
2342 LOG.error("created {} staled entries ", totalStaledCount);
2346 * BGP config remove scenario, Need to remove all the
2347 * external routes from FIB.
2349 public static void deleteExternalFibRoutes() {
2350 totalExternalRoutes = 0;
2353 * at the time FIB route deletion, Wait till all PENDING write transaction
2354 * to complete (or)wait for max timeout value of STALE_FIB_WAIT Seconds.
2356 int retry = STALE_FIB_WAIT;
2358 while ((BgpUtil.getGetPendingWrTransaction() != 0) && (retry > 0)) {
2362 LOG.error("TimeOut occured {} seconds, while deleting external routes", STALE_FIB_WAIT);
2365 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2366 DataBroker db = BgpUtil.getBroker();
2368 LOG.error("Couldn't find BgpUtil dataBroker while deleting external routes");
2372 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(BgpUtil.getBroker(),
2373 LogicalDatastoreType.CONFIGURATION, id);
2374 if (fibEntries.isPresent()) {
2375 if (fibEntries.get().getVrfTables() == null) {
2376 LOG.error("deleteExternalFibRoutes::getVrfTables is null");
2379 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2380 for (VrfTables vrfTable : staleVrfTables) {
2381 rd = vrfTable.getRouteDistinguisher();
2382 if (vrfTable.getVrfEntry() == null) {
2383 LOG.error("deleteExternalFibRoutes::getVrfEntry is null");
2386 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2387 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2388 //route cleanup is only meant for the routes learned through BGP.
2391 totalExternalRoutes++;
2392 fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
2396 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
2398 } catch (InterruptedException | ReadFailedException e) {
2399 LOG.error("deleteExternalFibRoutes:: error ", e);
2401 LOG.debug("deleted {} fib entries ", totalExternalRoutes);
2404 //map<rd, map<prefix/len:nexthop, label>>
2405 public static Map<String, Map<String, Long>> getStaledFibEntriesMap() {
2406 return staledFibEntriesMap;
2409 //TODO: below function is for testing purpose with cli
2410 public static void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
2411 LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
2412 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
2413 String vpnName = BgpUtil.getVpnNameFromRd(dataBroker, rd);
2414 if (vpnName != null) {
2415 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
2416 RouteOrigin.BGP, NwConstants.DEL_FLOW);
2420 public boolean isBgpConnected() {
2421 return bgpRouter.isBgpConnected();
2424 public long getLastConnectedTS() {
2425 return bgpRouter.getLastConnectedTS();
2428 public long getConnectTS() {
2429 return bgpRouter.getConnectTS();
2432 public long getStartTS() {
2433 return bgpRouter.getStartTS();
2436 public static int getTotalStaledCount() {
2437 return totalStaledCount;
2440 public static int getTotalCleared() {
2441 return totalCleared;
2444 public Timer getBgpCountersTimer() {
2445 return bgpCountersTimer;
2448 public BgpCounters getBgpCounters() {
2452 public void setBgpCountersTimer(Timer timer) {
2453 bgpCountersTimer = timer;
2456 public void setBgpAlarmsTimer(Timer timer) {
2457 bgpAlarmsTimer = timer;
2460 public void startBgpCountersTask() {
2461 if (getBgpCounters() == null) {
2462 bgpCounters = new BgpCounters(bgpConfigurationManager.getBgpSdncMipIp());
2463 setBgpCountersTimer(new Timer(true));
2464 getBgpCountersTimer().scheduleAtFixedRate(bgpCounters, 0, 120 * 1000);
2465 LOG.info("Bgp Counters task scheduled for every two minutes.");
2467 bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2471 public void stopBgpCountersTask() {
2472 Timer timer = getBgpCountersTimer();
2473 if (getBgpCounters() != null) {
2475 setBgpCountersTimer(null);
2480 public void startBgpAlarmsTask() {
2481 if (getBgpAlarms() == null) {
2482 bgpAlarms = new BgpAlarms(this);
2483 setBgpAlarmsTimer(new Timer(true));
2484 getBgpAlarmsTimer().scheduleAtFixedRate(bgpAlarms, 0, 60 * 1000);
2485 LOG.info("Bgp Alarms task scheduled for every minute.");
2489 public void stopBgpAlarmsTask() {
2490 Timer timer = getBgpAlarmsTimer();
2491 if (getBgpAlarms() != null) {
2493 setBgpAlarmsTimer(null);
2498 public Timer getBgpAlarmsTimer() {
2499 return bgpAlarmsTimer;
2502 public BgpAlarms getBgpAlarms() {
2506 private static String appendNextHopToPrefix(String prefix, String nextHop) {
2507 return prefix + ":" + nextHop;
2510 private static String extractPrefix(String prefixNextHop) {
2511 return prefixNextHop.split(":")[0];
2514 private static String extractNextHop(String prefixNextHop) {
2515 return prefixNextHop.split(":")[1];
2518 private static String extractMd5Secret(final Neighbors val) {
2519 String md5Secret = null;
2520 TcpSecurityOption tcpSecOpt = val.getTcpSecurityOption();
2521 if (tcpSecOpt != null) {
2522 if (tcpSecOpt instanceof TcpMd5SignatureOption) {
2523 md5Secret = ((TcpMd5SignatureOption) tcpSecOpt).getTcpMd5SignaturePassword().getValue();
2524 } else { // unknown TcpSecurityOption
2525 LOG.debug("neighbors Ignored unknown tcp-security-option of peer {}", val.getAddress().getValue());
2529 } // private method extractMd5Secret