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.utils.batching.DefaultBatchHandler;
57 import org.opendaylight.genius.utils.clustering.EntityOwnerUtils;
58 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.AddressFamiliesReactor;
59 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.AsIdReactor;
60 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.BgpReactor;
61 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.ConfigServerReactor;
62 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.EbgpMultihopReactor;
63 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.GracefulRestartReactor;
64 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.LoggingReactor;
65 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.MultipathReactor;
66 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.NeighborsReactor;
67 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.NetworksReactor;
68 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.RouteCleanup;
69 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.UpdateSourceReactor;
70 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.VrfMaxpathReactor;
71 import org.opendaylight.netvirt.bgpmanager.BgpConfigurationManager.VrfsReactor;
72 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
73 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
74 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
75 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
76 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
77 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
78 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
79 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
80 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
81 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
82 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
83 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
84 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
85 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
86 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
87 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
88 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
89 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
90 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
91 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.LayerType;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Multipath;
102 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathBuilder;
103 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathKey;
104 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
105 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
107 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
108 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
109 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
110 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpath;
111 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathBuilder;
112 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathKey;
113 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
114 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
115 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
116 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
117 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
118 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
119 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
120 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
121 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
122 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
123 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
124 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
125 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
126 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
131 import org.opendaylight.yangtools.concepts.ListenerRegistration;
132 import org.opendaylight.yangtools.yang.binding.DataObject;
133 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
134 import org.osgi.framework.BundleContext;
135 import org.slf4j.Logger;
136 import org.slf4j.LoggerFactory;
140 public class BgpConfigurationManager {
141 private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
142 private static DataBroker dataBroker;
143 private static FibDSWriter fibDSWriter;
144 public static IBgpManager bgpManager;
145 private final BundleContext bundleContext;
146 private static Bgp config;
147 private static BgpRouter bgpRouter;
148 private static BgpThriftService updateServer;
149 private BgpCounters bgpCounters;
150 private BgpAlarms bgpAlarms;
151 private Timer bgpCountersTimer;
152 private Timer bgpAlarmsTimer;
153 private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
154 private static final String DEF_LOGLEVEL = "errors";
155 private static final String UPDATE_PORT = "bgp.thrift.service.port";
156 private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
157 private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
158 private static final String DEF_UPORT = "6644";
159 private static final String DEF_CHOST = "127.0.0.1";
160 private static final String DEF_CPORT = "7644";
161 private static final String SDNC_BGP_MIP = "sdnc_bgp_mip";
162 private static final String BGP_SDNC_MIP = "bgp_sdnc_mip";
163 private static final String CLUSTER_CONF_FILE = "/cluster/etc/cluster.conf";
164 private static final Timer IP_ACTIVATION_CHECK_TIMER = new Timer();
165 private static final int STALE_FIB_WAIT = 60;
166 private static final int RESTART_DEFAULT_GR = 90;
167 private long staleStartTime = 0;
168 private long staleEndTime = 0;
169 private long cfgReplayStartTime = 0;
170 private long cfgReplayEndTime = 0;
171 private long staleCleanupTime = 0;
172 private static final int DS_RETRY_COOUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
173 private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
175 public String getBgpSdncMipIp() {
176 return readThriftIpForCommunication(BGP_SDNC_MIP);
179 public long getStaleCleanupTime() {
180 return staleCleanupTime;
183 public void setStaleCleanupTime(long staleCleanupTime) {
184 this.staleCleanupTime = staleCleanupTime;
187 public long getCfgReplayEndTime() {
188 return cfgReplayEndTime;
191 public void setCfgReplayEndTime(long cfgReplayEndTime) {
192 this.cfgReplayEndTime = cfgReplayEndTime;
195 public long getCfgReplayStartTime() {
196 return cfgReplayStartTime;
199 public void setCfgReplayStartTime(long cfgReplayStartTime) {
200 this.cfgReplayStartTime = cfgReplayStartTime;
203 public long getStaleEndTime() {
207 public void setStaleEndTime(long staleEndTime) {
208 this.staleEndTime = staleEndTime;
211 public long getStaleStartTime() {
212 return staleStartTime;
215 public void setStaleStartTime(long staleStartTime) {
216 this.staleStartTime = staleStartTime;
220 // to have stale FIB map (RD, Prefix)
221 // number of seconds wait for route sync-up between ODL and BGP
222 private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
224 static String odlThriftIp = "127.0.0.1";
225 static String bgpThriftIp = "127.0.0.1";
226 private static String cHostStartup;
227 private static String cPortStartup;
228 private static CountDownLatch initer = new CountDownLatch(1);
229 //static IITMProvider itmProvider;
230 //map<rd, map<prefix/len:nexthop, label>>
231 private static Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
233 static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
234 static final String BGP_ENTITY_NAME = "bgp";
236 static int totalStaledCount = 0;
237 static int totalCleared = 0;
239 private static final Class[] REACTORS = {
240 ConfigServerReactor.class, AsIdReactor.class,
241 GracefulRestartReactor.class, LoggingReactor.class,
242 NeighborsReactor.class, UpdateSourceReactor.class,
243 EbgpMultihopReactor.class, AddressFamiliesReactor.class,
244 NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
245 MultipathReactor.class, VrfMaxpathReactor.class
248 private ListenerRegistration<DataChangeListener>[] registrations;
250 final BgpConfigurationManager bgpConfigurationManager;
252 public BgpConfigurationManager(final DataBroker dataBroker,
253 final EntityOwnershipService entityOwnershipService,
254 final FibDSWriter fibDSWriter,
255 final BundleContext bundleContext)
256 throws InterruptedException, ExecutionException, TimeoutException {
257 BgpConfigurationManager.dataBroker = dataBroker;
258 BgpConfigurationManager.fibDSWriter = fibDSWriter;
259 this.bundleContext = bundleContext;
260 String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
261 cHostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
262 cPortStartup = getProperty(CONFIG_PORT, DEF_CPORT);
263 LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
264 + cHostStartup + ":" + cPortStartup);
265 VtyshCli.setHostAddr(cHostStartup);
266 ClearBgpCli.setHostAddr(cHostStartup);
267 setEntityOwnershipService(entityOwnershipService);
268 bgpRouter = BgpRouter.getInstance();
269 odlThriftIp = readThriftIpForCommunication(SDNC_BGP_MIP);
270 bgpThriftIp = readThriftIpForCommunication(BGP_SDNC_MIP);
273 LOG.info("BGP Configuration manager initialized");
276 bgpConfigurationManager = this;
277 BgpUtil.batchSize = BgpUtil.BATCH_SIZE;
278 if (Integer.getInteger("batch.size") != null) {
279 BgpUtil.batchSize = Integer.getInteger("batch.size");
281 BgpUtil.batchInterval = BgpUtil.PERIODICITY;
282 if (Integer.getInteger("batch.wait.time") != null) {
283 BgpUtil.batchInterval = Integer.getInteger("batch.wait.time");
285 BgpUtil.registerWithBatchManager(
286 new DefaultBatchHandler(dataBroker, LogicalDatastoreType.CONFIGURATION, BgpUtil.batchSize,
287 BgpUtil.batchInterval));
289 GlobalEventExecutor.INSTANCE.execute(() -> {
290 final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
291 IBgpManager.class, bundleContext);
292 bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
293 updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, fibDSWriter);
294 updateServer.start();
295 LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
299 private Object createListener(Class<?> cls) {
304 ctor = cls.getConstructor(BgpConfigurationManager.class);
305 obj = ctor.newInstance(this);
306 } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
308 LOG.error("Failed to create listener object", e);
313 private void registerCallbacks() {
314 String emsg = "Failed to register listener";
315 registrations = new ListenerRegistration[REACTORS.length];
316 InstanceIdentifier<?> iid = InstanceIdentifier.create(Bgp.class);
317 for (Class reactor : REACTORS) {
318 Object obj = createListener(reactor);
319 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
320 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
324 public void close() {
325 if (updateServer != null) {
328 LOG.info("{} close", getClass().getSimpleName());
331 private boolean configExists() throws ReadFailedException {
332 InstanceIdentifier.InstanceIdentifierBuilder<Bgp> iib =
333 InstanceIdentifier.builder(Bgp.class);
334 InstanceIdentifier<Bgp> iid = iib.build();
335 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
339 private String getProperty(String var, String def) {
340 String property = bundleContext.getProperty(var);
341 return (property == null ? def : property);
344 boolean ignoreClusterDcnEventForFollower() {
345 return !EntityOwnerUtils.amIEntityOwner(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME);
349 config = getConfig();
353 public void setEntityOwnershipService(final EntityOwnershipService entityOwnershipService) {
355 EntityOwnerUtils.registerEntityCandidateForOwnerShip(entityOwnershipService,
356 BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME, ownershipChange -> {
357 LOG.trace("entity owner change event fired");
358 if (ownershipChange.hasOwner() && ownershipChange.isOwner()) {
359 LOG.trace("This PL is the Owner");
363 LOG.info("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.hasOwner(),
364 ownershipChange.isOwner());
367 } catch (CandidateAlreadyRegisteredException e) {
368 LOG.error("failed to register bgp entity", e);
372 private static final String ADD_WARN =
373 "Config store updated; undo with Delete if needed.";
374 private static final String DEL_WARN =
375 "Config store updated; undo with Add if needed.";
376 private static final String UPD_WARN =
377 "Update operation not supported; Config store updated;"
378 + " restore with another Update if needed.";
380 public class ConfigServerReactor
381 extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
382 implements AutoCloseable, ClusteredDataTreeChangeListener<ConfigServer> {
383 private static final String YANG_OBJ = "config-server ";
385 public ConfigServerReactor() {
386 super(ConfigServer.class, ConfigServerReactor.class);
390 protected synchronized void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
391 LOG.trace("received bgp connect config host {}", val.getHost().getValue());
392 if (ignoreClusterDcnEventForFollower()) {
398 } catch (InterruptedException e) {
401 LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
402 synchronized (BgpConfigurationManager.this) {
403 boolean res = bgpRouter.connect(val.getHost().getValue(),
404 val.getPort().intValue());
406 LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
412 protected ConfigServerReactor getDataTreeChangeListener() {
413 return ConfigServerReactor.this;
417 protected InstanceIdentifier<ConfigServer> getWildCardPath() {
418 return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
422 protected synchronized void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
423 LOG.trace("received bgp disconnect");
424 if (ignoreClusterDcnEventForFollower()) {
427 synchronized (BgpConfigurationManager.this) {
428 bgpRouter.disconnect();
433 protected void update(InstanceIdentifier<ConfigServer> iid,
434 ConfigServer oldval, ConfigServer newval) {
435 LOG.trace("received bgp Connection update");
436 if (ignoreClusterDcnEventForFollower()) {
439 LOG.error(YANG_OBJ + UPD_WARN);
443 private BgpRouter getClient(String yangObj) {
444 if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
445 LOG.warn("{}: configuration received when BGP is inactive", yangObj);
451 public class AsIdReactor
452 extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
453 implements AutoCloseable, ClusteredDataTreeChangeListener<AsId> {
455 private static final String YANG_OBJ = "as-id ";
457 public AsIdReactor() {
458 super(AsId.class, AsIdReactor.class);
462 protected synchronized void add(InstanceIdentifier<AsId> iid, AsId val) {
463 LOG.error("received bgp add asid {}", val);
464 if (ignoreClusterDcnEventForFollower()) {
467 LOG.debug("received add router config asNum {}", val.getLocalAs());
468 synchronized (BgpConfigurationManager.this) {
469 IpAddress routerId = val.getRouterId();
470 BgpRouter br = getClient(YANG_OBJ);
471 long asNum = val.getLocalAs();
473 LOG.error("{} Unable to process add for routerId {} asNum {}; {}", YANG_OBJ, routerId, asNum,
474 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
477 Boolean afb = val.isAnnounceFbit();
478 String rid = (routerId == null) ? "" : new String(routerId.getValue());
479 int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, val);
480 boolean announceFbit = true;
482 br.startBgp(asNum, rid, stalepathTime, announceFbit);
483 if (getBgpCounters() == null) {
484 startBgpCountersTask();
486 if (getBgpAlarms() == null) {
487 startBgpAlarmsTask();
489 } catch (BgpRouterException bre) {
490 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
491 LOG.error(YANG_OBJ + "Add requested when BGP is already active");
493 LOG.error(YANG_OBJ + "Add received exception: \""
494 + bre + "\"; " + ADD_WARN);
496 } catch (TException e) {
497 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
503 protected AsIdReactor getDataTreeChangeListener() {
504 return AsIdReactor.this;
508 protected InstanceIdentifier<AsId> getWildCardPath() {
509 return InstanceIdentifier.create(Bgp.class).child(AsId.class);
513 protected synchronized void remove(InstanceIdentifier<AsId> iid, AsId val) {
514 LOG.error("received delete router config asNum {}", val.getLocalAs());
515 if (ignoreClusterDcnEventForFollower()) {
518 synchronized (BgpConfigurationManager.this) {
519 long asNum = val.getLocalAs();
520 BgpRouter br = getClient(YANG_OBJ);
522 LOG.error("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
523 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
528 } catch (TException | BgpRouterException e) {
529 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
531 if (getBgpCounters() != null) {
532 stopBgpCountersTask();
534 if (getBgpAlarms() != null) {
541 protected void update(InstanceIdentifier<AsId> iid,
542 AsId oldval, AsId newval) {
543 if (ignoreClusterDcnEventForFollower()) {
546 LOG.error(YANG_OBJ + UPD_WARN);
550 public class GracefulRestartReactor
551 extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
552 implements AutoCloseable, ClusteredDataTreeChangeListener<GracefulRestart> {
554 private static final String YANG_OBJ = "graceful-restart ";
556 public GracefulRestartReactor() {
557 super(GracefulRestart.class, GracefulRestartReactor.class);
561 protected synchronized void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
562 if (ignoreClusterDcnEventForFollower()) {
565 synchronized (BgpConfigurationManager.this) {
566 int stalePathTime = val.getStalepathTime().intValue();
567 BgpRouter br = getClient(YANG_OBJ);
569 LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
570 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
574 br.addGracefulRestart(stalePathTime);
575 } catch (TException | BgpRouterException e) {
576 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
582 protected GracefulRestartReactor getDataTreeChangeListener() {
583 return GracefulRestartReactor.this;
587 protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
588 return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
592 protected synchronized void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
593 if (ignoreClusterDcnEventForFollower()) {
596 LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
597 synchronized (BgpConfigurationManager.this) {
598 BgpRouter br = getClient(YANG_OBJ);
600 LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
601 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
605 br.delGracefulRestart();
606 } catch (TException | BgpRouterException e) {
607 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
613 protected void update(InstanceIdentifier<GracefulRestart> iid,
614 GracefulRestart oldval, GracefulRestart newval) {
615 if (ignoreClusterDcnEventForFollower()) {
618 LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
619 synchronized (BgpConfigurationManager.this) {
620 int stalePathTime = newval.getStalepathTime().intValue();
621 BgpRouter br = getClient(YANG_OBJ);
623 LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
624 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
628 br.addGracefulRestart(stalePathTime);
629 } catch (TException | BgpRouterException e) {
630 LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
636 public class LoggingReactor
637 extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
638 implements AutoCloseable, ClusteredDataTreeChangeListener<Logging> {
640 private static final String YANG_OBJ = "logging ";
642 public LoggingReactor() {
643 super(Logging.class, LoggingReactor.class);
647 protected synchronized void add(InstanceIdentifier<Logging> iid, Logging val) {
648 if (ignoreClusterDcnEventForFollower()) {
651 synchronized (BgpConfigurationManager.this) {
652 BgpRouter br = getClient(YANG_OBJ);
654 LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
655 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
659 br.setLogging(val.getFile(), val.getLevel());
660 } catch (TException | BgpRouterException e) {
661 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
667 protected LoggingReactor getDataTreeChangeListener() {
668 return LoggingReactor.this;
672 protected InstanceIdentifier<Logging> getWildCardPath() {
673 return InstanceIdentifier.create(Bgp.class).child(Logging.class);
677 protected synchronized void remove(InstanceIdentifier<Logging> iid, Logging val) {
678 if (ignoreClusterDcnEventForFollower()) {
681 LOG.debug("received remove Logging config val {}", val.getLevel());
682 synchronized (BgpConfigurationManager.this) {
683 BgpRouter br = getClient(YANG_OBJ);
685 LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
686 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
690 br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
691 } catch (TException | BgpRouterException e) {
692 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
698 protected void update(InstanceIdentifier<Logging> iid,
699 Logging oldval, Logging newval) {
700 if (ignoreClusterDcnEventForFollower()) {
703 synchronized (BgpConfigurationManager.this) {
704 BgpRouter br = getClient(YANG_OBJ);
706 LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
707 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
711 br.setLogging(newval.getFile(), newval.getLevel());
712 } catch (TException | BgpRouterException e) {
713 LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
719 public class NeighborsReactor
720 extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
721 implements AutoCloseable, ClusteredDataTreeChangeListener<Neighbors> {
723 private static final String YANG_OBJ = "neighbors ";
725 public NeighborsReactor() {
726 super(Neighbors.class, NeighborsReactor.class);
730 protected synchronized void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
731 if (ignoreClusterDcnEventForFollower()) {
734 LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
735 synchronized (BgpConfigurationManager.this) {
736 String peerIp = val.getAddress().getValue();
737 long as = val.getRemoteAs();
738 BgpRouter br = getClient(YANG_OBJ);
740 LOG.error("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
741 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
745 //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
746 br.addNeighbor(peerIp, as);
748 } catch (TException | BgpRouterException e) {
749 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
755 protected NeighborsReactor getDataTreeChangeListener() {
756 return NeighborsReactor.this;
760 protected InstanceIdentifier<Neighbors> getWildCardPath() {
761 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
765 protected synchronized void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
766 if (ignoreClusterDcnEventForFollower()) {
769 LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
770 synchronized (BgpConfigurationManager.this) {
771 String peerIp = val.getAddress().getValue();
772 BgpRouter br = getClient(YANG_OBJ);
774 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
775 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
779 //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
780 br.delNeighbor(peerIp);
781 } catch (TException | BgpRouterException e) {
782 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
788 protected void update(InstanceIdentifier<Neighbors> iid,
789 Neighbors oldval, Neighbors newval) {
790 if (ignoreClusterDcnEventForFollower()) {
793 //purposefully nothing to do.
797 public class EbgpMultihopReactor
798 extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
799 implements AutoCloseable, ClusteredDataTreeChangeListener<EbgpMultihop> {
801 private static final String YANG_OBJ = "ebgp-multihop ";
803 public EbgpMultihopReactor() {
804 super(EbgpMultihop.class, EbgpMultihopReactor.class);
808 protected synchronized void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
809 if (ignoreClusterDcnEventForFollower()) {
812 LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
813 synchronized (BgpConfigurationManager.this) {
814 String peerIp = val.getPeerIp().getValue();
815 BgpRouter br = getClient(YANG_OBJ);
817 LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
818 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
822 br.addEbgpMultihop(peerIp, val.getNhops().intValue());
823 } catch (TException | BgpRouterException e) {
824 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
830 protected EbgpMultihopReactor getDataTreeChangeListener() {
831 return EbgpMultihopReactor.this;
835 protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
836 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
840 protected synchronized void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
841 if (ignoreClusterDcnEventForFollower()) {
844 LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
845 synchronized (BgpConfigurationManager.this) {
846 String peerIp = val.getPeerIp().getValue();
847 BgpRouter br = getClient(YANG_OBJ);
849 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
850 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
854 br.delEbgpMultihop(peerIp);
855 } catch (TException | BgpRouterException e) {
856 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
862 protected void update(InstanceIdentifier<EbgpMultihop> iid,
863 EbgpMultihop oldval, EbgpMultihop newval) {
864 if (ignoreClusterDcnEventForFollower()) {
867 LOG.error(YANG_OBJ + UPD_WARN);
871 public class UpdateSourceReactor
872 extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
873 implements AutoCloseable, ClusteredDataTreeChangeListener<UpdateSource> {
875 private static final String YANG_OBJ = "update-source ";
877 public UpdateSourceReactor() {
878 super(UpdateSource.class, UpdateSourceReactor.class);
882 protected synchronized void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
883 if (ignoreClusterDcnEventForFollower()) {
886 LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
887 synchronized (BgpConfigurationManager.this) {
888 String peerIp = val.getPeerIp().getValue();
889 BgpRouter br = getClient(YANG_OBJ);
891 LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
892 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
896 br.addUpdateSource(peerIp, val.getSourceIp().getValue());
897 } catch (TException | BgpRouterException e) {
898 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
904 protected UpdateSourceReactor getDataTreeChangeListener() {
905 return UpdateSourceReactor.this;
909 protected InstanceIdentifier<UpdateSource> getWildCardPath() {
910 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
914 protected synchronized void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
915 if (ignoreClusterDcnEventForFollower()) {
918 LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
919 synchronized (BgpConfigurationManager.this) {
920 String peerIp = val.getPeerIp().getValue();
921 BgpRouter br = getClient(YANG_OBJ);
923 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
924 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
928 br.delUpdateSource(peerIp);
929 } catch (TException | BgpRouterException e) {
930 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
936 protected void update(InstanceIdentifier<UpdateSource> iid,
937 UpdateSource oldval, UpdateSource newval) {
938 if (ignoreClusterDcnEventForFollower()) {
941 LOG.error(YANG_OBJ + UPD_WARN);
945 public class AddressFamiliesReactor
946 extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
947 implements AutoCloseable, ClusteredDataTreeChangeListener<AddressFamilies> {
949 private static final String YANG_OBJ = "address-families ";
951 public AddressFamiliesReactor() {
952 super(AddressFamilies.class, AddressFamiliesReactor.class);
956 protected synchronized void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
957 if (ignoreClusterDcnEventForFollower()) {
960 LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
961 synchronized (BgpConfigurationManager.this) {
962 String peerIp = val.getPeerIp().getValue();
963 BgpRouter br = getClient(YANG_OBJ);
965 LOG.error("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
966 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
969 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
970 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
972 br.addAddressFamily(peerIp, afi, safi);
973 } catch (TException | BgpRouterException e) {
974 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
980 protected AddressFamiliesReactor getDataTreeChangeListener() {
981 return AddressFamiliesReactor.this;
985 protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
986 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
990 protected synchronized void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
991 if (ignoreClusterDcnEventForFollower()) {
994 LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
995 synchronized (BgpConfigurationManager.this) {
996 String peerIp = val.getPeerIp().getValue();
997 BgpRouter br = getClient(YANG_OBJ);
999 LOG.error("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
1000 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1003 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1004 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1006 br.delAddressFamily(peerIp, afi, safi);
1007 } catch (TException | BgpRouterException e) {
1008 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1014 protected void update(InstanceIdentifier<AddressFamilies> iid,
1015 AddressFamilies oldval, AddressFamilies newval) {
1016 if (ignoreClusterDcnEventForFollower()) {
1019 LOG.error(YANG_OBJ + UPD_WARN);
1023 public class NetworksReactor
1024 extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1025 implements AutoCloseable, ClusteredDataTreeChangeListener<Networks> {
1027 private static final String YANG_OBJ = "networks ";
1029 public NetworksReactor() {
1030 super(Networks.class, NetworksReactor.class);
1034 public NetworksReactor getDataTreeChangeListener() {
1035 return NetworksReactor.this;
1039 protected synchronized void add(InstanceIdentifier<Networks> iid, Networks val) {
1040 if (ignoreClusterDcnEventForFollower()) {
1043 LOG.debug("received add Networks config val {}", val.getPrefixLen());
1044 synchronized (BgpConfigurationManager.this) {
1045 String rd = val.getRd();
1046 String pfxlen = val.getPrefixLen();
1047 String nh = val.getNexthop().getValue();
1048 BgpRouter br = getClient(YANG_OBJ);
1050 LOG.error("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
1051 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1054 Long label = val.getLabel();
1055 int lbl = (label == null) ? qbgpConstants.LBL_NO_LABEL
1057 int l3vni = (val.getL3vni() == null) ? qbgpConstants.LBL_NO_LABEL
1058 : val.getL3vni().intValue();
1060 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1061 int ethernetTag = val.getEthtag().intValue();
1062 String esi = val.getEsi();
1063 String macaddress = val.getMacaddress();
1064 EncapType encapType = val.getEncapType();
1065 String routerMac = val.getRoutermac();
1068 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
1069 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1070 } catch (TException | BgpRouterException e) {
1071 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1077 protected InstanceIdentifier<Networks> getWildCardPath() {
1078 return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1082 protected synchronized void remove(InstanceIdentifier<Networks> iid, Networks val) {
1083 if (ignoreClusterDcnEventForFollower()) {
1086 LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1087 synchronized (BgpConfigurationManager.this) {
1088 String rd = val.getRd();
1089 String pfxlen = val.getPrefixLen();
1090 BgpRouter br = getClient(YANG_OBJ);
1092 LOG.error("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
1093 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1096 Long label = val.getLabel();
1097 int lbl = (label == null) ? 0 : label.intValue();
1098 if (rd == null && lbl > 0) {
1099 //LU prefix is being deleted.
1100 rd = Integer.toString(lbl);
1103 br.delPrefix(rd, pfxlen);
1104 } catch (TException | BgpRouterException e) {
1105 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1111 protected void update(final InstanceIdentifier<Networks> iid,
1112 final Networks oldval, final Networks newval) {
1113 if (ignoreClusterDcnEventForFollower()) {
1116 if (oldval.equals(newval)) {
1117 //Update: OLD and New values are same, no need to trigger remove/add.
1118 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1119 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1122 LOG.debug("received update networks config val {}", newval.getPrefixLen());
1123 remove(iid, oldval);
1124 timer.schedule(new TimerTask() {
1129 }, Integer.getInteger("bgp.nexthop.update.delay.in.secs", 5) * 1000);
1133 static Timer timer = new Timer();
1135 public class VrfsReactor
1136 extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1137 implements AutoCloseable, ClusteredDataTreeChangeListener<Vrfs> {
1139 private static final String YANG_OBJ = "vrfs ";
1141 public VrfsReactor() {
1142 super(Vrfs.class, VrfsReactor.class);
1146 protected synchronized void add(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1147 if (ignoreClusterDcnEventForFollower()) {
1150 LOG.debug("received add Vrfs config val {}", val.getRd());
1151 synchronized (BgpConfigurationManager.this) {
1152 String rd = val.getRd();
1153 BgpRouter br = getClient(YANG_OBJ);
1155 LOG.error("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1156 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1160 br.addVrf(val.getLayerType(), rd, val.getImportRts(),
1161 val.getExportRts());
1162 } catch (TException | BgpRouterException e) {
1163 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1169 protected VrfsReactor getDataTreeChangeListener() {
1170 return VrfsReactor.this;
1174 protected InstanceIdentifier<Vrfs> getWildCardPath() {
1175 return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1179 protected synchronized void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1180 if (ignoreClusterDcnEventForFollower()) {
1183 LOG.debug("received remove Vrfs config val {}", val.getRd());
1184 synchronized (BgpConfigurationManager.this) {
1185 String rd = val.getRd();
1186 BgpRouter br = getClient(YANG_OBJ);
1188 LOG.error("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
1189 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1194 } catch (TException | BgpRouterException e) {
1195 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1201 protected void update(InstanceIdentifier<Vrfs> iid,
1202 Vrfs oldval, Vrfs newval) {
1203 if (ignoreClusterDcnEventForFollower()) {
1206 LOG.debug("VRFS: Update getting triggered for VRFS rd {}", oldval.getRd());
1207 LOG.error(YANG_OBJ + UPD_WARN);
1211 Future lastCleanupJob;
1212 Future lastReplayJobFt = null;
1214 protected void activateMIP() {
1216 LOG.trace("BgpReactor: Executing MIP Activate command");
1217 Process processBgp = Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1218 Process processOs = Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1219 LOG.trace("bgpMIP Activated");
1221 } catch (IOException io) {
1222 LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1226 AtomicBoolean started = new AtomicBoolean(false);
1228 public class BgpReactor
1229 extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1230 implements AutoCloseable, ClusteredDataTreeChangeListener<Bgp> {
1232 private static final String YANG_OBJ = "Bgp ";
1234 public BgpReactor() {
1235 super(Bgp.class, BgpReactor.class);
1240 protected synchronized void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1241 LOG.error("received add Bgp config replaying the config");
1245 } catch (InterruptedException e) {
1248 synchronized (BgpConfigurationManager.this) {
1250 if (ignoreClusterDcnEventForFollower()) {
1254 if (isIpAvailable(odlThriftIp)) {
1257 IP_ACTIVATION_CHECK_TIMER.scheduleAtFixedRate(new TimerTask() {
1260 if (isIpAvailable(odlThriftIp)) {
1262 IP_ACTIVATION_CHECK_TIMER.cancel();
1264 LOG.trace("waiting for odlThriftIP: {} to be present", odlThriftIp);
1273 protected BgpReactor getDataTreeChangeListener() {
1274 return BgpReactor.this;
1278 protected InstanceIdentifier<Bgp> getWildCardPath() {
1279 return InstanceIdentifier.create(Bgp.class);
1283 protected synchronized void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1284 if (ignoreClusterDcnEventForFollower()) {
1287 LOG.debug("received remove Bgp config");
1288 synchronized (BgpConfigurationManager.this) {
1294 protected void update(InstanceIdentifier<Bgp> iid,
1295 Bgp oldval, Bgp newval) {
1296 if (ignoreClusterDcnEventForFollower()) {
1299 synchronized (BgpConfigurationManager.this) {
1305 @SuppressWarnings("deprecation")
1306 public class MultipathReactor
1307 extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1308 implements AutoCloseable, ClusteredDataTreeChangeListener<Multipath> {
1310 private static final String YANG_OBJ = "multipath ";
1312 public MultipathReactor() {
1313 super(Multipath.class, MultipathReactor.class);
1318 protected MultipathReactor getDataTreeChangeListener() {
1319 return MultipathReactor.this;
1323 protected InstanceIdentifier<Multipath> getWildCardPath() {
1324 return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
1328 protected synchronized void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1329 ExecutorService executor = Executors.newSingleThreadExecutor();
1330 executor.submit(new MultipathStatusChange(val));
1331 executor.shutdown();
1335 protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1336 ExecutorService executor = Executors.newSingleThreadExecutor();
1337 executor.submit(new MultipathStatusChange(newval));
1338 executor.shutdown();
1342 protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1343 ExecutorService executor = Executors.newSingleThreadExecutor();
1344 executor.submit(new MultipathStatusChange(dataObjectModification));
1345 executor.shutdown();
1348 class MultipathStatusChange implements Callable<Void> {
1350 Multipath multipath;
1352 MultipathStatusChange(Multipath multipath) {
1353 this.multipath = multipath;
1357 public Void call() throws Exception {
1358 if (!ignoreClusterDcnEventForFollower()) {
1359 synchronized (BgpConfigurationManager.this) {
1361 BgpRouter br = getClient(YANG_OBJ);
1364 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1365 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1368 if (multipath.isMultipathEnabled()) {
1369 br.enableMultipath(afi, safi);
1371 br.disableMultipath(afi, safi);
1373 } catch (TException | BgpRouterException e) {
1374 LOG.error(YANG_OBJ + " received exception: \"" + e + "\"");
1385 public void close() {
1390 @SuppressWarnings("deprecation")
1391 public class VrfMaxpathReactor
1392 extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1393 implements AutoCloseable, ClusteredDataTreeChangeListener<VrfMaxpath> {
1395 private static final String YANG_OBJ = "vrfMaxpath ";
1397 public VrfMaxpathReactor() {
1398 super(VrfMaxpath.class, VrfMaxpathReactor.class);
1403 protected VrfMaxpathReactor getDataTreeChangeListener() {
1404 return VrfMaxpathReactor.this;
1408 protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1409 return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
1412 class VrfMaxPathConfigurator implements Callable<Void> {
1414 VrfMaxpath vrfMaxpathVal;
1416 VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1417 this.vrfMaxpathVal = vrfMaxPathVal;
1421 public Void call() throws Exception {
1422 if (!ignoreClusterDcnEventForFollower()) {
1423 synchronized (BgpConfigurationManager.this) {
1424 BgpRouter br = getClient(YANG_OBJ);
1427 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
1428 LOG.debug("Maxpath for vrf: " + vrfMaxpathVal.getRd() + " : is "
1429 + vrfMaxpathVal.getMaxpaths());
1430 } catch (TException | BgpRouterException e) {
1432 + " received exception: \"" + e + "\"");
1442 protected synchronized void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1443 ExecutorService executor = Executors.newSingleThreadExecutor();
1444 executor.submit(new VrfMaxPathConfigurator(vrfMaxPathVal));
1445 executor.shutdown();
1449 protected void update(InstanceIdentifier<VrfMaxpath> iid,
1450 VrfMaxpath oldval, VrfMaxpath newval) {
1451 if (oldval.getMaxpaths() != newval.getMaxpaths()) {
1452 ExecutorService executor = Executors.newSingleThreadExecutor();
1453 executor.submit(new VrfMaxPathConfigurator(newval));
1454 executor.shutdown();
1459 protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1460 ExecutorService executor = Executors.newSingleThreadExecutor();
1461 executor.submit(new VrfMaxPathConfigurator(vrfMaxpathVal));
1462 executor.shutdown();
1466 public void close() {
1471 public String readThriftIpForCommunication(String mipAddr) {
1472 File file = new File(CLUSTER_CONF_FILE);
1473 if (!file.exists()) {
1477 try (BufferedReader br = new BufferedReader(new FileReader(file))) {
1479 while ((line = br.readLine()) != null) {
1480 if (line.contains(mipAddr)) {
1482 return line.substring(line.lastIndexOf(" ") + 1);
1485 } catch (FileNotFoundException e) {
1487 } catch (IOException e) {
1488 LOG.error("Error reading {}", CLUSTER_CONF_FILE, e);
1493 public boolean isIpAvailable(String odlip) {
1496 if (odlip != null) {
1497 if ("127.0.0.1".equals(odlip)) {
1500 Enumeration networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1501 while (networkInterfaceEnumeration.hasMoreElements()) {
1502 NetworkInterface networkInterface = (NetworkInterface) networkInterfaceEnumeration.nextElement();
1503 Enumeration inetAddressEnumeration = networkInterface.getInetAddresses();
1504 while (inetAddressEnumeration.hasMoreElements()) {
1505 InetAddress inetAddress = (InetAddress) inetAddressEnumeration.nextElement();
1506 if (odlip.equals(inetAddress.getHostAddress())) {
1512 } catch (SocketException e) {
1518 public static long getStalePathtime(int defValue, AsId asId) {
1521 spt = getConfig().getGracefulRestart().getStalepathTime();
1522 } catch (NullPointerException e) {
1524 spt = asId.getStalepathTime();
1525 LOG.trace("BGP config/Stale-path time is not set using graceful");
1526 } catch (NullPointerException ignore) {
1527 LOG.trace("BGP AS id is not set using graceful");
1532 LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1538 public synchronized void bgpRestarted() {
1540 * If there a thread which in the process of stale cleanup, cancel it
1541 * and start a new thread (to avoid processing same again).
1543 if (previousReplayJobInProgress()) {
1544 cancelPreviousReplayJob();
1546 Runnable task = () -> {
1548 LOG.info("running bgp replay task ");
1549 if (get() == null) {
1550 String host = getConfigHost();
1551 int port = getConfigPort();
1552 LOG.info("connecting to bgp host {} ", host);
1554 boolean res = bgpRouter.connect(host, port);
1555 LOG.info("no config to push in bgp replay task ");
1558 setStaleStartTime(System.currentTimeMillis());
1559 LOG.info("started creating stale fibDSWriter map ");
1560 createStaleFibMap();
1561 setStaleEndTime(System.currentTimeMillis());
1562 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1563 LOG.info("started bgp config replay ");
1564 setCfgReplayStartTime(System.currentTimeMillis());
1567 } catch (TimeoutException | ExecutionException e) {
1568 LOG.error("Error while replaying routes. {}", e);
1570 setCfgReplayEndTime(System.currentTimeMillis());
1571 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1572 long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1573 Thread.sleep(routeSyncTime * 1000L);
1574 setStaleCleanupTime(routeSyncTime);
1575 new RouteCleanup().call();
1576 } catch (InterruptedException eCancel) {
1577 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1580 lastReplayJobFt = executor.submit(task);
1583 private boolean previousReplayJobInProgress() {
1584 return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1587 private void cancelPreviousReplayJob() {
1589 LOG.error("cancelling already running bgp replay task");
1590 lastReplayJobFt.cancel(true);
1591 lastReplayJobFt = null;
1593 } catch (InterruptedException e) {
1594 LOG.error("Failed to cancel previous replay job ", e);
1598 private static void doRouteSync() throws InterruptedException, TimeoutException, ExecutionException {
1599 BgpSyncHandle bsh = BgpSyncHandle.getInstance();
1600 LOG.error("Starting BGP route sync");
1602 bgpRouter.initRibSync(bsh);
1603 } catch (TException | BgpRouterException e) {
1604 LOG.error("Route sync aborted, exception when initializing", e);
1607 while (bsh.getState() != bsh.DONE) {
1608 Routes routes = null;
1610 routes = bgpRouter.doRibSync(bsh);
1611 } catch (TException | BgpRouterException e) {
1612 LOG.error("Route sync aborted, exception when syncing", e);
1615 Iterator<Update> updates = routes.getUpdatesIterator();
1616 while (updates.hasNext()) {
1617 Update update = updates.next();
1618 Map<String, Map<String, Long>> staleFibRdMap = BgpConfigurationManager.getStaledFibEntriesMap();
1619 String rd = update.getRd();
1620 String nexthop = update.getNexthop();
1622 // TODO: decide correct label here
1623 int label = update.getL3label();
1625 String prefix = update.getPrefix();
1626 int plen = update.getPrefixlen();
1629 // TODO: protocol type will not be available in "update"
1630 // use "rd" to query vrf table and obtain the protocol_type. Currently using PROTOCOL_EVPN as default.
1632 protocol_type.PROTOCOL_EVPN,
1639 update.getMacaddress(),
1641 update.getRoutermac()
1646 LOG.error("Ending BGP route-sync");
1647 bgpRouter.endRibSync(bsh);
1648 } catch (TException | BgpRouterException e) {
1653 /* onUpdatePushRoute
1654 * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1655 * - Entry compare shall include NextHop, Label.
1656 * - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1657 * - If entry not found, add to FIB Config DS.
1658 * - If entry found, but either Label/NextHop doesn't match.
1659 * - Update FIB Config DS with modified values.
1660 * - delete from Stale Map.
1663 public static void onUpdatePushRoute(protocol_type protocolType,
1673 throws InterruptedException, ExecutionException, TimeoutException {
1674 boolean addroute = false;
1676 VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1677 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1678 encapType = VrfEntry.EncapType.Vxlan;
1679 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = BgpUtil.getVpnInstanceOpData(dataBroker, rd);
1680 if (vpnInstanceOpDataEntry != null) {
1681 l3vni = vpnInstanceOpDataEntry.getL3vni();
1683 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1687 if (!staledFibEntriesMap.isEmpty()) {
1688 // restart Scenario, as MAP is not empty.
1689 Map<String, Long> map = staledFibEntriesMap.get(rd);
1691 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1692 Long labelInStaleMap = map.get(prefixNextHop);
1693 if (null == labelInStaleMap) {
1694 // New Entry, which happened to be added during restart.
1697 map.remove(prefixNextHop);
1698 if (isRouteModified(label, labelInStaleMap)) {
1699 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1700 // Existing entry, where in Label got modified during restart
1706 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1710 LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1711 // TODO: modify addFibEntryToDS signature
1712 fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, Collections.singletonList(nextHop),
1713 encapType, label, l3vni, routermac, RouteOrigin.BGP);
1714 LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1718 private static boolean isRouteModified(int label, Long labelInStaleMap) {
1719 return labelInStaleMap != null && !labelInStaleMap.equals(label);
1722 private static void replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1723 for (Neighbors nbr : neighbors) {
1725 br.addNeighbor(nbr.getAddress().getValue(),
1727 //itmProvider.buildTunnelsToDCGW(new IpAddress(nbr.getAddress().getValue().toCharArray()));
1728 } catch (TException | BgpRouterException e) {
1729 LOG.error("Replay:addNbr() received exception", e);
1732 EbgpMultihop en = nbr.getEbgpMultihop();
1735 br.addEbgpMultihop(en.getPeerIp().getValue(),
1736 en.getNhops().intValue());
1737 } catch (TException | BgpRouterException e) {
1738 LOG.error("Replay:addEBgp() received exception", e);
1741 UpdateSource us = nbr.getUpdateSource();
1744 br.addUpdateSource(us.getPeerIp().getValue(),
1745 us.getSourceIp().getValue());
1746 } catch (TException | BgpRouterException e) {
1747 LOG.error("Replay:addUS() received exception", e);
1750 List<AddressFamilies> afs = nbr.getAddressFamilies();
1752 for (AddressFamilies af : afs) {
1753 af_afi afi = af_afi.findByValue(af.getAfi().intValue());
1754 af_safi safi = af_safi.findByValue(af.getSafi().intValue());
1756 br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
1757 } catch (TException | BgpRouterException e) {
1758 LOG.error("Replay:addAf() received exception", e);
1765 public static String getConfigHost() {
1766 if (config == null) {
1767 return cHostStartup;
1769 ConfigServer ts = config.getConfigServer();
1770 return (ts == null ? cHostStartup : ts.getHost().getValue());
1773 public static int getConfigPort() {
1774 if (config == null) {
1775 return Integer.parseInt(cPortStartup);
1777 ConfigServer ts = config.getConfigServer();
1778 return (ts == null ? Integer.parseInt(cPortStartup) :
1779 ts.getPort().intValue());
1782 public static Bgp getConfig() {
1783 AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COOUNT);
1784 while (0 != bgpDSretryCount.decrementAndGet()) {
1786 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1787 InstanceIdentifier.create(Bgp.class)).orNull();
1788 } catch (ReadFailedException e) {
1789 //Config DS may not be up, so sleep for 1 second and retry
1790 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
1792 Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
1793 } catch (InterruptedException timerEx) {
1794 LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
1795 + "config DS availability", timerEx);
1799 LOG.error("failed to get bgp config");
1803 @SuppressWarnings("checkstyle:IllegalCatch")
1804 public synchronized void replay() throws InterruptedException, TimeoutException, ExecutionException {
1805 synchronized (bgpConfigurationManager) {
1806 String host = getConfigHost();
1807 int port = getConfigPort();
1808 LOG.error("connecting to bgp host {} ", host);
1810 boolean res = bgpRouter.connect(host, port);
1812 String msg = "Cannot connect to BGP config server at " + host + ":" + port;
1813 if (config != null) {
1814 msg += "; Configuration Replay aborted";
1819 config = getConfig();
1820 if (config == null) {
1821 LOG.error("bgp config is empty nothing to push to bgp");
1824 BgpRouter br = bgpRouter;
1825 AsId asId = config.getAsId();
1829 long asNum = asId.getLocalAs();
1830 IpAddress routerId = asId.getRouterId();
1831 Long spt = asId.getStalepathTime();
1832 Boolean afb = asId.isAnnounceFbit();
1833 String rid = (routerId == null) ? "" : new String(routerId.getValue());
1834 int stalepathTime = (int) getStalePathtime(0, config.getAsId());
1835 boolean announceFbit = true;
1837 br.startBgp(asNum, rid, stalepathTime, announceFbit);
1838 } catch (BgpRouterException bre) {
1839 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
1842 LOG.error("Replay: startBgp() received exception: \""
1843 + bre + "\"; " + ADD_WARN);
1845 } catch (TException e) {
1846 //not unusual. We may have restarted & BGP is already on
1847 LOG.error("Replay:startBgp() received exception: \"" + e + "\"");
1850 if (getBgpCounters() == null) {
1851 startBgpCountersTask();
1854 if (getBgpAlarms() == null) {
1855 startBgpAlarmsTask();
1858 Logging logging = config.getLogging();
1859 if (logging != null) {
1861 br.setLogging(logging.getFile(), logging.getLevel());
1862 } catch (TException | BgpRouterException e) {
1863 LOG.error("Replay:setLogging() received exception", e);
1867 GracefulRestart gracefulRestart = config.getGracefulRestart();
1868 if (gracefulRestart != null) {
1870 br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
1871 } catch (TException | BgpRouterException e) {
1872 LOG.error("Replay:addGr() received exception", e);
1876 List<Vrfs> vrfs = config.getVrfs();
1878 for (Vrfs vrf : vrfs) {
1880 br.addVrf(vrf.getLayerType(), vrf.getRd(), vrf.getImportRts(),
1881 vrf.getExportRts());
1882 } catch (TException | BgpRouterException e) {
1883 LOG.error("Replay:addVrf() received exception", e);
1888 List<Networks> ln = config.getNetworks();
1890 for (Networks net : ln) {
1891 String rd = net.getRd();
1892 String pfxlen = net.getPrefixLen();
1893 String nh = net.getNexthop().getValue();
1894 Long label = net.getLabel();
1895 int lbl = (label == null) ? 0 : label.intValue();
1896 int l3vni = (net.getL3vni() == null) ? 0 : net.getL3vni().intValue();
1897 if (rd == null && lbl > 0) {
1898 //LU prefix is being deleted.
1899 rd = Integer.toString(lbl);
1902 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
1903 int ethernetTag = net.getEthtag().intValue();
1904 String esi = net.getEsi();
1905 String macaddress = net.getMacaddress();
1906 EncapType encapType = net.getEncapType();
1907 String routerMac = net.getRoutermac();
1910 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, BgpUtil.convertToThriftProtocolType(protocolType),
1911 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1912 } catch (Exception e) {
1913 LOG.error("Replay:addPfx() received exception", e);
1917 List<Neighbors> neighbors = config.getNeighbors();
1918 if (neighbors != null) {
1919 LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
1920 replayNbrConfig(neighbors, br);
1922 LOG.error("no Neighbors present for replay config ");
1925 List<Multipath> multipaths = config.getMultipath();
1927 if (multipaths != null) {
1928 for (Multipath multipath: multipaths) {
1929 if (multipath != null) {
1930 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1931 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1934 if (multipath.isMultipathEnabled()) {
1935 br.enableMultipath(afi, safi);
1937 br.disableMultipath(afi, safi);
1939 } catch (TException | BgpRouterException e) {
1940 LOG.info("Replay:multipaths() received exception: \"" + e + "\"");
1945 List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
1946 if (vrfMaxpaths != null) {
1947 for (VrfMaxpath vrfMaxpath: vrfMaxpaths) {
1949 br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
1950 } catch (TException | BgpRouterException e) {
1951 LOG.info("Replay:vrfMaxPath() received exception: \"" + e + "\"");
1958 private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
1959 BgpUtil.update(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1962 private <T extends DataObject> void asyncWrite(InstanceIdentifier<T> iid, T dto) {
1963 BgpUtil.write(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
1966 private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
1967 BgpUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, iid);
1970 public synchronized void startConfig(String bgpHost, int thriftPort) {
1971 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
1972 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
1973 InstanceIdentifier<ConfigServer> iid = iib.build();
1974 Ipv4Address ipAddr = new Ipv4Address(bgpHost);
1975 ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
1976 .setPort((long) thriftPort).build();
1980 public synchronized void startBgp(long as, String routerId, int spt, boolean fbit) {
1981 IpAddress rid = (routerId == null) ? null : new IpAddress(routerId.toCharArray());
1982 Long staleTime = (long) spt;
1983 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
1984 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
1985 InstanceIdentifier<AsId> iid = iib.build();
1986 AsId dto = new AsIdBuilder().setLocalAs(as)
1988 .setStalepathTime(staleTime)
1989 .setAnnounceFbit(fbit).build();
1993 public synchronized void addLogging(String fileName, String logLevel) {
1994 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
1995 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
1996 InstanceIdentifier<Logging> iid = iib.build();
1997 Logging dto = new LoggingBuilder().setFile(fileName)
1998 .setLevel(logLevel).build();
2002 public synchronized void addGracefulRestart(int staleTime) {
2003 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2004 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2005 InstanceIdentifier<GracefulRestart> iid = iib.build();
2006 GracefulRestart dto = new GracefulRestartBuilder()
2007 .setStalepathTime((long) staleTime).build();
2011 public synchronized void addNeighbor(
2012 String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2013 addNeighborAux(nbrIp, remoteAs, md5Secret);
2014 } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2016 public synchronized void addNeighbor(String nbrIp, long remoteAs) {
2017 addNeighborAux(nbrIp, remoteAs, null);
2018 } // public addNeighbor(nbrIp, remoteAs)
2020 private void addNeighborAux(String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2021 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2022 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2023 InstanceIdentifier.builder(Bgp.class)
2024 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2025 InstanceIdentifier<Neighbors> iid = iib.build();
2026 TcpSecurityOption tcpSecOption = null;
2027 if (md5Secret != null) {
2028 tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2029 } // else let tcpSecOption be null
2030 Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2031 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2033 } // private addNeighborAux(nbrIp, remoteAs, md5Secret)
2035 public synchronized void addUpdateSource(String nbrIp, String srcIp) {
2036 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2037 Ipv4Address srcAddr = new Ipv4Address(srcIp);
2038 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2039 InstanceIdentifier.builder(Bgp.class)
2040 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2041 .child(UpdateSource.class);
2042 InstanceIdentifier<UpdateSource> iid = iib.build();
2043 UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2044 .setSourceIp(srcAddr).build();
2048 public synchronized void addEbgpMultihop(String nbrIp, int hops) {
2049 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2050 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2051 InstanceIdentifier.builder(Bgp.class)
2052 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2053 .child(EbgpMultihop.class);
2054 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2055 EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2056 .setNhops((long) hops).build();
2060 public synchronized void addAddressFamily(String nbrIp, int afi, int safi) {
2061 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2062 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2063 InstanceIdentifier.builder(Bgp.class)
2064 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2065 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2066 InstanceIdentifier<AddressFamilies> iid = iib.build();
2067 AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2068 .setAfi((long) afi).setSafi((long) safi).build();
2072 public synchronized void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2073 VrfEntry.EncapType encapType, int lbl, long l3vni, String gatewayMac, int addressFamily) {
2074 for (String nh : nhList) {
2075 Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2076 Long label = (long) lbl;
2077 Long afi = (long) addressFamily;
2078 InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2079 .child(Networks.class, new NetworksKey(pfx, rd)).build();
2080 NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2081 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG)
2083 buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, macAddress, gatewayMac);
2084 update(iid, networksBuilder.build());
2088 private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
2089 long l3vni, String macAddress, String gatewayMac) {
2090 if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2091 builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2092 .setEncapType(EncapType.GRE);
2094 builder.setL3vni(l3vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2095 .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2099 // TODO: add LayerType as arg - supports command
2100 public synchronized void addVrf(String rd, List<String> irts, List<String> erts, LayerType layerType) {
2101 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2102 InstanceIdentifier.builder(Bgp.class)
2103 .child(Vrfs.class, new VrfsKey(rd));
2104 InstanceIdentifier<Vrfs> iid = iib.build();
2105 Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2106 .setExportRts(erts).setLayerType(layerType).build();
2108 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2109 } catch (TransactionCommitFailedException e) {
2110 LOG.error("Error adding VRF to datastore", e);
2111 throw new RuntimeException(e);
2115 public synchronized void stopConfig() {
2116 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2117 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2118 InstanceIdentifier<ConfigServer> iid = iib.build();
2122 public synchronized void stopBgp() {
2123 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2124 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2125 InstanceIdentifier<AsId> iid = iib.build();
2129 public synchronized void delLogging() {
2130 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2131 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2132 InstanceIdentifier<Logging> iid = iib.build();
2136 public synchronized void delGracefulRestart() {
2137 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2138 InstanceIdentifier.builder(Bgp.class)
2139 .child(GracefulRestart.class);
2140 InstanceIdentifier<GracefulRestart> iid = iib.build();
2144 public synchronized void delNeighbor(String nbrIp) {
2145 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2146 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2147 InstanceIdentifier.builder(Bgp.class)
2148 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2149 InstanceIdentifier<Neighbors> iid = iib.build();
2153 public synchronized void delUpdateSource(String nbrIp) {
2154 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2155 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2156 InstanceIdentifier.builder(Bgp.class)
2157 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2158 .child(UpdateSource.class);
2159 InstanceIdentifier<UpdateSource> iid = iib.build();
2163 public synchronized void delEbgpMultihop(String nbrIp) {
2164 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2165 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2166 InstanceIdentifier.builder(Bgp.class)
2167 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2168 .child(EbgpMultihop.class);
2169 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2173 public synchronized void delAddressFamily(String nbrIp, int afi, int safi) {
2174 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2175 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2176 InstanceIdentifier.builder(Bgp.class)
2177 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2178 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2179 InstanceIdentifier<AddressFamilies> iid = iib.build();
2183 public synchronized void delPrefix(String rd, String pfx, int afi) {
2184 InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2185 InstanceIdentifier.builder(Bgp.class)
2186 .child(Networks.class, new NetworksKey(pfx, rd));
2187 InstanceIdentifier<Networks> iid = iib.build();
2191 public synchronized void delVrf(String rd) {
2192 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2193 InstanceIdentifier.builder(Bgp.class)
2194 .child(Vrfs.class, new VrfsKey(rd));
2195 InstanceIdentifier<Vrfs> iid = iib.build();
2199 public synchronized void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2200 long lafi = afi.getValue();
2201 long lsafi = safi.getValue();
2203 InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2206 .child(Multipath.class,
2207 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2209 Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2210 update(iib.build(), dto);
2213 public synchronized void multipaths(String rd, int maxpath) {
2214 InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2217 .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2219 VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2220 update(iib.build(), dto);
2223 static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
2226 * Remove Stale Marked Routes after timer expiry.
2228 class RouteCleanup implements Callable<Integer> {
2231 public Integer call() {
2234 if (staledFibEntriesMap.isEmpty()) {
2235 LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2237 for (String rd : staledFibEntriesMap.keySet()) {
2238 if (Thread.interrupted()) {
2241 Map<String, Long> map = staledFibEntriesMap.get(rd);
2243 for (String key : map.keySet()) {
2244 if (Thread.interrupted()) {
2247 String prefix = extractPrefix(key);
2248 String nextHop = extractNextHop(key);
2250 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
2251 rd, prefix, nextHop);
2252 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
2258 staledFibEntriesMap.clear();
2260 LOG.error("cleared {} stale routes after bgp restart", totalCleared);
2266 * BGP restart scenario, ODL-BGP manager was/is running.
2267 * On re-sync notification, Get a copy of FIB database.
2269 public static void createStaleFibMap() {
2270 totalStaledCount = 0;
2273 * at the time Stale FIB creation, Wait till all PENDING write transaction
2274 * to complete (or)wait for max timeout value of STALE_FIB_WAIT Seconds.
2276 int retry = STALE_FIB_WAIT;
2277 while ((BgpUtil.getGetPendingWrTransaction() != 0) && (retry > 0)) {
2281 LOG.error("TimeOut occured {} seconds, in waiting stale fibDSWriter create", STALE_FIB_WAIT);
2284 staledFibEntriesMap.clear();
2285 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2286 DataBroker db = BgpUtil.getBroker();
2288 LOG.error("Couldn't find BgpUtil dataBroker while creating createStaleFibMap");
2292 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(BgpUtil.getBroker(),
2293 LogicalDatastoreType.CONFIGURATION, id);
2294 if (fibEntries.isPresent()) {
2295 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2296 for (VrfTables vrfTable : staleVrfTables) {
2297 Map<String, Long> staleFibEntMap = new HashMap<>();
2298 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2299 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2300 //Stale marking and cleanup is only meant for the routes learned through BGP.
2303 if (Thread.interrupted()) {
2307 //Create MAP from staleVrfTables.
2308 vrfEntry.getRoutePaths()
2310 routePath -> staleFibEntMap.put(
2311 appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2312 routePath.getNexthopAddress()), routePath.getLabel()));
2314 staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2317 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2319 } catch (InterruptedException | ReadFailedException e) {
2320 LOG.error("createStaleFibMap:: error ", e);
2322 LOG.error("created {} staled entries ", totalStaledCount);
2325 //map<rd, map<prefix/len:nexthop, label>>
2326 public static Map<String, Map<String, Long>> getStaledFibEntriesMap() {
2327 return staledFibEntriesMap;
2330 //TODO: below function is for testing purpose with cli
2331 public static void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
2332 LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
2333 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
2336 public boolean isBgpConnected() {
2337 return bgpRouter.isBgpConnected();
2340 public long getLastConnectedTS() {
2341 return bgpRouter.getLastConnectedTS();
2344 public long getConnectTS() {
2345 return bgpRouter.getConnectTS();
2348 public long getStartTS() {
2349 return bgpRouter.getStartTS();
2352 public static int getTotalStaledCount() {
2353 return totalStaledCount;
2356 public static int getTotalCleared() {
2357 return totalCleared;
2360 public Timer getBgpCountersTimer() {
2361 return bgpCountersTimer;
2364 public BgpCounters getBgpCounters() {
2368 public void setBgpCountersTimer(Timer timer) {
2369 bgpCountersTimer = timer;
2372 public void setBgpAlarmsTimer(Timer timer) {
2373 bgpAlarmsTimer = timer;
2376 public void startBgpCountersTask() {
2377 if (getBgpCounters() == null) {
2378 bgpCounters = new BgpCounters(bgpConfigurationManager.getBgpSdncMipIp());
2379 setBgpCountersTimer(new Timer(true));
2380 getBgpCountersTimer().scheduleAtFixedRate(bgpCounters, 0, 120 * 1000);
2381 LOG.info("Bgp Counters task scheduled for every two minutes.");
2383 bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2387 public void stopBgpCountersTask() {
2388 Timer timer = getBgpCountersTimer();
2389 if (getBgpCounters() != null) {
2391 setBgpCountersTimer(null);
2396 public void startBgpAlarmsTask() {
2397 if (getBgpAlarms() == null) {
2398 bgpAlarms = new BgpAlarms(this);
2399 setBgpAlarmsTimer(new Timer(true));
2400 getBgpAlarmsTimer().scheduleAtFixedRate(bgpAlarms, 0, 60 * 1000);
2401 LOG.info("Bgp Alarms task scheduled for every minute.");
2405 public void stopBgpAlarmsTask() {
2406 Timer timer = getBgpAlarmsTimer();
2407 if (getBgpAlarms() != null) {
2409 setBgpAlarmsTimer(null);
2414 public Timer getBgpAlarmsTimer() {
2415 return bgpAlarmsTimer;
2418 public BgpAlarms getBgpAlarms() {
2422 private static String appendNextHopToPrefix(String prefix, String nextHop) {
2423 return prefix + ":" + nextHop;
2426 private static String extractPrefix(String prefixNextHop) {
2427 return prefixNextHop.split(":")[0];
2430 private static String extractNextHop(String prefixNextHop) {
2431 return prefixNextHop.split(":")[1];