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 com.google.common.util.concurrent.ThreadFactoryBuilder;
12 import io.netty.util.concurrent.GlobalEventExecutor;
13 import java.io.IOException;
14 import java.lang.reflect.Constructor;
15 import java.lang.reflect.InvocationTargetException;
16 import java.net.InetAddress;
17 import java.net.NetworkInterface;
18 import java.net.SocketException;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.Enumeration;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
27 import java.util.Objects;
28 import java.util.Timer;
29 import java.util.concurrent.Callable;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Executors;
34 import java.util.concurrent.Future;
35 import java.util.concurrent.ScheduledExecutorService;
36 import java.util.concurrent.ScheduledFuture;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.TimeoutException;
39 import java.util.concurrent.atomic.AtomicInteger;
40 import java.util.concurrent.atomic.AtomicReference;
41 import javax.annotation.Nullable;
42 import javax.annotation.PreDestroy;
43 import javax.inject.Inject;
44 import javax.inject.Singleton;
45 import org.apache.thrift.TApplicationException;
46 import org.apache.thrift.TException;
47 import org.apache.thrift.transport.TTransport;
48 import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
49 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
50 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
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.clustering.EntityOwnershipUtils;
58 import org.opendaylight.infrautils.metrics.MetricProvider;
59 import org.opendaylight.mdsal.eos.binding.api.Entity;
60 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
61 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
62 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
63 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
64 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
65 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
66 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
67 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
68 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
69 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
70 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
71 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
72 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
73 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
74 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
75 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
76 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
77 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
78 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
79 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
80 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
81 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
82 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
83 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
84 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
85 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
86 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
87 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
88 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
89 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
90 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
91 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Multipath;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathBuilder;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathKey;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
102 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
103 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
104 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpath;
105 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathKey;
107 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
108 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
109 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
110 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
111 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
112 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
113 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
114 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
115 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
116 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
117 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrf;
118 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrfBuilder;
119 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
120 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOption;
121 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
122 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
123 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
129 import org.opendaylight.yangtools.yang.binding.DataObject;
130 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
131 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
132 import org.osgi.framework.BundleContext;
133 import org.slf4j.Logger;
134 import org.slf4j.LoggerFactory;
137 public class BgpConfigurationManager {
138 private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
140 // to have stale FIB map (RD, Prefix)
141 // number of seconds wait for route sync-up between ODL and BGP
142 private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
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 = "255.255.255.255"; // Invalid Host IP
150 private static final String DEF_CPORT = "0"; // Invalid Port
151 private static final String DEF_BGP_SDNC_MIP = "127.0.0.1";
152 private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.sdnc.mip";
153 private static final int RESTART_DEFAULT_GR = 90;
154 private static final int DS_RETRY_COUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
155 private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
156 private static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
157 private static final String BGP_ENTITY_NAME = "bgp";
158 private static final String ADD_WARN = "Config store updated; undo with Delete if needed.";
159 private static final String DEL_WARN = "Config store updated; undo with Add if needed.";
160 private static final String UPD_WARN = "Update operation not supported; Config store updated;"
161 + " restore with another Update if needed.";
163 private static final Class<?>[] REACTORS = {
164 ConfigServerReactor.class, AsIdReactor.class,
165 GracefulRestartReactor.class, LoggingReactor.class,
166 NeighborsReactor.class, UpdateSourceReactor.class,
167 EbgpMultihopReactor.class, AddressFamiliesReactor.class,
168 NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
169 MultipathReactor.class, VrfMaxpathReactor.class
172 private IBgpManager bgpManager;
173 private final DataBroker dataBroker;
174 private final FibDSWriter fibDSWriter;
175 private final IVpnLinkService vpnLinkService;
176 private final BundleContext bundleContext;
177 private final BgpUtil bgpUtil;
178 private volatile Bgp config;
179 private final BgpRouter bgpRouter;
180 private final BgpSyncHandle bgpSyncHandle = new BgpSyncHandle();
181 private BgpThriftService updateServer;
183 private final CountDownLatch initer = new CountDownLatch(1);
185 private final String hostStartup;
186 private final String portStartup;
188 private final AtomicReference<BgpCounters> bgpCountersReference = new AtomicReference<>();
189 private ScheduledFuture<?> bgpCountersTask;
191 private final AtomicReference<BgpAlarms> bgpAlarmsReference = new AtomicReference<>();
192 private ScheduledFuture<?> bgpAlarmsTask;
194 private Future<?> lastReplayJobFt;
195 private ScheduledFuture<?> routeCleanupFuture;
197 private long staleStartTime;
198 private long staleEndTime;
199 private long cfgReplayStartTime;
200 private long cfgReplayEndTime;
201 private long staleCleanupTime;
202 private int totalStaledCount;
203 private int totalCleared;
204 private int totalExternalRoutes;
205 private int totalExternalMacRoutes;
207 private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
208 new ThreadFactoryBuilder().setNameFormat("BgpConfigurationManager-%d").setDaemon(true).build());
211 * this map store the new address families to send to quagga. When it is sended you must clear it.
212 * The keys String are rd (route distinguisher).
214 private final ConcurrentHashMap<String, List<AddressFamiliesVrf>> mapNewAdFamily = new ConcurrentHashMap<>();
216 // map<rd, map<prefix/len:nexthop, label>>
217 private final Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
219 // map<rd, map<tep-ip, map<mac, l2vni>>>
220 private final Map<String, Map<String, Map<String, Long>>> rt2TepMap = new ConcurrentHashMap<>();
222 private final List<AutoCloseable> listeners = new ArrayList<>();
224 private final EntityOwnershipUtils entityOwnershipUtils;
225 private final EntityOwnershipCandidateRegistration candidateRegistration;
226 private final EntityOwnershipListenerRegistration entityListenerRegistration;
227 private final MetricProvider metricProvider;
230 public BgpConfigurationManager(final DataBroker dataBroker,
231 final EntityOwnershipService entityOwnershipService,
232 final FibDSWriter fibDSWriter,
233 final IVpnLinkService vpnLinkSrvce,
234 final BundleContext bundleContext,
235 final BgpUtil bgpUtil,
236 final MetricProvider metricProvider)
237 throws InterruptedException, ExecutionException, TimeoutException {
238 this.dataBroker = dataBroker;
239 this.fibDSWriter = fibDSWriter;
240 this.vpnLinkService = vpnLinkSrvce;
241 this.bundleContext = bundleContext;
242 this.bgpUtil = bgpUtil;
243 this.metricProvider = metricProvider;
244 String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
245 hostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
246 portStartup = getProperty(CONFIG_PORT, DEF_CPORT);
247 LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
248 + hostStartup + ":" + portStartup);
249 VtyshCli.setHostAddr(hostStartup);
250 ClearBgpCli.setHostAddr(hostStartup);
251 bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner);
254 entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
256 candidateRegistration = registerEntityCandidate(entityOwnershipService);
257 entityListenerRegistration = registerEntityListener(entityOwnershipService);
259 LOG.info("BGP Configuration manager initialized");
262 GlobalEventExecutor.INSTANCE.execute(() -> {
263 final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
264 IBgpManager.class, bundleContext);
265 bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
266 updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, this);
267 updateServer.start();
268 LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
272 public String getBgpSdncMipIp() {
273 return getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
276 public long getStaleCleanupTime() {
277 return staleCleanupTime;
280 public void setStaleCleanupTime(long staleCleanupTime) {
281 this.staleCleanupTime = staleCleanupTime;
284 public long getCfgReplayEndTime() {
285 return cfgReplayEndTime;
288 public void setCfgReplayEndTime(long cfgReplayEndTime) {
289 this.cfgReplayEndTime = cfgReplayEndTime;
292 public long getCfgReplayStartTime() {
293 return cfgReplayStartTime;
296 public void setCfgReplayStartTime(long cfgReplayStartTime) {
297 this.cfgReplayStartTime = cfgReplayStartTime;
300 public long getStaleEndTime() {
304 public void setStaleEndTime(long staleEndTime) {
305 this.staleEndTime = staleEndTime;
308 public long getStaleStartTime() {
309 return staleStartTime;
312 public void setStaleStartTime(long staleStartTime) {
313 this.staleStartTime = staleStartTime;
316 private Object createListener(Class<?> cls) {
318 Constructor<?> ctor = cls.getConstructor(BgpConfigurationManager.class);
319 return ctor.newInstance(this);
320 } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
322 LOG.error("Failed to create listener object", e);
327 private void registerCallbacks() {
328 for (Class<?> reactor : REACTORS) {
329 Object obj = createListener(reactor);
331 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
332 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
338 @SuppressWarnings("checkstyle:IllegalCatch")
340 public void close() {
343 if (updateServer != null) {
347 if (candidateRegistration != null) {
348 candidateRegistration.close();
351 entityListenerRegistration.close();
353 listeners.forEach(l -> {
356 } catch (Exception e) {
357 LOG.warn("Error closing {}", l ,e);
361 LOG.info("{} close", getClass().getSimpleName());
364 private String getProperty(String var, String def) {
365 String property = bundleContext.getProperty(var);
366 return property == null ? def : property;
369 private EntityOwnershipCandidateRegistration registerEntityCandidate(
370 final EntityOwnershipService entityOwnershipService) {
372 return entityOwnershipService.registerCandidate(
373 new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME));
374 } catch (CandidateAlreadyRegisteredException e) {
375 LOG.error("failed to register bgp entity", e);
380 private EntityOwnershipListenerRegistration registerEntityListener(
381 final EntityOwnershipService entityOwnershipService) {
382 return entityOwnershipService.registerListener(BGP_ENTITY_TYPE_FOR_OWNERSHIP, ownershipChange -> {
383 LOG.trace("entity owner change event fired: {}", ownershipChange);
385 if (ownershipChange.getState() == EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED) {
386 LOG.trace("This PL is the Owner");
390 LOG.debug("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
391 ownershipChange.getState().isOwner());
396 public boolean isBGPEntityOwner() {
397 return entityOwnershipUtils.isEntityOwner(new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME), 0, 1);
401 config = getConfig();
405 public class ConfigServerReactor
406 extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
407 implements ClusteredDataTreeChangeListener<ConfigServer> {
408 private static final String YANG_OBJ = "config-server ";
410 public ConfigServerReactor() {
411 super(ConfigServer.class, ConfigServerReactor.class);
415 protected void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
416 LOG.trace("received bgp connect config host {}", val.getHost().getValue());
417 if (!isBGPEntityOwner()) {
423 } catch (InterruptedException e) {
426 LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
427 bgpRouter.configServerUpdated();
428 synchronized (BgpConfigurationManager.this) {
429 boolean res = bgpRouter.connect(val.getHost().getValue(),
430 val.getPort().intValue());
432 LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
435 VtyshCli.setHostAddr(val.getHost().getValue());
436 ClearBgpCli.setHostAddr(val.getHost().getValue());
440 protected ConfigServerReactor getDataTreeChangeListener() {
441 return ConfigServerReactor.this;
445 protected InstanceIdentifier<ConfigServer> getWildCardPath() {
446 return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
450 protected void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
451 LOG.trace("received bgp disconnect");
452 if (!isBGPEntityOwner()) {
456 bgpRouter.configServerUpdated();
458 synchronized (BgpConfigurationManager.this) {
459 bgpRouter.disconnect();
464 protected void update(InstanceIdentifier<ConfigServer> iid,
465 ConfigServer oldval, ConfigServer newval) {
466 LOG.trace("received bgp Connection update");
467 if (!isBGPEntityOwner()) {
470 LOG.error(YANG_OBJ + UPD_WARN);
474 private BgpRouter getClient(String yangObj) {
475 if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
476 LOG.warn("{}: configuration received when BGP is inactive", yangObj);
482 public class AsIdReactor
483 extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
484 implements ClusteredDataTreeChangeListener<AsId> {
486 private static final String YANG_OBJ = "as-id ";
488 public AsIdReactor() {
489 super(AsId.class, AsIdReactor.class);
493 protected void add(InstanceIdentifier<AsId> iid, AsId val) {
494 LOG.error("received bgp add asid {}", val);
495 if (!isBGPEntityOwner()) {
498 LOG.debug("received add router config asNum {}", val.getLocalAs());
499 synchronized (BgpConfigurationManager.this) {
500 BgpRouter br = getClient(YANG_OBJ);
502 LOG.debug("{} Unable to process add for asNum {}; {}", YANG_OBJ, val.getLocalAs(),
503 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
508 startBgpCountersTask();
509 startBgpAlarmsTask();
514 protected AsIdReactor getDataTreeChangeListener() {
515 return AsIdReactor.this;
519 protected InstanceIdentifier<AsId> getWildCardPath() {
520 return InstanceIdentifier.create(Bgp.class).child(AsId.class);
524 protected void remove(InstanceIdentifier<AsId> iid, AsId val) {
525 LOG.error("received delete router config asNum {}", val.getLocalAs());
526 if (!isBGPEntityOwner()) {
529 synchronized (BgpConfigurationManager.this) {
530 long asNum = val.getLocalAs();
531 BgpRouter br = getClient(YANG_OBJ);
533 LOG.debug("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
534 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
539 } catch (TException | BgpRouterException e) {
540 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
543 stopBgpCountersTask();
546 Bgp conf = getConfig();
548 LOG.error("Config Null while removing the as-id");
551 LOG.debug("Removing external routes from FIB");
552 deleteExternalFibRoutes();
553 List<Neighbors> nbrs = conf.getNeighbors();
554 if (nbrs != null && nbrs.size() > 0) {
555 LOG.error("Tring to remove the as-id when neighbor config is already present");
556 for (Neighbors nbr : nbrs) {
557 LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
558 delNeighbor(nbr.getAddress().getValue());
565 protected void update(InstanceIdentifier<AsId> iid,
566 AsId oldval, AsId newval) {
567 if (!isBGPEntityOwner()) {
570 LOG.error(YANG_OBJ + UPD_WARN);
574 public class GracefulRestartReactor
575 extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
576 implements ClusteredDataTreeChangeListener<GracefulRestart> {
578 private static final String YANG_OBJ = "graceful-restart ";
580 public GracefulRestartReactor() {
581 super(GracefulRestart.class, GracefulRestartReactor.class);
585 protected void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
586 if (!isBGPEntityOwner()) {
589 synchronized (BgpConfigurationManager.this) {
590 int stalePathTime = val.getStalepathTime().intValue();
591 BgpRouter br = getClient(YANG_OBJ);
593 LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
594 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
598 br.addGracefulRestart(stalePathTime);
599 } catch (TException | BgpRouterException e) {
600 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
606 protected GracefulRestartReactor getDataTreeChangeListener() {
607 return GracefulRestartReactor.this;
611 protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
612 return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
616 protected void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
617 if (!isBGPEntityOwner()) {
620 LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
621 synchronized (BgpConfigurationManager.this) {
622 BgpRouter br = getClient(YANG_OBJ);
624 LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
625 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
629 br.delGracefulRestart();
630 } catch (TException | BgpRouterException e) {
631 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
637 protected void update(InstanceIdentifier<GracefulRestart> iid,
638 GracefulRestart oldval, GracefulRestart newval) {
639 if (!isBGPEntityOwner()) {
642 LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
643 synchronized (BgpConfigurationManager.this) {
644 int stalePathTime = newval.getStalepathTime().intValue();
645 BgpRouter br = getClient(YANG_OBJ);
647 LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
648 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
652 br.addGracefulRestart(stalePathTime);
653 } catch (TException | BgpRouterException e) {
654 LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
660 public class LoggingReactor
661 extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
662 implements ClusteredDataTreeChangeListener<Logging> {
664 private static final String YANG_OBJ = "logging ";
666 public LoggingReactor() {
667 super(Logging.class, LoggingReactor.class);
671 protected void add(InstanceIdentifier<Logging> iid, Logging val) {
672 if (!isBGPEntityOwner()) {
675 synchronized (BgpConfigurationManager.this) {
676 BgpRouter br = getClient(YANG_OBJ);
678 LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
679 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
683 br.setLogging(val.getFile(), val.getLevel());
684 } catch (TException | BgpRouterException e) {
685 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
691 protected LoggingReactor getDataTreeChangeListener() {
692 return LoggingReactor.this;
696 protected InstanceIdentifier<Logging> getWildCardPath() {
697 return InstanceIdentifier.create(Bgp.class).child(Logging.class);
701 protected void remove(InstanceIdentifier<Logging> iid, Logging val) {
702 if (!isBGPEntityOwner()) {
705 LOG.debug("received remove Logging config val {}", val.getLevel());
706 synchronized (BgpConfigurationManager.this) {
707 BgpRouter br = getClient(YANG_OBJ);
709 LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
710 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
714 br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
715 } catch (TException | BgpRouterException e) {
716 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
722 protected void update(InstanceIdentifier<Logging> iid,
723 Logging oldval, Logging newval) {
724 if (!isBGPEntityOwner()) {
727 synchronized (BgpConfigurationManager.this) {
728 BgpRouter br = getClient(YANG_OBJ);
730 LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
731 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
735 br.setLogging(newval.getFile(), newval.getLevel());
736 } catch (TException | BgpRouterException e) {
737 LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
743 public class NeighborsReactor
744 extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
745 implements ClusteredDataTreeChangeListener<Neighbors> {
747 private static final String YANG_OBJ = "neighbors ";
749 public NeighborsReactor() {
750 super(Neighbors.class, NeighborsReactor.class);
754 protected void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
755 if (!isBGPEntityOwner()) {
758 LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
759 synchronized (BgpConfigurationManager.this) {
760 String peerIp = val.getAddress().getValue();
761 long as = val.getRemoteAs();
762 final String md5Secret = extractMd5Secret(val);
763 BgpRouter br = getClient(YANG_OBJ);
765 LOG.debug("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
766 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
770 //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
771 br.addNeighbor(peerIp, as, md5Secret);
773 } catch (TException | BgpRouterException e) {
774 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
780 protected NeighborsReactor getDataTreeChangeListener() {
781 return NeighborsReactor.this;
785 protected InstanceIdentifier<Neighbors> getWildCardPath() {
786 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
790 protected void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
791 if (!isBGPEntityOwner()) {
794 LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
795 synchronized (BgpConfigurationManager.this) {
796 String peerIp = val.getAddress().getValue();
797 BgpRouter br = getClient(YANG_OBJ);
799 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
800 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
804 //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
805 br.delNeighbor(peerIp);
806 } catch (TException | BgpRouterException e) {
807 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
810 final BgpAlarms bgpAlarms = getBgpAlarms();
811 if (bgpAlarms != null) {
812 bgpAlarms.clearBgpNbrDownAlarm(peerIp);
818 protected void update(InstanceIdentifier<Neighbors> iid,
819 Neighbors oldval, Neighbors newval) {
820 if (!isBGPEntityOwner()) {
823 //purposefully nothing to do.
827 public class EbgpMultihopReactor
828 extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
829 implements ClusteredDataTreeChangeListener<EbgpMultihop> {
831 private static final String YANG_OBJ = "ebgp-multihop ";
833 public EbgpMultihopReactor() {
834 super(EbgpMultihop.class, EbgpMultihopReactor.class);
838 protected void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
839 if (!isBGPEntityOwner()) {
842 LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
843 synchronized (BgpConfigurationManager.this) {
844 String peerIp = val.getPeerIp().getValue();
845 BgpRouter br = getClient(YANG_OBJ);
847 LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
848 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
852 br.addEbgpMultihop(peerIp, val.getNhops().intValue());
853 } catch (TException | BgpRouterException e) {
854 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
860 protected EbgpMultihopReactor getDataTreeChangeListener() {
861 return EbgpMultihopReactor.this;
865 protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
866 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
870 protected void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
871 if (!isBGPEntityOwner()) {
874 LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
875 synchronized (BgpConfigurationManager.this) {
876 String peerIp = val.getPeerIp().getValue();
877 BgpRouter br = getClient(YANG_OBJ);
879 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
880 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
884 br.delEbgpMultihop(peerIp);
885 } catch (TException | BgpRouterException e) {
886 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
892 protected void update(InstanceIdentifier<EbgpMultihop> iid,
893 EbgpMultihop oldval, EbgpMultihop newval) {
894 if (!isBGPEntityOwner()) {
897 LOG.error(YANG_OBJ + UPD_WARN);
901 public class UpdateSourceReactor
902 extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
903 implements ClusteredDataTreeChangeListener<UpdateSource> {
905 private static final String YANG_OBJ = "update-source ";
907 public UpdateSourceReactor() {
908 super(UpdateSource.class, UpdateSourceReactor.class);
912 protected void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
913 if (!isBGPEntityOwner()) {
916 LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
917 synchronized (BgpConfigurationManager.this) {
918 String peerIp = val.getPeerIp().getValue();
919 BgpRouter br = getClient(YANG_OBJ);
921 LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
922 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
926 br.addUpdateSource(peerIp, val.getSourceIp().getValue());
927 } catch (TException | BgpRouterException e) {
928 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
934 protected UpdateSourceReactor getDataTreeChangeListener() {
935 return UpdateSourceReactor.this;
939 protected InstanceIdentifier<UpdateSource> getWildCardPath() {
940 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
944 protected void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
945 if (!isBGPEntityOwner()) {
948 LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
949 synchronized (BgpConfigurationManager.this) {
950 String peerIp = val.getPeerIp().getValue();
951 BgpRouter br = getClient(YANG_OBJ);
953 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
954 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
958 br.delUpdateSource(peerIp);
959 } catch (TException | BgpRouterException e) {
960 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
966 protected void update(InstanceIdentifier<UpdateSource> iid,
967 UpdateSource oldval, UpdateSource newval) {
968 if (!isBGPEntityOwner()) {
971 LOG.error(YANG_OBJ + UPD_WARN);
975 public class AddressFamiliesReactor
976 extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
977 implements ClusteredDataTreeChangeListener<AddressFamilies> {
979 private static final String YANG_OBJ = "address-families ";
981 public AddressFamiliesReactor() {
982 super(AddressFamilies.class, AddressFamiliesReactor.class);
986 protected void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
987 if (!isBGPEntityOwner()) {
990 LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
991 synchronized (BgpConfigurationManager.this) {
992 String peerIp = val.getPeerIp().getValue();
993 BgpRouter br = getClient(YANG_OBJ);
995 LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
996 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
999 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1000 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1002 br.addAddressFamily(peerIp, afi, safi);
1003 } catch (TException | BgpRouterException e) {
1004 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1010 protected AddressFamiliesReactor getDataTreeChangeListener() {
1011 return AddressFamiliesReactor.this;
1015 protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
1016 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
1020 protected void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1021 if (!isBGPEntityOwner()) {
1024 LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
1025 synchronized (BgpConfigurationManager.this) {
1026 String peerIp = val.getPeerIp().getValue();
1027 BgpRouter br = getClient(YANG_OBJ);
1029 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
1030 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1033 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1034 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1036 br.delAddressFamily(peerIp, afi, safi);
1037 } catch (TException | BgpRouterException e) {
1038 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1044 protected void update(InstanceIdentifier<AddressFamilies> iid,
1045 AddressFamilies oldval, AddressFamilies newval) {
1046 if (!isBGPEntityOwner()) {
1049 LOG.error(YANG_OBJ + UPD_WARN);
1053 public class NetworksReactor
1054 extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1055 implements ClusteredDataTreeChangeListener<Networks> {
1057 private static final String YANG_OBJ = "networks ";
1059 public NetworksReactor() {
1060 super(Networks.class, NetworksReactor.class);
1064 public NetworksReactor getDataTreeChangeListener() {
1065 return NetworksReactor.this;
1069 protected void add(InstanceIdentifier<Networks> iid, Networks val) {
1070 if (!isBGPEntityOwner()) {
1073 LOG.debug("received add Networks config val {}", val.getPrefixLen());
1074 synchronized (BgpConfigurationManager.this) {
1075 String rd = val.getRd();
1076 String pfxlen = val.getPrefixLen();
1077 String nh = val.getNexthop().getValue();
1078 BgpRouter br = getClient(YANG_OBJ);
1080 LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
1081 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1084 Long label = val.getLabel();
1085 int lbl = label == null ? qbgpConstants.LBL_NO_LABEL
1087 int l3vni = val.getL3vni() == null ? qbgpConstants.LBL_NO_LABEL
1088 : val.getL3vni().intValue();
1089 int l2vni = val.getL2vni() == null ? qbgpConstants.LBL_NO_LABEL
1090 : val.getL2vni().intValue();
1092 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1093 int ethernetTag = val.getEthtag().intValue();
1094 String esi = val.getEsi();
1095 String macaddress = val.getMacaddress();
1096 EncapType encapType = val.getEncapType();
1097 String routerMac = val.getRoutermac();
1100 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni, BgpUtil.convertToThriftProtocolType(protocolType),
1101 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1102 } catch (TException | BgpRouterException e) {
1103 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1109 protected InstanceIdentifier<Networks> getWildCardPath() {
1110 return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1114 protected void remove(InstanceIdentifier<Networks> iid, Networks val) {
1115 if (!isBGPEntityOwner()) {
1118 LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1119 synchronized (BgpConfigurationManager.this) {
1120 String rd = val.getRd();
1121 String pfxlen = val.getPrefixLen();
1122 BgpRouter br = getClient(YANG_OBJ);
1124 LOG.debug("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
1125 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1128 Long label = val.getLabel();
1129 int lbl = label == null ? 0 : label.intValue();
1130 if (rd == null && lbl > 0) {
1131 //LU prefix is being deleted.
1132 rd = Integer.toString(lbl);
1135 br.delPrefix(rd, pfxlen);
1136 } catch (TException | BgpRouterException e) {
1137 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1142 /**get the value AFI from a prefix as "x.x.x.x/x".
1144 * @param pfxlen the prefix to get an afi
1145 * @return the afi value as you are need
1147 public int testValueAFI(String pfxlen) {
1148 int afiNew = af_afi.AFI_IP.getValue();
1150 String ipOnly = pfxlen.substring(0, pfxlen.lastIndexOf("/"));
1151 java.net.Inet6Address.getByName(ipOnly);
1152 afiNew = af_afi.AFI_IPV6.getValue();
1153 } catch (java.net.UnknownHostException e) {
1154 //ce n'est pas de l'ipv6
1161 protected void update(final InstanceIdentifier<Networks> iid,
1162 final Networks oldval, final Networks newval) {
1163 if (!isBGPEntityOwner()) {
1166 if (oldval.equals(newval)) {
1167 //Update: OLD and New values are same, no need to trigger remove/add.
1168 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1169 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1172 LOG.debug("update networks old val RD: {}, Prefix: {}, Label: {}, NH: {} "
1173 + "new val RD: {}, Prefix: {}, Label: {}, NH: {}",
1174 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop(),
1175 newval.getRd(), newval.getPrefixLen(), newval.getLabel(), newval.getNexthop());
1176 remove(iid, oldval);
1181 static Timer timer = new Timer();
1183 public class VrfsReactor
1184 extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1185 implements ClusteredDataTreeChangeListener<Vrfs> {
1187 private static final String YANG_OBJ = "vrfs ";
1189 public VrfsReactor() {
1190 super(Vrfs.class, VrfsReactor.class);
1194 protected void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
1195 if (!isBGPEntityOwner()) {
1198 LOG.debug("received add Vrfs config value {}", vrfs.getRd());
1199 synchronized (BgpConfigurationManager.this) {
1200 String rd = vrfs.getRd();
1201 BgpRouter br = getClient(YANG_OBJ);
1203 LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1204 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1208 List<AddressFamiliesVrf> vrfAddrFamilyList = vrfs.getAddressFamiliesVrf();
1209 for (AddressFamiliesVrf vrfAddrFamily : vrfAddrFamilyList) {
1210 /*add to br the new vrfs arguments*/
1211 br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(), vrfs.getExportRts(),
1212 vrfAddrFamily.getAfi(), vrfAddrFamily.getSafi());
1214 /*add to br the vrfs contained in mapNewAdFamily*/
1215 List<AddressFamiliesVrf> vrfAddrFamilyListFromMap = mapNewAdFamily.get(rd);
1216 if (vrfAddrFamilyListFromMap == null) {
1220 for (AddressFamiliesVrf adf : vrfAddrFamilyListFromMap) {
1221 if (vrfAddrFamilyList.contains(adf)) {
1222 mapNewAdFamily.remove(rd);
1223 } else if (adf != null) {
1225 br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(), vrfs.getExportRts(),
1226 adf.getAfi(), adf.getSafi());
1227 // remove AddressFamiliesVrf which was already added to BGP
1228 vrfAddrFamilyListFromMap.remove(adf);
1229 if (vrfAddrFamilyListFromMap.isEmpty()) {
1230 // remove Vrf entry from temp mapNewAdFamily if all its AddressFamiliesVrf was
1232 mapNewAdFamily.remove(rd);
1236 } catch (TException | BgpRouterException e) {
1237 LOG.error("{} get {}, Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1243 protected VrfsReactor getDataTreeChangeListener() {
1244 return VrfsReactor.this;
1248 protected InstanceIdentifier<Vrfs> getWildCardPath() {
1249 return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1253 protected void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1254 if (!isBGPEntityOwner()) {
1257 LOG.debug("received remove Vrfs config val {}", val.getRd());
1258 synchronized (BgpConfigurationManager.this) {
1259 String rd = val.getRd();
1260 BgpRouter br = getClient(YANG_OBJ);
1262 LOG.debug("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
1263 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1267 List<AddressFamiliesVrf> adf = mapNewAdFamily.get(rd);
1268 adf = adf != null ? adf : new ArrayList<>();
1269 for (AddressFamiliesVrf s : val.getAddressFamiliesVrf()) {
1270 br.delVrf(rd, s.getAfi(), s.getSafi());
1271 adf.remove(s);// remove in the map the vrf in waiting for advertise quagga
1273 if (adf.isEmpty()) {
1274 mapNewAdFamily.remove(rd);
1276 } catch (TException | BgpRouterException e) {
1277 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1283 protected void update(InstanceIdentifier<Vrfs> iid,
1284 Vrfs oldval, Vrfs newval) {
1285 if (oldval != null && newval != null) {
1286 LOG.debug("received update Vrfs config val {}, VRFS: Update getting triggered for VRFS rd {}",
1287 newval.getRd(), oldval.getRd());
1289 LOG.debug("received update Vrfs config val {}, from old vrf {}",
1292 if (!isBGPEntityOwner()) {
1296 List<AddressFamiliesVrf> adFamilyVrfToDel = new ArrayList<>();
1297 List<AddressFamiliesVrf> adFamilyVrfToAdd = new ArrayList<>();
1298 List<AddressFamiliesVrf> oldlistAdFamilies = new ArrayList<>();
1299 List<AddressFamiliesVrf> newlistAdFamilies = new ArrayList<>();
1300 if (oldval != null) {
1301 oldlistAdFamilies = oldval.getAddressFamiliesVrf() == null
1302 ? new ArrayList<>() : oldval.getAddressFamiliesVrf();
1304 if (newval != null) {
1305 newlistAdFamilies = newval.getAddressFamiliesVrf() == null
1306 ? new ArrayList<>() : newval.getAddressFamiliesVrf();
1308 /*find old AddressFamily to remove from new configuration*/
1309 for (AddressFamiliesVrf adVrf : oldlistAdFamilies) {
1310 if (!newlistAdFamilies.contains(adVrf)) {
1311 adFamilyVrfToDel.add(adVrf);
1314 /*find new AddressFamily to add to unexisting configuration*/
1315 for (AddressFamiliesVrf adVrf : newlistAdFamilies) {
1316 if (!oldlistAdFamilies.contains(adVrf)) {
1317 adFamilyVrfToAdd.add(adVrf);
1320 String rd = newval != null ? newval.getRd() : null;
1322 BgpRouter br = getClient(YANG_OBJ);
1324 LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1325 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1329 for (AddressFamiliesVrf adfvrf : adFamilyVrfToAdd) {
1331 LOG.debug("call addVRf rd {} afi {} safi {}", rd, adfvrf.getAfi(), adfvrf.getSafi());
1332 br.addVrf(BgpUtil.getLayerType(adfvrf), rd, newval.getImportRts(),
1333 newval.getExportRts(), adfvrf.getAfi(), adfvrf.getSafi());
1334 } catch (TException | BgpRouterException e) {
1335 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1339 for (AddressFamiliesVrf adfToDel : adFamilyVrfToDel) {
1341 LOG.debug("call delVRf rd {} afi {} safi {}", rd, adfToDel.getAfi(), adfToDel.getSafi());
1342 br.delVrf(rd, adfToDel.getAfi(), adfToDel.getSafi());
1343 } catch (TException | BgpRouterException e) {
1344 LOG.error("{} delVrf received exception; {}", YANG_OBJ, ADD_WARN, e);
1351 protected void activateMIP() {
1353 LOG.trace("BgpReactor: Executing MIP Activate command");
1354 Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1355 Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1356 LOG.trace("bgpMIP Activated");
1358 } catch (IOException io) {
1359 LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1363 public class BgpReactor
1364 extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1365 implements ClusteredDataTreeChangeListener<Bgp> {
1367 private static final String YANG_OBJ = "Bgp ";
1369 public BgpReactor() {
1370 super(Bgp.class, BgpReactor.class);
1375 protected void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1376 LOG.debug("received add Bgp config");
1380 } catch (InterruptedException e) {
1383 synchronized (BgpConfigurationManager.this) {
1385 if (!isBGPEntityOwner()) {
1393 protected BgpReactor getDataTreeChangeListener() {
1394 return BgpReactor.this;
1398 protected InstanceIdentifier<Bgp> getWildCardPath() {
1399 return InstanceIdentifier.create(Bgp.class);
1403 protected void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1404 if (!isBGPEntityOwner()) {
1407 LOG.debug("received remove Bgp config");
1413 protected void update(InstanceIdentifier<Bgp> iid,
1414 Bgp oldval, Bgp newval) {
1415 if (!isBGPEntityOwner()) {
1423 @SuppressWarnings("deprecation")
1424 public class MultipathReactor
1425 extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1426 implements ClusteredDataTreeChangeListener<Multipath> {
1428 private static final String YANG_OBJ = "multipath ";
1430 public MultipathReactor() {
1431 super(Multipath.class, MultipathReactor.class);
1436 protected MultipathReactor getDataTreeChangeListener() {
1437 return MultipathReactor.this;
1441 protected InstanceIdentifier<Multipath> getWildCardPath() {
1442 return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
1446 protected void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1447 executor.execute(new MultipathStatusChange(val));
1451 protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1452 executor.execute(new MultipathStatusChange(newval));
1456 protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1457 executor.execute(new MultipathStatusChange(dataObjectModification));
1460 class MultipathStatusChange implements Runnable {
1462 Multipath multipath;
1464 MultipathStatusChange(Multipath multipath) {
1465 this.multipath = multipath;
1470 if (isBGPEntityOwner()) {
1471 synchronized (BgpConfigurationManager.this) {
1473 BgpRouter br = getClient(YANG_OBJ);
1476 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1477 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1480 if (multipath.isMultipathEnabled()) {
1481 br.enableMultipath(afi, safi);
1483 br.disableMultipath(afi, safi);
1485 } catch (TException | BgpRouterException e) {
1486 LOG.error(YANG_OBJ + " received exception: \"" + e + "\"");
1496 public void close() {
1501 @SuppressWarnings("deprecation")
1502 public class VrfMaxpathReactor
1503 extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1504 implements ClusteredDataTreeChangeListener<VrfMaxpath> {
1506 private static final String YANG_OBJ = "vrfMaxpath ";
1508 public VrfMaxpathReactor() {
1509 super(VrfMaxpath.class, VrfMaxpathReactor.class);
1514 protected VrfMaxpathReactor getDataTreeChangeListener() {
1515 return VrfMaxpathReactor.this;
1519 protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1520 return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
1523 class VrfMaxPathConfigurator implements Runnable {
1525 VrfMaxpath vrfMaxpathVal;
1527 VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1528 this.vrfMaxpathVal = vrfMaxPathVal;
1533 if (isBGPEntityOwner()) {
1534 synchronized (BgpConfigurationManager.this) {
1535 BgpRouter br = getClient(YANG_OBJ);
1538 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
1539 LOG.debug("Maxpath for vrf: " + vrfMaxpathVal.getRd() + " : is "
1540 + vrfMaxpathVal.getMaxpaths());
1541 } catch (TException | BgpRouterException e) {
1543 + " received exception: \"" + e + "\"");
1552 protected void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1553 executor.execute(new VrfMaxPathConfigurator(vrfMaxPathVal));
1557 protected void update(InstanceIdentifier<VrfMaxpath> iid,
1558 VrfMaxpath oldval, VrfMaxpath newval) {
1559 if (!Objects.equals(oldval.getMaxpaths(), newval.getMaxpaths())) {
1560 executor.execute(new VrfMaxPathConfigurator(newval));
1565 protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1566 executor.execute(new VrfMaxPathConfigurator(vrfMaxpathVal));
1570 public void close() {
1575 public boolean isIpAvailable(String odlip) {
1578 if (odlip != null) {
1579 if ("127.0.0.1".equals(odlip)) {
1582 Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1583 while (networkInterfaceEnumeration.hasMoreElements()) {
1584 NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
1585 Enumeration<InetAddress> inetAddressEnumeration = networkInterface.getInetAddresses();
1586 while (inetAddressEnumeration.hasMoreElements()) {
1587 InetAddress inetAddress = inetAddressEnumeration.nextElement();
1588 if (odlip.equals(inetAddress.getHostAddress())) {
1594 } catch (SocketException e) {
1600 public long getStalePathtime(int defValue, AsId asId) {
1603 spt = getConfig().getGracefulRestart().getStalepathTime();
1604 } catch (NullPointerException e) {
1606 spt = asId.getStalepathTime();
1607 LOG.trace("BGP config/Stale-path time is not set using graceful");
1608 } catch (NullPointerException ignore) {
1609 LOG.trace("BGP AS id is not set using graceful");
1614 LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1620 public static boolean isValidConfigBgpHostPort(String bgpHost, int bgpPort) {
1621 if (!bgpHost.equals(DEF_CHOST) && bgpPort != Integer.parseInt(DEF_CPORT)) {
1628 public synchronized void bgpRestarted() {
1630 * If there a thread which in the process of stale cleanup, cancel it
1631 * and start a new thread (to avoid processing same again).
1633 if (previousReplayJobInProgress()) {
1634 cancelPreviousReplayJob();
1636 Runnable task = () -> {
1638 LOG.info("running bgp replay task ");
1639 if (get() == null) {
1640 String host = getConfigHost();
1641 int port = getConfigPort();
1642 LOG.info("connecting to bgp host {} ", host);
1643 bgpRouter.connect(host, port);
1644 LOG.info("no config to push in bgp replay task ");
1647 setStaleStartTime(System.currentTimeMillis());
1648 LOG.info("started creating stale fibDSWriter map ");
1649 createStaleFibMap();
1650 setStaleEndTime(System.currentTimeMillis());
1651 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1652 LOG.info("started bgp config replay ");
1653 setCfgReplayStartTime(System.currentTimeMillis());
1654 boolean replaySucceded = replay();
1655 setCfgReplayEndTime(System.currentTimeMillis());
1656 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1657 if (replaySucceded) {
1658 LOG.info("starting the stale cleanup timer");
1659 long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1660 setStaleCleanupTime(routeSyncTime);
1661 routeCleanupFuture = executor.schedule(new RouteCleanup(), routeSyncTime, TimeUnit.SECONDS);
1663 staledFibEntriesMap.clear();
1665 } catch (InterruptedException | TimeoutException | ExecutionException eCancel) {
1666 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1669 lastReplayJobFt = executor.submit(task);
1672 private boolean previousReplayJobInProgress() {
1673 return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1676 private void cancelPreviousReplayJob() {
1678 LOG.error("cancelling already running bgp replay task");
1679 if (lastReplayJobFt != null) {
1680 lastReplayJobFt.cancel(true);
1681 lastReplayJobFt = null;
1682 staledFibEntriesMap.clear();
1684 if (routeCleanupFuture != null) {
1685 routeCleanupFuture.cancel(true);
1686 routeCleanupFuture = null;
1687 staledFibEntriesMap.clear();
1690 } catch (InterruptedException e) {
1691 LOG.error("Failed to cancel previous replay job ", e);
1695 private void doRouteSync() throws InterruptedException, TimeoutException, ExecutionException {
1696 LOG.error("Starting BGP route sync");
1698 bgpRouter.initRibSync(bgpSyncHandle);
1699 } catch (TException | BgpRouterException e) {
1700 LOG.error("Route sync aborted, exception when initializing", e);
1703 while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
1704 for (af_afi afi : af_afi.values()) {
1705 Routes routes = null;
1707 routes = bgpRouter.doRibSync(bgpSyncHandle, afi);
1708 } catch (TException | BgpRouterException e) {
1709 LOG.error("Route sync aborted, exception when syncing", e);
1712 Iterator<Update> updates = routes.getUpdatesIterator();
1713 while (updates.hasNext()) {
1714 Update update = updates.next();
1715 String rd = update.getRd();
1716 String nexthop = update.getNexthop();
1718 // TODO: decide correct label here
1719 int label = update.getL3label();
1720 int l2label = update.getL2label();
1722 String prefix = update.getPrefix();
1723 int plen = update.getPrefixlen();
1726 // TODO: protocol type will not be available in "update"
1727 // use "rd" to query vrf table and obtain the protocol_type.
1728 // Currently using PROTOCOL_EVPN as default.
1730 protocol_type.PROTOCOL_EVPN,
1737 update.getMacaddress(),
1740 update.getRoutermac(),
1746 LOG.error("Ending BGP route-sync");
1747 bgpRouter.endRibSync(bgpSyncHandle);
1748 } catch (TException | BgpRouterException e) {
1753 public void addTepToElanDS(String rd, String tepIp, String mac, Long l2vni) {
1754 boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
1756 LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
1757 bgpUtil.addTepToElanInstance(rd, tepIp);
1759 LOG.debug("Skipping the Elan update for RT2 from tep {} rd {}", tepIp, rd);
1763 public void deleteTepfromElanDS(String rd, String tepIp, String mac) {
1764 boolean needUpdate = deleteFromRt2TepMap(rd, tepIp, mac);
1766 LOG.info("Deleting tepIp {} with RD {} to ELan DS", tepIp, rd);
1767 bgpUtil.deleteTepFromElanInstance(rd, tepIp);
1769 LOG.debug("Skipping the Elan update for RT2 withdraw from tep {} rd {}", tepIp, rd);
1773 /* onUpdatePushRoute
1774 * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1775 * - Entry compare shall include NextHop, Label.
1776 * - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1777 * - If entry not found, add to FIB Config DS.
1778 * - If entry found, but either Label/NextHop doesn't match.
1779 * - Update FIB Config DS with modified values.
1780 * - delete from Stale Map.
1783 public void onUpdatePushRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1784 int ethtag, String esi, String macaddress, int label, int l2label, String routermac, af_afi afi)
1785 throws InterruptedException, ExecutionException, TimeoutException {
1786 boolean addroute = false;
1787 boolean macupdate = false;
1789 VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1790 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1791 encapType = VrfEntry.EncapType.Vxlan;
1792 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1793 if (vpnInstanceOpDataEntry != null) {
1794 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1795 LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
1796 vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
1797 addTepToElanDS(rd, nextHop, macaddress, (long)l2label);
1800 l3vni = vpnInstanceOpDataEntry.getL3vni();
1803 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1808 if (!staledFibEntriesMap.isEmpty()) {
1809 // restart Scenario, as MAP is not empty.
1810 Map<String, Long> map = staledFibEntriesMap.get(rd);
1812 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1813 Long labelInStaleMap = map.get(prefixNextHop);
1814 if (null == labelInStaleMap) {
1815 // New Entry, which happened to be added during restart.
1818 map.remove(prefixNextHop);
1819 if (isRouteModified(label, labelInStaleMap)) {
1820 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1821 // Existing entry, where in Label got modified during restart
1826 LOG.debug("rd {} map is null while processing prefix {} ", rd, prefix);
1830 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1834 LOG.info("ADD: Adding Mac Fib entry rd {} mac{} nexthop {} l2vni {}", rd, macaddress, nextHop, l2label);
1835 fibDSWriter.addMacEntryToDS(rd, macaddress, prefix, Collections.singletonList(nextHop),
1836 encapType, l2label, routermac, RouteOrigin.BGP);
1837 LOG.info("ADD: Added Mac Fib entry rd {} prefix {} nexthop {} label {}", rd, macaddress, nextHop, l2label);
1838 } else if (addroute) {
1839 LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
1840 rd, prefix, nextHop, label, afi);
1841 // TODO: modify addFibEntryToDS signature
1842 List<String> nextHopList = Collections.singletonList(nextHop);
1843 fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
1844 routermac, RouteOrigin.BGP);
1845 LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1846 String vpnName = bgpUtil.getVpnNameFromRd(rd);
1847 if (vpnName != null) {
1848 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, nextHopList, label, RouteOrigin.BGP,
1849 NwConstants.ADD_FLOW);
1854 public void onUpdateWithdrawRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1855 String macaddress) throws InterruptedException, ExecutionException, TimeoutException {
1857 boolean macupdate = false;
1858 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1859 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1860 if (vpnInstanceOpDataEntry != null) {
1861 vni = vpnInstanceOpDataEntry.getL3vni();
1862 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1863 LOG.debug("Got RT2 withdraw for RD %s from tep %s with mac %s remote RD %s",
1864 vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
1865 deleteTepfromElanDS(rd, nextHop, macaddress);
1866 LOG.debug("For rd %s. skipping fib update", rd);
1870 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1875 LOG.info("Removing Mac Fib entry rd {} mac{} nexthop {} ", rd, macaddress, nextHop);
1876 fibDSWriter.removeMacEntryFromDS(rd, macaddress);
1877 LOG.info("Removed Mac Fib entry rd {} prefix {} nexthop {} ", rd, macaddress, nextHop);
1879 LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
1880 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nextHop);
1881 LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
1885 //TODO: below function is for testing purpose with cli
1886 public void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
1887 LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
1888 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
1889 String vpnName = bgpUtil.getVpnNameFromRd(rd);
1890 if (vpnName != null) {
1891 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
1892 RouteOrigin.BGP, NwConstants.DEL_FLOW);
1896 private static boolean isRouteModified(int label, Long labelInStaleMap) {
1897 return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
1900 static class ReplayNbr {
1902 boolean shouldRetry = false;
1904 public Neighbors getNbr() {
1908 public boolean isShouldRetry() {
1912 public void setShouldRetry(boolean retryNbr) {
1913 this.shouldRetry = retryNbr;
1916 ReplayNbr(Neighbors nbr, boolean shouldRetry) {
1918 this.shouldRetry = shouldRetry;
1922 private static boolean replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1923 if (neighbors == null || neighbors.isEmpty()) {
1924 LOG.error("Replaying nbr configuration, received NULL list ");
1928 List<ReplayNbr> replayNbrList = new ArrayList<>();
1929 for (Neighbors nbr : neighbors) {
1931 replayNbrList.add(new ReplayNbr(nbr, true));
1934 final int numberOfNbrRetries = 3;
1935 RetryOnException nbrRetry = new RetryOnException(numberOfNbrRetries);
1937 for (ReplayNbr replayNbr : replayNbrList) {
1938 if (!replayNbr.isShouldRetry()) {
1941 boolean replayDone = false;
1942 LOG.debug("Replaying addNbr {}", replayNbr.getNbr().getAddress().getValue());
1945 final String md5password = extractMd5Secret(replayNbr.getNbr());
1946 br.addNeighbor(replayNbr.getNbr().getAddress().getValue(),
1947 replayNbr.getNbr().getRemoteAs().longValue(), md5password);
1948 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1950 LOG.debug("Replaying updatesource along with nbr: {} US-ip: {} to peer {}",
1951 replayNbr.getNbr().getAddress().getValue(),
1952 us.getSourceIp().getValue(),
1953 us.getPeerIp().getValue());
1954 br.addUpdateSource(us.getPeerIp().getValue(),
1955 us.getSourceIp().getValue());
1958 } catch (TException | BgpRouterException eNbr) {
1959 LOG.debug("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), eNbr);
1961 boolean replaySuccess = true;
1962 replaySuccess = replaySuccess && replayDone;
1963 LOG.debug("Replay addNbr {} successful", replayNbr.getNbr().getAddress().getValue());
1965 //Update Source handling
1966 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1967 if (replayDone == false && us != null) {
1968 LOG.debug("Replaying updatesource {} to peer {}", us.getSourceIp().getValue(),
1969 us.getPeerIp().getValue());
1972 br.addUpdateSource(us.getPeerIp().getValue(),
1973 us.getSourceIp().getValue());
1975 } catch (TException | BgpRouterException eUs) {
1976 LOG.debug("Replaying UpdateSource for Nbr {}, exception:",
1977 replayNbr.getNbr().getAddress().getValue(), eUs);
1979 LOG.debug("Replay updatesource {} successful", us.getSourceIp().getValue());
1980 replaySuccess = replaySuccess && replayDone;
1983 EbgpMultihop en = replayNbr.getNbr().getEbgpMultihop();
1987 br.addEbgpMultihop(en.getPeerIp().getValue(),
1988 en.getNhops().intValue());
1990 } catch (TException | BgpRouterException eEbgpMhop) {
1991 LOG.debug("Replaying EbgpMultihop for Nbr {}, exception: ",
1992 replayNbr.getNbr().getAddress().getValue(), eEbgpMhop);
1994 replaySuccess = replaySuccess && replayDone;
1998 List<AddressFamilies> afs = replayNbr.getNbr().getAddressFamilies();
2000 for (AddressFamilies af : afs) {
2001 af_afi afi = af_afi.findByValue(af.getAfi().intValue());
2002 af_safi safi = af_safi.findByValue(af.getSafi().intValue());
2005 br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
2007 } catch (TException | BgpRouterException eAFs) {
2008 LOG.debug("Replaying AddressFamily for Nbr {}, exception:",
2009 replayNbr.getNbr().getAddress().getValue(), eAFs);
2011 replaySuccess = replaySuccess && replayDone;
2014 //replay is success --> no need to replay this nbr in next iteration.
2015 replayNbr.setShouldRetry(replaySuccess ? false : true);
2017 } while (nbrRetry.decrementAndRetry());
2018 boolean replaySuccess = true;
2019 for (ReplayNbr replayNbr : replayNbrList) {
2020 replaySuccess = replaySuccess && !replayNbr.isShouldRetry();
2022 return replaySuccess;
2025 public String getConfigHost() {
2026 if (config == null) {
2029 ConfigServer ts = config.getConfigServer();
2030 return ts == null ? hostStartup : ts.getHost().getValue();
2033 public int getConfigPort() {
2034 if (config == null) {
2035 return Integer.parseInt(portStartup);
2037 ConfigServer ts = config.getConfigServer();
2038 return ts == null ? Integer.parseInt(portStartup) :
2039 ts.getPort().intValue();
2042 public Bgp getConfig() {
2043 AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COUNT);
2044 while (0 != bgpDSretryCount.decrementAndGet()) {
2046 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
2047 InstanceIdentifier.create(Bgp.class)).orNull();
2048 } catch (ReadFailedException e) {
2049 //Config DS may not be up, so sleep for 1 second and retry
2050 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
2052 Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
2053 } catch (InterruptedException timerEx) {
2054 LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
2055 + "config DS availability", timerEx);
2059 LOG.error("failed to get bgp config");
2063 @SuppressWarnings("checkstyle:IllegalCatch")
2064 public synchronized boolean replay() throws InterruptedException, TimeoutException, ExecutionException {
2065 boolean replaySucceded = true;
2066 String host = getConfigHost();
2067 int port = getConfigPort();
2068 LOG.error("connecting to bgp host {} ", host);
2069 boolean res = bgpRouter.connect(host, port);
2071 String msg = "Cannot connect to BGP config server at " + host + ":" + port;
2072 if (config != null) {
2073 msg += "; Configuration Replay aborted";
2076 return replaySucceded;
2078 config = getConfig();
2079 if (config == null) {
2080 LOG.error("bgp config is empty nothing to push to bgp");
2081 return replaySucceded;
2083 BgpRouter br = bgpRouter;
2084 AsId asId = config.getAsId();
2086 LOG.error("bgp as-id is null");
2087 return replaySucceded;
2089 long asNum = asId.getLocalAs();
2090 IpAddress routerId = asId.getRouterId();
2091 String rid = routerId == null ? "" : new String(routerId.getValue());
2092 int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, config.getAsId());
2093 boolean announceFbit = true;
2094 boolean replayDone = false;
2095 final int numberOfStartBgpRetries = 3;
2096 RetryOnException startBgpRetry = new RetryOnException(numberOfStartBgpRetries);
2099 LOG.debug("Replaying BGPConfig ");
2100 br.startBgp(asNum, rid, stalepathTime, announceFbit);
2101 LOG.debug("Replay BGPConfig successful");
2104 } catch (BgpRouterException bre) {
2105 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
2106 LOG.debug("Starting the routesync for exception", bre);
2107 startBgpRetry.errorOccured();
2108 if (!startBgpRetry.shouldRetry()) {
2109 LOG.debug("starting route sync for BgpRouter exception");
2113 LOG.error("Replay: startBgp() received exception error {} : ",
2114 bre.getErrorCode(), bre);
2115 startBgpRetry.errorOccured();
2117 } catch (TApplicationException tae) {
2118 if (tae.getType() == BgpRouterException.BGP_ERR_ACTIVE) {
2119 LOG.debug("Starting the routesync for exception", tae);
2120 startBgpRetry.errorOccured();
2121 if (!startBgpRetry.shouldRetry()) {
2122 LOG.debug("starting route sync for Thrift BGP_ERR_ACTIVE exception");
2125 } else if (tae.getType() == BgpRouterException.BGP_ERR_COMMON_FAILURE) {
2126 LOG.debug("Starting the routesync for AS-ID started exception", tae);
2127 startBgpRetry.errorOccured();
2128 if (!startBgpRetry.shouldRetry()) {
2129 LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception");
2133 LOG.error("Replay: startBgp() received exception type {}: ",
2134 tae.getType(), tae);
2135 startBgpRetry.errorOccured();
2137 } catch (Exception e) {
2138 //not unusual. We may have restarted & BGP is already on
2139 LOG.error("Replay:startBgp() received exception: ", e);
2140 startBgpRetry.errorOccured();
2142 } while (startBgpRetry.shouldRetry());
2144 replaySucceded = replayDone;
2146 startBgpCountersTask();
2147 startBgpAlarmsTask();
2150 * commenting this due to a bug with QBGP. Will uncomment once QBGP fix is done.
2151 * This wont have any functional impacts
2154 // br.delayEOR(delayEorSeconds);
2155 //} catch (TException | BgpRouterException e) {
2156 // LOG.error("Replay: delayEOR() number of seconds to wait for EOR from ODL:", e);
2159 List<Neighbors> neighbors = config.getNeighbors();
2160 if (neighbors != null) {
2161 LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
2162 boolean neighborConfigReplayResult = replayNbrConfig(neighbors, br);
2163 if (neighborConfigReplayResult == false) {
2164 replaySucceded = false;
2167 LOG.error("no Neighbors present for replay config ");
2170 Logging logging = config.getLogging();
2171 if (logging != null) {
2173 br.setLogging(logging.getFile(), logging.getLevel());
2174 } catch (TException | BgpRouterException e) {
2175 LOG.error("Replay:setLogging() received exception", e);
2179 GracefulRestart gracefulRestart = config.getGracefulRestart();
2180 if (gracefulRestart != null) {
2182 br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
2183 } catch (TException | BgpRouterException e) {
2184 LOG.error("Replay:addGr() received exception", e);
2188 List<Vrfs> vrfs = config.getVrfs();
2190 vrfs = new ArrayList<>();
2192 for (Vrfs vrf : vrfs) {
2193 for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf()) {
2195 br.addVrf(BgpUtil.getLayerType(adf), vrf.getRd(), vrf.getImportRts(),
2196 vrf.getExportRts(), adf.getAfi(), adf.getSafi());
2197 } catch (TException | BgpRouterException e) {
2198 LOG.error("Replay:addVrf() received exception", e);
2203 List<Networks> ln = config.getNetworks();
2205 for (Networks net : ln) {
2206 String rd = net.getRd();
2207 String pfxlen = net.getPrefixLen();
2208 String nh = net.getNexthop().getValue();
2209 Long label = net.getLabel();
2210 int lbl = label == null ? 0 : label.intValue();
2211 int l3vni = net.getL3vni() == null ? 0 : net.getL3vni().intValue();
2212 int l2vni = net.getL2vni() == null ? 0 : net.getL2vni().intValue();
2213 if (rd == null && lbl > 0) {
2214 //LU prefix is being deleted.
2215 rd = Integer.toString(lbl);
2218 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
2219 int ethernetTag = net.getEthtag().intValue();
2220 String esi = net.getEsi();
2221 String macaddress = net.getMacaddress();
2222 EncapType encapType = net.getEncapType();
2223 String routerMac = net.getRoutermac();
2226 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni,
2227 BgpUtil.convertToThriftProtocolType(protocolType),
2228 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
2229 } catch (TException | BgpRouterException e) {
2230 LOG.error("Replay:addPfx() received exception", e);
2236 List<Multipath> multipaths = config.getMultipath();
2238 if (multipaths != null) {
2239 for (Multipath multipath : multipaths) {
2240 if (multipath != null) {
2241 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
2242 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
2245 if (multipath.isMultipathEnabled()) {
2246 br.enableMultipath(afi, safi);
2248 br.disableMultipath(afi, safi);
2250 } catch (TException | BgpRouterException e) {
2251 LOG.info("Replay:multipaths() received exception: \"" + e + "\"");
2256 List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
2257 if (vrfMaxpaths != null) {
2258 for (VrfMaxpath vrfMaxpath : vrfMaxpaths) {
2260 br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
2261 } catch (TException | BgpRouterException e) {
2262 LOG.info("Replay:vrfMaxPath() received exception: \"" + e + "\"");
2267 //send End of Rib Marker to Qthriftd.
2268 final int numberOfEORRetries = 3;
2270 RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
2274 LOG.debug("Replay sendEOR {} successful");
2277 } catch (Exception e) {
2278 eorRetry.errorOccured();
2279 LOG.error("Replay:sedEOR() received exception:", e);
2281 } while (eorRetry.shouldRetry());
2283 return replaySucceded && replayDone;
2286 private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
2287 bgpUtil.update(LogicalDatastoreType.CONFIGURATION, iid, dto);
2290 private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
2291 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, iid);
2294 public void startConfig(String bgpHost, int thriftPort) {
2295 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2296 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2297 InstanceIdentifier<ConfigServer> iid = iib.build();
2298 Ipv4Address ipAddr = new Ipv4Address(bgpHost);
2299 ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
2300 .setPort((long) thriftPort).build();
2304 public void startBgp(long as, String routerId, int spt, boolean fbit) {
2305 IpAddress rid = routerId == null ? null : new IpAddress(routerId.toCharArray());
2306 Long staleTime = (long) spt;
2307 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2308 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2309 InstanceIdentifier<AsId> iid = iib.build();
2310 AsId dto = new AsIdBuilder().setLocalAs(as)
2312 .setStalepathTime(staleTime)
2313 .setAnnounceFbit(fbit).build();
2317 public void addLogging(String fileName, String logLevel) {
2318 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2319 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2320 InstanceIdentifier<Logging> iid = iib.build();
2321 Logging dto = new LoggingBuilder().setFile(fileName)
2322 .setLevel(logLevel).build();
2326 public void addGracefulRestart(int staleTime) {
2327 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2328 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2329 InstanceIdentifier<GracefulRestart> iid = iib.build();
2330 GracefulRestart dto = new GracefulRestartBuilder()
2331 .setStalepathTime((long) staleTime).build();
2335 public void addNeighbor(
2336 String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2337 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2338 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2339 InstanceIdentifier.builder(Bgp.class)
2340 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2341 InstanceIdentifier<Neighbors> iid = iib.build();
2342 TcpSecurityOption tcpSecOption = null;
2343 if (md5Secret != null) {
2344 tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2345 } // else let tcpSecOption be null
2346 Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2347 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2349 } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2351 public void addUpdateSource(String nbrIp, String srcIp) {
2352 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2353 Ipv4Address srcAddr = new Ipv4Address(srcIp);
2354 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2355 InstanceIdentifier.builder(Bgp.class)
2356 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2357 .child(UpdateSource.class);
2358 InstanceIdentifier<UpdateSource> iid = iib.build();
2359 UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2360 .setSourceIp(srcAddr).build();
2364 public void addEbgpMultihop(String nbrIp, int hops) {
2365 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2366 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2367 InstanceIdentifier.builder(Bgp.class)
2368 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2369 .child(EbgpMultihop.class);
2370 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2371 EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2372 .setNhops((long) hops).build();
2376 public void addAddressFamily(String nbrIp, int afi, int safi) {
2377 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2378 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2379 InstanceIdentifier.builder(Bgp.class)
2380 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2381 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2382 InstanceIdentifier<AddressFamilies> iid = iib.build();
2383 AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2384 .setAfi((long) afi).setSafi((long) safi).build();
2388 public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2389 VrfEntry.EncapType encapType, long lbl, long l3vni, long l2vni, String gatewayMac) {
2390 for (String nh : nhList) {
2391 Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2393 InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2394 .child(Networks.class, new NetworksKey(pfx, rd)).build();
2395 NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2396 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
2397 buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, l2vni, macAddress, gatewayMac);
2398 update(iid, networksBuilder.build());
2402 private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
2403 long l3vni, long l2vni, String macAddress, String gatewayMac) {
2404 if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2405 builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2406 .setEncapType(EncapType.GRE);
2408 builder.setL3vni(l3vni).setL2vni(l2vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2409 .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2413 // TODO: add LayerType as arg - supports command
2414 public void addVrf(String rd, List<String> irts, List<String> erts, AddressFamily addressFamily) {
2415 Vrfs vrf = bgpUtil.getVrfFromRd(rd);
2416 List<AddressFamiliesVrf> adfList = new ArrayList<>(1);
2418 adfList = vrf.getAddressFamiliesVrf();
2420 AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2421 if (addressFamily.equals(AddressFamily.IPV4)) {
2422 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2423 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2424 } else if (addressFamily.equals(AddressFamily.IPV6)) {
2425 adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2426 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2427 } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2428 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2429 adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2431 AddressFamiliesVrf adf = adfBuilder.build();
2433 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = InstanceIdentifier.builder(Bgp.class)
2434 .child(Vrfs.class, new VrfsKey(rd));
2435 InstanceIdentifier<Vrfs> iid = iib.build();
2436 Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2437 .setExportRts(erts).setAddressFamiliesVrf(adfList).build();
2439 List<AddressFamiliesVrf> listAdFamilies = mapNewAdFamily.get(rd);
2440 if (listAdFamilies != null) {
2441 listAdFamilies.add(adf);
2443 mapNewAdFamily.put(rd, adfList);
2447 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2448 } catch (TransactionCommitFailedException e) {
2449 LOG.error("Error adding VRF to datastore", e);
2450 throw new RuntimeException(e);
2454 public void stopConfig() {
2455 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2456 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2457 InstanceIdentifier<ConfigServer> iid = iib.build();
2461 public void stopBgp() {
2462 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2463 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2464 InstanceIdentifier<AsId> iid = iib.build();
2468 public void delLogging() {
2469 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2470 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2471 InstanceIdentifier<Logging> iid = iib.build();
2475 public void delGracefulRestart() {
2476 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2477 InstanceIdentifier.builder(Bgp.class)
2478 .child(GracefulRestart.class);
2479 InstanceIdentifier<GracefulRestart> iid = iib.build();
2483 public void delNeighbor(String nbrIp) {
2484 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2485 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2486 InstanceIdentifier.builder(Bgp.class)
2487 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2488 InstanceIdentifier<Neighbors> iid = iib.build();
2492 public void delUpdateSource(String nbrIp) {
2493 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2494 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2495 InstanceIdentifier.builder(Bgp.class)
2496 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2497 .child(UpdateSource.class);
2498 InstanceIdentifier<UpdateSource> iid = iib.build();
2502 public void delEbgpMultihop(String nbrIp) {
2503 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2504 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2505 InstanceIdentifier.builder(Bgp.class)
2506 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2507 .child(EbgpMultihop.class);
2508 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2512 public void delAddressFamily(String nbrIp, int afi, int safi) {
2513 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2514 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2515 InstanceIdentifier.builder(Bgp.class)
2516 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2517 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2518 InstanceIdentifier<AddressFamilies> iid = iib.build();
2522 public void delPrefix(String rd, String pfx) {
2523 InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2524 InstanceIdentifier.builder(Bgp.class)
2525 .child(Networks.class, new NetworksKey(pfx, rd));
2526 InstanceIdentifier<Networks> iid = iib.build();
2530 public boolean delVrf(String rd, AddressFamily addressFamily) {
2531 if (addressFamily == null) {
2532 LOG.error("delVrf: vrf {}, addressFamily invalid", rd);
2535 AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2536 if (addressFamily.equals(AddressFamily.IPV4)) {
2537 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2538 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2539 } else if (addressFamily.equals(AddressFamily.IPV6)) {
2540 adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2541 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2542 } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2543 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2544 adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2546 Vrfs vrfOriginal = bgpUtil.getVrfFromRd(rd);
2547 if (vrfOriginal == null) {
2548 LOG.error("delVrf: no vrf with existing rd {}. step aborted", rd);
2552 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2553 InstanceIdentifier.builder(Bgp.class)
2554 .child(Vrfs.class, new VrfsKey(rd));
2556 InstanceIdentifier<Vrfs> iid = iib.build();
2558 @SuppressWarnings("static-access")
2559 InstanceIdentifier<Bgp> iid6 = iid.builder(Bgp.class).build()
2560 .child(Multipath.class, new MultipathKey(adfBuilder.getAfi(), adfBuilder.getSafi())).create(Bgp.class);
2561 InstanceIdentifierBuilder<Vrfs> iib3 = iid6.child(Vrfs.class, new VrfsKey(rd)).builder();
2562 InstanceIdentifier<Vrfs> iidFinal = iib3.build();
2564 //** update or delete the vrfs with the rest of AddressFamilies already present in the last list
2565 AddressFamiliesVrf adfToDel = adfBuilder.build();
2566 List<AddressFamiliesVrf> adfListOriginal = vrfOriginal.getAddressFamiliesVrf() == null
2567 ? new ArrayList<>() : vrfOriginal.getAddressFamiliesVrf();
2568 List<AddressFamiliesVrf> adfListToRemoveFromOriginal = new ArrayList<>();
2569 adfListOriginal.forEach(adf -> {
2570 if (adf.equals(adfToDel)) {
2571 adfListToRemoveFromOriginal.add(adfToDel);
2575 for (AddressFamiliesVrf adfToRemove : adfListToRemoveFromOriginal) {
2576 adfListOriginal.remove(adfToRemove);
2578 SingleTransactionDataBroker.syncWrite(dataBroker,
2579 LogicalDatastoreType.CONFIGURATION, iid, vrfOriginal);
2580 } catch (TransactionCommitFailedException e) {
2581 LOG.error("delVrf: Error updating VRF to datastore", e);
2582 throw new RuntimeException(e);
2585 if (adfListOriginal.isEmpty()) {
2589 // not all is removed
2593 public void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2594 long lafi = afi.getValue();
2595 long lsafi = safi.getValue();
2597 InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2600 .child(Multipath.class,
2601 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2603 Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2604 update(iib.build(), dto);
2607 public void multipaths(String rd, int maxpath) {
2608 InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2611 .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2613 VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2614 update(iib.build(), dto);
2618 * Remove Stale Marked Routes after timer expiry.
2620 private class RouteCleanup implements Callable<Integer> {
2623 public Integer call() {
2626 if (staledFibEntriesMap.isEmpty()) {
2627 LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2629 for (String rd : staledFibEntriesMap.keySet()) {
2630 if (Thread.interrupted()) {
2633 Map<String, Long> map = staledFibEntriesMap.get(rd);
2635 for (String key : map.keySet()) {
2636 if (Thread.interrupted()) {
2639 String prefix = extractPrefix(key);
2640 String nextHop = extractNextHop(key);
2642 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
2643 rd, prefix, nextHop);
2644 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
2650 staledFibEntriesMap.clear();
2652 LOG.error("cleared {} stale routes after bgp restart", totalCleared);
2658 * BGP restart scenario, ODL-BGP manager was/is running.
2659 * On re-sync notification, Get a copy of FIB database.
2661 public void createStaleFibMap() {
2662 totalStaledCount = 0;
2664 staledFibEntriesMap.clear();
2665 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2667 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2668 LogicalDatastoreType.CONFIGURATION, id);
2669 if (fibEntries.isPresent()) {
2670 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2671 for (VrfTables vrfTable : staleVrfTables) {
2672 Map<String, Long> staleFibEntMap = new HashMap<>();
2673 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2674 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2675 //Stale marking and cleanup is only meant for the routes learned through BGP.
2678 if (Thread.interrupted()) {
2682 //Create MAP from staleVrfTables.
2683 vrfEntry.getRoutePaths()
2685 routePath -> staleFibEntMap.put(
2686 appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2687 routePath.getNexthopAddress()), routePath.getLabel()));
2689 staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2692 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2694 } catch (ReadFailedException e) {
2695 LOG.error("createStaleFibMap:: error ", e);
2697 LOG.error("created {} staled entries ", totalStaledCount);
2701 * BGP config remove scenario, Need to remove all the
2702 * external routes from FIB.
2704 public void deleteExternalFibRoutes() {
2705 totalExternalRoutes = 0;
2706 totalExternalMacRoutes = 0;
2708 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2710 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2711 LogicalDatastoreType.CONFIGURATION, id);
2712 if (fibEntries.isPresent()) {
2713 if (fibEntries.get().getVrfTables() == null) {
2714 LOG.error("deleteExternalFibRoutes::getVrfTables is null");
2717 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2718 for (VrfTables vrfTable : staleVrfTables) {
2719 String rd = vrfTable.getRouteDistinguisher();
2720 if (vrfTable.getVrfEntry() != null) {
2721 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2722 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2723 //route cleanup is only meant for the routes learned through BGP.
2726 totalExternalRoutes++;
2727 fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
2729 } else if (vrfTable.getMacVrfEntry() != null) {
2730 for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
2731 if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
2732 //route cleanup is only meant for the routes learned through BGP.
2735 totalExternalMacRoutes++;
2736 fibDSWriter.removeMacEntryFromDS(rd, macEntry.getMac());
2741 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
2743 } catch (ReadFailedException e) {
2744 LOG.error("deleteExternalFibRoutes:: error ", e);
2746 LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
2749 public boolean addToRt2TepMap(String rd, String tepIp, String mac, Long l2vni) {
2750 boolean isFirstMacUpdateFromTep = false;
2751 if (rt2TepMap.containsKey(rd)) {
2752 if (rt2TepMap.get(rd).containsKey(tepIp)) {
2753 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and tep-ip {}. No Elan DS write required",
2754 mac, l2vni, rd, tepIp);
2755 rt2TepMap.get(rd).get(tepIp).put(mac, l2vni);
2757 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
2759 isFirstMacUpdateFromTep = true;
2760 Map<String, Long> macList = new HashMap<>();
2761 macList.put(mac, l2vni);
2762 rt2TepMap.get(rd).put(tepIp, macList);
2765 LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
2766 mac, l2vni, rd, tepIp);
2767 isFirstMacUpdateFromTep = true;
2768 Map<String, Long> macList = new HashMap<>();
2769 macList.put(mac, l2vni);
2770 Map<String, Map<String, Long>> tepIpMacMap = new HashMap<>();
2771 tepIpMacMap.put(tepIp, macList);
2772 rt2TepMap.put(rd, tepIpMacMap);
2774 return isFirstMacUpdateFromTep;
2777 public boolean deleteFromRt2TepMap(String rd, String tepIp, String mac) {
2778 boolean isLastMacUpdateFromTep = false;
2779 LOG.debug("RT2 withdraw with rd {} mac {} tep-ip {} ", rd, mac, tepIp);
2780 if (rt2TepMap.containsKey(rd)) {
2781 if (rt2TepMap.get(rd).containsKey(tepIp)) {
2782 if (rt2TepMap.get(rd).get(tepIp).containsKey(mac)) {
2783 LOG.debug("RT2 Withdraw : Removing the mac {} from Map", mac);
2784 rt2TepMap.get(rd).get(tepIp).remove(mac);
2785 if (rt2TepMap.get(rd).get(tepIp).isEmpty()) {
2786 isLastMacUpdateFromTep = true;
2787 LOG.debug("RT2 Withdraw : Removing the tep-ip {} from Map", tepIp);
2788 rt2TepMap.get(rd).remove(tepIp);
2789 if (rt2TepMap.get(rd).isEmpty()) {
2790 LOG.debug("RT2 Withdraw : Removing the rd {} from Map", rd);
2791 rt2TepMap.remove(rd);
2797 return isLastMacUpdateFromTep;
2800 public Collection<String> getTepIPs(String rd) {
2801 final Map<String, Map<String, Long>> tepIpMap = rt2TepMap.get(rd);
2802 return tepIpMap != null ? tepIpMap.keySet() : Collections.emptyList();
2805 public boolean isBgpConnected() {
2806 return bgpRouter.isBgpConnected();
2809 public long getLastConnectedTS() {
2810 return bgpRouter.getLastConnectedTS();
2813 public long getConnectTS() {
2814 return bgpRouter.getConnectTS();
2817 public long getStartTS() {
2818 return bgpRouter.getStartTS();
2821 public TTransport getTransport() {
2822 return bgpRouter.getTransport();
2825 public int getTotalStaledCount() {
2826 return totalStaledCount;
2829 public int getTotalCleared() {
2830 return totalCleared;
2833 public BgpCounters getBgpCounters() {
2834 return bgpCountersReference.get();
2837 private void startBgpCountersTask() {
2838 if (getBgpCounters() == null && bgpCountersReference.compareAndSet(null,
2839 new BgpCounters(getBgpSdncMipIp(), metricProvider))) {
2840 bgpCountersTask = executor.scheduleAtFixedRate(bgpCountersReference.get(), 0, 120 * 1000,
2841 TimeUnit.MILLISECONDS);
2842 LOG.info("Bgp Counters task scheduled for every two minutes.");
2844 bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2848 private void stopBgpCountersTask() {
2849 final BgpCounters bgpCounters = bgpCountersReference.getAndSet(null);
2850 if (bgpCounters != null) {
2851 bgpCountersTask.cancel(true);
2852 bgpCounters.close();
2856 private void startBgpAlarmsTask() {
2857 if (getBgpAlarms() == null && bgpAlarmsReference.compareAndSet(null, new BgpAlarms(this))) {
2858 bgpAlarmsReference.get().init();
2859 bgpAlarmsTask = executor.scheduleAtFixedRate(bgpAlarmsReference.get(), 0, 60 * 1000, TimeUnit.MILLISECONDS);
2860 LOG.info("Bgp Alarms task scheduled for every minute.");
2864 private void stopBgpAlarmsTask() {
2865 final BgpAlarms bgpAlarms = bgpAlarmsReference.getAndSet(null);
2866 if (bgpAlarms != null) {
2867 bgpAlarmsTask.cancel(true);
2872 public BgpAlarms getBgpAlarms() {
2873 return bgpAlarmsReference.get();
2876 private static String appendNextHopToPrefix(String prefix, String nextHop) {
2877 return prefix + ":" + nextHop;
2880 private static String extractPrefix(String prefixNextHop) {
2881 return prefixNextHop.split(":")[0];
2884 private static String extractNextHop(String prefixNextHop) {
2885 return prefixNextHop.split(":")[1];
2888 private static String extractMd5Secret(final Neighbors val) {
2889 String md5Secret = null;
2890 TcpSecurityOption tcpSecOpt = val.getTcpSecurityOption();
2891 if (tcpSecOpt != null) {
2892 if (tcpSecOpt instanceof TcpMd5SignatureOption) {
2893 md5Secret = ((TcpMd5SignatureOption) tcpSecOpt).getTcpMd5SignaturePassword().getValue();
2894 } else { // unknown TcpSecurityOption
2895 LOG.debug("neighbors Ignored unknown tcp-security-option of peer {}", val.getAddress().getValue());
2899 } // private method extractMd5Secret