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 this.dataBroker = dataBroker;
238 this.fibDSWriter = fibDSWriter;
239 this.vpnLinkService = vpnLinkSrvce;
240 this.bundleContext = bundleContext;
241 this.bgpUtil = bgpUtil;
242 this.metricProvider = metricProvider;
243 String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
244 hostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
245 portStartup = getProperty(CONFIG_PORT, DEF_CPORT);
246 LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
247 + hostStartup + ":" + portStartup);
248 VtyshCli.setHostAddr(hostStartup);
249 ClearBgpCli.setHostAddr(hostStartup);
250 bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner);
253 entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
255 candidateRegistration = registerEntityCandidate(entityOwnershipService);
256 entityListenerRegistration = registerEntityListener(entityOwnershipService);
258 LOG.info("BGP Configuration manager initialized");
261 GlobalEventExecutor.INSTANCE.execute(() -> {
262 final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
263 IBgpManager.class, bundleContext);
264 bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
265 updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, this);
266 updateServer.start();
267 LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
271 public String getBgpSdncMipIp() {
272 return getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
275 public long getStaleCleanupTime() {
276 return staleCleanupTime;
279 public void setStaleCleanupTime(long staleCleanupTime) {
280 this.staleCleanupTime = staleCleanupTime;
283 public long getCfgReplayEndTime() {
284 return cfgReplayEndTime;
287 public void setCfgReplayEndTime(long cfgReplayEndTime) {
288 this.cfgReplayEndTime = cfgReplayEndTime;
291 public long getCfgReplayStartTime() {
292 return cfgReplayStartTime;
295 public void setCfgReplayStartTime(long cfgReplayStartTime) {
296 this.cfgReplayStartTime = cfgReplayStartTime;
299 public long getStaleEndTime() {
303 public void setStaleEndTime(long staleEndTime) {
304 this.staleEndTime = staleEndTime;
307 public long getStaleStartTime() {
308 return staleStartTime;
311 public void setStaleStartTime(long staleStartTime) {
312 this.staleStartTime = staleStartTime;
315 private Object createListener(Class<?> cls) {
317 Constructor<?> ctor = cls.getConstructor(BgpConfigurationManager.class);
318 return ctor.newInstance(this);
319 } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
321 LOG.error("Failed to create listener object", e);
326 private void registerCallbacks() {
327 for (Class<?> reactor : REACTORS) {
328 Object obj = createListener(reactor);
330 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
331 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
337 @SuppressWarnings("checkstyle:IllegalCatch")
339 public void close() {
342 if (updateServer != null) {
346 if (candidateRegistration != null) {
347 candidateRegistration.close();
350 entityListenerRegistration.close();
352 listeners.forEach(l -> {
355 } catch (Exception e) {
356 LOG.warn("Error closing {}", l ,e);
360 LOG.info("{} close", getClass().getSimpleName());
363 private String getProperty(String var, String def) {
364 String property = bundleContext.getProperty(var);
365 return property == null ? def : property;
368 private EntityOwnershipCandidateRegistration registerEntityCandidate(
369 final EntityOwnershipService entityOwnershipService) {
371 return entityOwnershipService.registerCandidate(
372 new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME));
373 } catch (CandidateAlreadyRegisteredException e) {
374 LOG.error("failed to register bgp entity", e);
379 private EntityOwnershipListenerRegistration registerEntityListener(
380 final EntityOwnershipService entityOwnershipService) {
381 return entityOwnershipService.registerListener(BGP_ENTITY_TYPE_FOR_OWNERSHIP, ownershipChange -> {
382 LOG.trace("entity owner change event fired: {}", ownershipChange);
384 if (ownershipChange.getState() == EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED) {
385 LOG.trace("This PL is the Owner");
389 LOG.debug("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
390 ownershipChange.getState().isOwner());
395 public boolean isBGPEntityOwner() {
396 return entityOwnershipUtils.isEntityOwner(new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME), 0, 1);
400 config = getConfig();
404 public class ConfigServerReactor
405 extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
406 implements ClusteredDataTreeChangeListener<ConfigServer> {
407 private static final String YANG_OBJ = "config-server ";
409 public ConfigServerReactor() {
410 super(ConfigServer.class, ConfigServerReactor.class);
414 protected void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
415 LOG.trace("received bgp connect config host {}", val.getHost().getValue());
416 if (!isBGPEntityOwner()) {
422 } catch (InterruptedException e) {
425 LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
426 bgpRouter.configServerUpdated();
427 synchronized (BgpConfigurationManager.this) {
428 boolean res = bgpRouter.connect(val.getHost().getValue(),
429 val.getPort().intValue());
431 LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
434 VtyshCli.setHostAddr(val.getHost().getValue());
435 ClearBgpCli.setHostAddr(val.getHost().getValue());
439 protected ConfigServerReactor getDataTreeChangeListener() {
440 return ConfigServerReactor.this;
444 protected InstanceIdentifier<ConfigServer> getWildCardPath() {
445 return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
449 protected void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
450 LOG.trace("received bgp disconnect");
451 if (!isBGPEntityOwner()) {
455 bgpRouter.configServerUpdated();
457 synchronized (BgpConfigurationManager.this) {
458 bgpRouter.disconnect();
463 protected void update(InstanceIdentifier<ConfigServer> iid,
464 ConfigServer oldval, ConfigServer newval) {
465 LOG.trace("received bgp Connection update");
466 if (!isBGPEntityOwner()) {
469 LOG.error(YANG_OBJ + UPD_WARN);
473 private BgpRouter getClient(String yangObj) {
474 if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
475 LOG.warn("{}: configuration received when BGP is inactive", yangObj);
481 public class AsIdReactor
482 extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
483 implements ClusteredDataTreeChangeListener<AsId> {
485 private static final String YANG_OBJ = "as-id ";
487 public AsIdReactor() {
488 super(AsId.class, AsIdReactor.class);
492 protected void add(InstanceIdentifier<AsId> iid, AsId val) {
493 LOG.error("received bgp add asid {}", val);
494 if (!isBGPEntityOwner()) {
497 LOG.debug("received add router config asNum {}", val.getLocalAs());
498 synchronized (BgpConfigurationManager.this) {
499 BgpRouter br = getClient(YANG_OBJ);
501 LOG.debug("{} Unable to process add for asNum {}; {}", YANG_OBJ, val.getLocalAs(),
502 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
507 startBgpCountersTask();
508 startBgpAlarmsTask();
513 protected AsIdReactor getDataTreeChangeListener() {
514 return AsIdReactor.this;
518 protected InstanceIdentifier<AsId> getWildCardPath() {
519 return InstanceIdentifier.create(Bgp.class).child(AsId.class);
523 protected void remove(InstanceIdentifier<AsId> iid, AsId val) {
524 LOG.error("received delete router config asNum {}", val.getLocalAs());
525 if (!isBGPEntityOwner()) {
528 synchronized (BgpConfigurationManager.this) {
529 long asNum = val.getLocalAs();
530 BgpRouter br = getClient(YANG_OBJ);
532 LOG.debug("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
533 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
538 } catch (TException | BgpRouterException e) {
539 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
542 stopBgpCountersTask();
545 Bgp conf = getConfig();
547 LOG.error("Config Null while removing the as-id");
550 LOG.debug("Removing external routes from FIB");
551 deleteExternalFibRoutes();
552 List<Neighbors> nbrs = conf.getNeighbors();
553 if (nbrs != null && nbrs.size() > 0) {
554 LOG.error("Tring to remove the as-id when neighbor config is already present");
555 for (Neighbors nbr : nbrs) {
556 LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
557 delNeighbor(nbr.getAddress().getValue());
564 protected void update(InstanceIdentifier<AsId> iid,
565 AsId oldval, AsId newval) {
566 if (!isBGPEntityOwner()) {
569 LOG.error(YANG_OBJ + UPD_WARN);
573 public class GracefulRestartReactor
574 extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
575 implements ClusteredDataTreeChangeListener<GracefulRestart> {
577 private static final String YANG_OBJ = "graceful-restart ";
579 public GracefulRestartReactor() {
580 super(GracefulRestart.class, GracefulRestartReactor.class);
584 protected void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
585 if (!isBGPEntityOwner()) {
588 synchronized (BgpConfigurationManager.this) {
589 int stalePathTime = val.getStalepathTime().intValue();
590 BgpRouter br = getClient(YANG_OBJ);
592 LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
593 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
597 br.addGracefulRestart(stalePathTime);
598 } catch (TException | BgpRouterException e) {
599 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
605 protected GracefulRestartReactor getDataTreeChangeListener() {
606 return GracefulRestartReactor.this;
610 protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
611 return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
615 protected void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
616 if (!isBGPEntityOwner()) {
619 LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
620 synchronized (BgpConfigurationManager.this) {
621 BgpRouter br = getClient(YANG_OBJ);
623 LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
624 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
628 br.delGracefulRestart();
629 } catch (TException | BgpRouterException e) {
630 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
636 protected void update(InstanceIdentifier<GracefulRestart> iid,
637 GracefulRestart oldval, GracefulRestart newval) {
638 if (!isBGPEntityOwner()) {
641 LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
642 synchronized (BgpConfigurationManager.this) {
643 int stalePathTime = newval.getStalepathTime().intValue();
644 BgpRouter br = getClient(YANG_OBJ);
646 LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
647 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
651 br.addGracefulRestart(stalePathTime);
652 } catch (TException | BgpRouterException e) {
653 LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
659 public class LoggingReactor
660 extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
661 implements ClusteredDataTreeChangeListener<Logging> {
663 private static final String YANG_OBJ = "logging ";
665 public LoggingReactor() {
666 super(Logging.class, LoggingReactor.class);
670 protected void add(InstanceIdentifier<Logging> iid, Logging val) {
671 if (!isBGPEntityOwner()) {
674 synchronized (BgpConfigurationManager.this) {
675 BgpRouter br = getClient(YANG_OBJ);
677 LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
678 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
682 br.setLogging(val.getFile(), val.getLevel());
683 } catch (TException | BgpRouterException e) {
684 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
690 protected LoggingReactor getDataTreeChangeListener() {
691 return LoggingReactor.this;
695 protected InstanceIdentifier<Logging> getWildCardPath() {
696 return InstanceIdentifier.create(Bgp.class).child(Logging.class);
700 protected void remove(InstanceIdentifier<Logging> iid, Logging val) {
701 if (!isBGPEntityOwner()) {
704 LOG.debug("received remove Logging config val {}", val.getLevel());
705 synchronized (BgpConfigurationManager.this) {
706 BgpRouter br = getClient(YANG_OBJ);
708 LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
709 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
713 br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
714 } catch (TException | BgpRouterException e) {
715 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
721 protected void update(InstanceIdentifier<Logging> iid,
722 Logging oldval, Logging newval) {
723 if (!isBGPEntityOwner()) {
726 synchronized (BgpConfigurationManager.this) {
727 BgpRouter br = getClient(YANG_OBJ);
729 LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
730 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
734 br.setLogging(newval.getFile(), newval.getLevel());
735 } catch (TException | BgpRouterException e) {
736 LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
742 public class NeighborsReactor
743 extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
744 implements ClusteredDataTreeChangeListener<Neighbors> {
746 private static final String YANG_OBJ = "neighbors ";
748 public NeighborsReactor() {
749 super(Neighbors.class, NeighborsReactor.class);
753 protected void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
754 if (!isBGPEntityOwner()) {
757 LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
758 synchronized (BgpConfigurationManager.this) {
759 String peerIp = val.getAddress().getValue();
760 long as = val.getRemoteAs();
761 final String md5Secret = extractMd5Secret(val);
762 BgpRouter br = getClient(YANG_OBJ);
764 LOG.debug("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
765 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
769 //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
770 br.addNeighbor(peerIp, as, md5Secret);
772 } catch (TException | BgpRouterException e) {
773 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
779 protected NeighborsReactor getDataTreeChangeListener() {
780 return NeighborsReactor.this;
784 protected InstanceIdentifier<Neighbors> getWildCardPath() {
785 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
789 protected void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
790 if (!isBGPEntityOwner()) {
793 LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
794 synchronized (BgpConfigurationManager.this) {
795 String peerIp = val.getAddress().getValue();
796 BgpRouter br = getClient(YANG_OBJ);
798 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
799 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
803 //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
804 br.delNeighbor(peerIp);
805 } catch (TException | BgpRouterException e) {
806 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
809 final BgpAlarms bgpAlarms = getBgpAlarms();
810 if (bgpAlarms != null) {
811 bgpAlarms.clearBgpNbrDownAlarm(peerIp);
817 protected void update(InstanceIdentifier<Neighbors> iid,
818 Neighbors oldval, Neighbors newval) {
819 if (!isBGPEntityOwner()) {
822 //purposefully nothing to do.
826 public class EbgpMultihopReactor
827 extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
828 implements ClusteredDataTreeChangeListener<EbgpMultihop> {
830 private static final String YANG_OBJ = "ebgp-multihop ";
832 public EbgpMultihopReactor() {
833 super(EbgpMultihop.class, EbgpMultihopReactor.class);
837 protected void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
838 if (!isBGPEntityOwner()) {
841 LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
842 synchronized (BgpConfigurationManager.this) {
843 String peerIp = val.getPeerIp().getValue();
844 BgpRouter br = getClient(YANG_OBJ);
846 LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
847 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
851 br.addEbgpMultihop(peerIp, val.getNhops().intValue());
852 } catch (TException | BgpRouterException e) {
853 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
859 protected EbgpMultihopReactor getDataTreeChangeListener() {
860 return EbgpMultihopReactor.this;
864 protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
865 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
869 protected void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
870 if (!isBGPEntityOwner()) {
873 LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
874 synchronized (BgpConfigurationManager.this) {
875 String peerIp = val.getPeerIp().getValue();
876 BgpRouter br = getClient(YANG_OBJ);
878 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
879 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
883 br.delEbgpMultihop(peerIp);
884 } catch (TException | BgpRouterException e) {
885 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
891 protected void update(InstanceIdentifier<EbgpMultihop> iid,
892 EbgpMultihop oldval, EbgpMultihop newval) {
893 if (!isBGPEntityOwner()) {
896 LOG.error(YANG_OBJ + UPD_WARN);
900 public class UpdateSourceReactor
901 extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
902 implements ClusteredDataTreeChangeListener<UpdateSource> {
904 private static final String YANG_OBJ = "update-source ";
906 public UpdateSourceReactor() {
907 super(UpdateSource.class, UpdateSourceReactor.class);
911 protected void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
912 if (!isBGPEntityOwner()) {
915 LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
916 synchronized (BgpConfigurationManager.this) {
917 String peerIp = val.getPeerIp().getValue();
918 BgpRouter br = getClient(YANG_OBJ);
920 LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
921 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
925 br.addUpdateSource(peerIp, val.getSourceIp().getValue());
926 } catch (TException | BgpRouterException e) {
927 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
933 protected UpdateSourceReactor getDataTreeChangeListener() {
934 return UpdateSourceReactor.this;
938 protected InstanceIdentifier<UpdateSource> getWildCardPath() {
939 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
943 protected void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
944 if (!isBGPEntityOwner()) {
947 LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
948 synchronized (BgpConfigurationManager.this) {
949 String peerIp = val.getPeerIp().getValue();
950 BgpRouter br = getClient(YANG_OBJ);
952 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
953 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
957 br.delUpdateSource(peerIp);
958 } catch (TException | BgpRouterException e) {
959 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
965 protected void update(InstanceIdentifier<UpdateSource> iid,
966 UpdateSource oldval, UpdateSource newval) {
967 if (!isBGPEntityOwner()) {
970 LOG.error(YANG_OBJ + UPD_WARN);
974 public class AddressFamiliesReactor
975 extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
976 implements ClusteredDataTreeChangeListener<AddressFamilies> {
978 private static final String YANG_OBJ = "address-families ";
980 public AddressFamiliesReactor() {
981 super(AddressFamilies.class, AddressFamiliesReactor.class);
985 protected void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
986 if (!isBGPEntityOwner()) {
989 LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
990 synchronized (BgpConfigurationManager.this) {
991 String peerIp = val.getPeerIp().getValue();
992 BgpRouter br = getClient(YANG_OBJ);
994 LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
995 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
998 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
999 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1001 br.addAddressFamily(peerIp, afi, safi);
1002 } catch (TException | BgpRouterException e) {
1003 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1009 protected AddressFamiliesReactor getDataTreeChangeListener() {
1010 return AddressFamiliesReactor.this;
1014 protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
1015 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
1019 protected void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1020 if (!isBGPEntityOwner()) {
1023 LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
1024 synchronized (BgpConfigurationManager.this) {
1025 String peerIp = val.getPeerIp().getValue();
1026 BgpRouter br = getClient(YANG_OBJ);
1028 LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
1029 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1032 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1033 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1035 br.delAddressFamily(peerIp, afi, safi);
1036 } catch (TException | BgpRouterException e) {
1037 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1043 protected void update(InstanceIdentifier<AddressFamilies> iid,
1044 AddressFamilies oldval, AddressFamilies newval) {
1045 if (!isBGPEntityOwner()) {
1048 LOG.error(YANG_OBJ + UPD_WARN);
1052 public class NetworksReactor
1053 extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1054 implements ClusteredDataTreeChangeListener<Networks> {
1056 private static final String YANG_OBJ = "networks ";
1058 public NetworksReactor() {
1059 super(Networks.class, NetworksReactor.class);
1063 public NetworksReactor getDataTreeChangeListener() {
1064 return NetworksReactor.this;
1068 protected void add(InstanceIdentifier<Networks> iid, Networks val) {
1069 if (!isBGPEntityOwner()) {
1072 LOG.debug("received add Networks config val {}", val.getPrefixLen());
1073 synchronized (BgpConfigurationManager.this) {
1074 String rd = val.getRd();
1075 String pfxlen = val.getPrefixLen();
1076 String nh = val.getNexthop().getValue();
1077 BgpRouter br = getClient(YANG_OBJ);
1079 LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
1080 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1083 Long label = val.getLabel();
1084 int lbl = label == null ? qbgpConstants.LBL_NO_LABEL
1086 int l3vni = val.getL3vni() == null ? qbgpConstants.LBL_NO_LABEL
1087 : val.getL3vni().intValue();
1088 int l2vni = val.getL2vni() == null ? qbgpConstants.LBL_NO_LABEL
1089 : val.getL2vni().intValue();
1091 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1092 int ethernetTag = val.getEthtag().intValue();
1093 String esi = val.getEsi();
1094 String macaddress = val.getMacaddress();
1095 EncapType encapType = val.getEncapType();
1096 String routerMac = val.getRoutermac();
1099 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni, BgpUtil.convertToThriftProtocolType(protocolType),
1100 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1101 } catch (TException | BgpRouterException e) {
1102 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1108 protected InstanceIdentifier<Networks> getWildCardPath() {
1109 return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1113 protected void remove(InstanceIdentifier<Networks> iid, Networks val) {
1114 if (!isBGPEntityOwner()) {
1117 LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1118 synchronized (BgpConfigurationManager.this) {
1119 String rd = val.getRd();
1120 String pfxlen = val.getPrefixLen();
1121 BgpRouter br = getClient(YANG_OBJ);
1123 LOG.debug("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
1124 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1127 Long label = val.getLabel();
1128 int lbl = label == null ? 0 : label.intValue();
1129 if (rd == null && lbl > 0) {
1130 //LU prefix is being deleted.
1131 rd = Integer.toString(lbl);
1134 br.delPrefix(rd, pfxlen);
1135 } catch (TException | BgpRouterException e) {
1136 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1141 /**get the value AFI from a prefix as "x.x.x.x/x".
1143 * @param pfxlen the prefix to get an afi
1144 * @return the afi value as you are need
1146 public int testValueAFI(String pfxlen) {
1147 int afiNew = af_afi.AFI_IP.getValue();
1149 String ipOnly = pfxlen.substring(0, pfxlen.lastIndexOf("/"));
1150 java.net.Inet6Address.getByName(ipOnly);
1151 afiNew = af_afi.AFI_IPV6.getValue();
1152 } catch (java.net.UnknownHostException e) {
1153 //ce n'est pas de l'ipv6
1160 protected void update(final InstanceIdentifier<Networks> iid,
1161 final Networks oldval, final Networks newval) {
1162 if (!isBGPEntityOwner()) {
1165 if (oldval.equals(newval)) {
1166 //Update: OLD and New values are same, no need to trigger remove/add.
1167 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1168 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1171 LOG.debug("update networks old val RD: {}, Prefix: {}, Label: {}, NH: {} "
1172 + "new val RD: {}, Prefix: {}, Label: {}, NH: {}",
1173 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop(),
1174 newval.getRd(), newval.getPrefixLen(), newval.getLabel(), newval.getNexthop());
1175 remove(iid, oldval);
1180 static Timer timer = new Timer();
1182 public class VrfsReactor
1183 extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1184 implements ClusteredDataTreeChangeListener<Vrfs> {
1186 private static final String YANG_OBJ = "vrfs ";
1188 public VrfsReactor() {
1189 super(Vrfs.class, VrfsReactor.class);
1193 protected void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
1194 if (!isBGPEntityOwner()) {
1197 LOG.debug("received add Vrfs config value {}", vrfs.getRd());
1198 synchronized (BgpConfigurationManager.this) {
1199 String rd = vrfs.getRd();
1200 BgpRouter br = getClient(YANG_OBJ);
1202 LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1203 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1207 List<AddressFamiliesVrf> vrfAddrFamilyList = vrfs.getAddressFamiliesVrf();
1208 for (AddressFamiliesVrf vrfAddrFamily : vrfAddrFamilyList) {
1209 /*add to br the new vrfs arguments*/
1210 br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(), vrfs.getExportRts(),
1211 vrfAddrFamily.getAfi(), vrfAddrFamily.getSafi());
1213 /*add to br the vrfs contained in mapNewAdFamily*/
1214 List<AddressFamiliesVrf> vrfAddrFamilyListFromMap = mapNewAdFamily.get(rd);
1215 if (vrfAddrFamilyListFromMap == null) {
1219 for (AddressFamiliesVrf adf : vrfAddrFamilyListFromMap) {
1220 if (vrfAddrFamilyList.contains(adf)) {
1221 mapNewAdFamily.remove(rd);
1222 } else if (adf != null) {
1224 br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(), vrfs.getExportRts(),
1225 adf.getAfi(), adf.getSafi());
1226 // remove AddressFamiliesVrf which was already added to BGP
1227 vrfAddrFamilyListFromMap.remove(adf);
1228 if (vrfAddrFamilyListFromMap.isEmpty()) {
1229 // remove Vrf entry from temp mapNewAdFamily if all its AddressFamiliesVrf was
1231 mapNewAdFamily.remove(rd);
1235 } catch (TException | BgpRouterException e) {
1236 LOG.error("{} get {}, Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1242 protected VrfsReactor getDataTreeChangeListener() {
1243 return VrfsReactor.this;
1247 protected InstanceIdentifier<Vrfs> getWildCardPath() {
1248 return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1252 protected void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1253 if (!isBGPEntityOwner()) {
1256 LOG.debug("received remove Vrfs config val {}", val.getRd());
1257 synchronized (BgpConfigurationManager.this) {
1258 String rd = val.getRd();
1259 BgpRouter br = getClient(YANG_OBJ);
1261 LOG.debug("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
1262 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1266 List<AddressFamiliesVrf> adf = mapNewAdFamily.get(rd);
1267 adf = adf != null ? adf : new ArrayList<>();
1268 for (AddressFamiliesVrf s : val.getAddressFamiliesVrf()) {
1269 br.delVrf(rd, s.getAfi(), s.getSafi());
1270 adf.remove(s);// remove in the map the vrf in waiting for advertise quagga
1272 if (adf.isEmpty()) {
1273 mapNewAdFamily.remove(rd);
1275 } catch (TException | BgpRouterException e) {
1276 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1282 protected void update(InstanceIdentifier<Vrfs> iid,
1283 Vrfs oldval, Vrfs newval) {
1284 if (oldval != null && newval != null) {
1285 LOG.debug("received update Vrfs config val {}, VRFS: Update getting triggered for VRFS rd {}",
1286 newval.getRd(), oldval.getRd());
1288 LOG.debug("received update Vrfs config val {}, from old vrf {}",
1291 if (!isBGPEntityOwner()) {
1295 List<AddressFamiliesVrf> adFamilyVrfToDel = new ArrayList<>();
1296 List<AddressFamiliesVrf> adFamilyVrfToAdd = new ArrayList<>();
1297 List<AddressFamiliesVrf> oldlistAdFamilies = new ArrayList<>();
1298 List<AddressFamiliesVrf> newlistAdFamilies = new ArrayList<>();
1299 if (oldval != null) {
1300 oldlistAdFamilies = oldval.getAddressFamiliesVrf() == null
1301 ? new ArrayList<>() : oldval.getAddressFamiliesVrf();
1303 if (newval != null) {
1304 newlistAdFamilies = newval.getAddressFamiliesVrf() == null
1305 ? new ArrayList<>() : newval.getAddressFamiliesVrf();
1307 /*find old AddressFamily to remove from new configuration*/
1308 for (AddressFamiliesVrf adVrf : oldlistAdFamilies) {
1309 if (!newlistAdFamilies.contains(adVrf)) {
1310 adFamilyVrfToDel.add(adVrf);
1313 /*find new AddressFamily to add to unexisting configuration*/
1314 for (AddressFamiliesVrf adVrf : newlistAdFamilies) {
1315 if (!oldlistAdFamilies.contains(adVrf)) {
1316 adFamilyVrfToAdd.add(adVrf);
1319 String rd = newval != null ? newval.getRd() : null;
1321 BgpRouter br = getClient(YANG_OBJ);
1323 LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
1324 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1328 for (AddressFamiliesVrf adfvrf : adFamilyVrfToAdd) {
1330 LOG.debug("call addVRf rd {} afi {} safi {}", rd, adfvrf.getAfi(), adfvrf.getSafi());
1331 br.addVrf(BgpUtil.getLayerType(adfvrf), rd, newval.getImportRts(),
1332 newval.getExportRts(), adfvrf.getAfi(), adfvrf.getSafi());
1333 } catch (TException | BgpRouterException e) {
1334 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1338 for (AddressFamiliesVrf adfToDel : adFamilyVrfToDel) {
1340 LOG.debug("call delVRf rd {} afi {} safi {}", rd, adfToDel.getAfi(), adfToDel.getSafi());
1341 br.delVrf(rd, adfToDel.getAfi(), adfToDel.getSafi());
1342 } catch (TException | BgpRouterException e) {
1343 LOG.error("{} delVrf received exception; {}", YANG_OBJ, ADD_WARN, e);
1350 protected void activateMIP() {
1352 LOG.trace("BgpReactor: Executing MIP Activate command");
1353 Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1354 Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1355 LOG.trace("bgpMIP Activated");
1357 } catch (IOException io) {
1358 LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1362 public class BgpReactor
1363 extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1364 implements ClusteredDataTreeChangeListener<Bgp> {
1366 private static final String YANG_OBJ = "Bgp ";
1368 public BgpReactor() {
1369 super(Bgp.class, BgpReactor.class);
1374 protected void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1375 LOG.debug("received add Bgp config");
1379 } catch (InterruptedException e) {
1382 synchronized (BgpConfigurationManager.this) {
1384 if (!isBGPEntityOwner()) {
1392 protected BgpReactor getDataTreeChangeListener() {
1393 return BgpReactor.this;
1397 protected InstanceIdentifier<Bgp> getWildCardPath() {
1398 return InstanceIdentifier.create(Bgp.class);
1402 protected void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1403 if (!isBGPEntityOwner()) {
1406 LOG.debug("received remove Bgp config");
1412 protected void update(InstanceIdentifier<Bgp> iid,
1413 Bgp oldval, Bgp newval) {
1414 if (!isBGPEntityOwner()) {
1422 @SuppressWarnings("deprecation")
1423 public class MultipathReactor
1424 extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1425 implements ClusteredDataTreeChangeListener<Multipath> {
1427 private static final String YANG_OBJ = "multipath ";
1429 public MultipathReactor() {
1430 super(Multipath.class, MultipathReactor.class);
1435 protected MultipathReactor getDataTreeChangeListener() {
1436 return MultipathReactor.this;
1440 protected InstanceIdentifier<Multipath> getWildCardPath() {
1441 return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
1445 protected void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1446 executor.execute(new MultipathStatusChange(val));
1450 protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1451 executor.execute(new MultipathStatusChange(newval));
1455 protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1456 executor.execute(new MultipathStatusChange(dataObjectModification));
1459 class MultipathStatusChange implements Runnable {
1461 Multipath multipath;
1463 MultipathStatusChange(Multipath multipath) {
1464 this.multipath = multipath;
1469 if (isBGPEntityOwner()) {
1470 synchronized (BgpConfigurationManager.this) {
1472 BgpRouter br = getClient(YANG_OBJ);
1475 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1476 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1479 if (multipath.isMultipathEnabled()) {
1480 br.enableMultipath(afi, safi);
1482 br.disableMultipath(afi, safi);
1484 } catch (TException | BgpRouterException e) {
1485 LOG.error(YANG_OBJ + " received exception: \"" + e + "\"");
1495 public void close() {
1500 @SuppressWarnings("deprecation")
1501 public class VrfMaxpathReactor
1502 extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1503 implements ClusteredDataTreeChangeListener<VrfMaxpath> {
1505 private static final String YANG_OBJ = "vrfMaxpath ";
1507 public VrfMaxpathReactor() {
1508 super(VrfMaxpath.class, VrfMaxpathReactor.class);
1513 protected VrfMaxpathReactor getDataTreeChangeListener() {
1514 return VrfMaxpathReactor.this;
1518 protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1519 return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
1522 class VrfMaxPathConfigurator implements Runnable {
1524 VrfMaxpath vrfMaxpathVal;
1526 VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1527 this.vrfMaxpathVal = vrfMaxPathVal;
1532 if (isBGPEntityOwner()) {
1533 synchronized (BgpConfigurationManager.this) {
1534 BgpRouter br = getClient(YANG_OBJ);
1537 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
1538 LOG.debug("Maxpath for vrf: " + vrfMaxpathVal.getRd() + " : is "
1539 + vrfMaxpathVal.getMaxpaths());
1540 } catch (TException | BgpRouterException e) {
1542 + " received exception: \"" + e + "\"");
1551 protected void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1552 executor.execute(new VrfMaxPathConfigurator(vrfMaxPathVal));
1556 protected void update(InstanceIdentifier<VrfMaxpath> iid,
1557 VrfMaxpath oldval, VrfMaxpath newval) {
1558 if (!Objects.equals(oldval.getMaxpaths(), newval.getMaxpaths())) {
1559 executor.execute(new VrfMaxPathConfigurator(newval));
1564 protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1565 executor.execute(new VrfMaxPathConfigurator(vrfMaxpathVal));
1569 public void close() {
1574 public boolean isIpAvailable(String odlip) {
1577 if (odlip != null) {
1578 if ("127.0.0.1".equals(odlip)) {
1581 Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1582 while (networkInterfaceEnumeration.hasMoreElements()) {
1583 NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
1584 Enumeration<InetAddress> inetAddressEnumeration = networkInterface.getInetAddresses();
1585 while (inetAddressEnumeration.hasMoreElements()) {
1586 InetAddress inetAddress = inetAddressEnumeration.nextElement();
1587 if (odlip.equals(inetAddress.getHostAddress())) {
1593 } catch (SocketException e) {
1599 public long getStalePathtime(int defValue, AsId asId) {
1602 spt = getConfig().getGracefulRestart().getStalepathTime();
1603 } catch (NullPointerException e) {
1605 spt = asId.getStalepathTime();
1606 LOG.trace("BGP config/Stale-path time is not set using graceful");
1607 } catch (NullPointerException ignore) {
1608 LOG.trace("BGP AS id is not set using graceful");
1613 LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1619 public static boolean isValidConfigBgpHostPort(String bgpHost, int bgpPort) {
1620 if (!bgpHost.equals(DEF_CHOST) && bgpPort != Integer.parseInt(DEF_CPORT)) {
1627 public synchronized void bgpRestarted() {
1629 * If there a thread which in the process of stale cleanup, cancel it
1630 * and start a new thread (to avoid processing same again).
1632 if (previousReplayJobInProgress()) {
1633 cancelPreviousReplayJob();
1635 Runnable task = () -> {
1637 LOG.info("running bgp replay task ");
1638 if (get() == null) {
1639 String host = getConfigHost();
1640 int port = getConfigPort();
1641 LOG.info("connecting to bgp host {} ", host);
1642 bgpRouter.connect(host, port);
1643 LOG.info("no config to push in bgp replay task ");
1646 setStaleStartTime(System.currentTimeMillis());
1647 LOG.info("started creating stale fibDSWriter map ");
1648 createStaleFibMap();
1649 setStaleEndTime(System.currentTimeMillis());
1650 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1651 LOG.info("started bgp config replay ");
1652 setCfgReplayStartTime(System.currentTimeMillis());
1653 boolean replaySucceded = replay();
1654 setCfgReplayEndTime(System.currentTimeMillis());
1655 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1656 if (replaySucceded) {
1657 LOG.info("starting the stale cleanup timer");
1658 long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1659 setStaleCleanupTime(routeSyncTime);
1660 routeCleanupFuture = executor.schedule(new RouteCleanup(), routeSyncTime, TimeUnit.SECONDS);
1662 staledFibEntriesMap.clear();
1664 } catch (InterruptedException | TimeoutException | ExecutionException eCancel) {
1665 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1668 lastReplayJobFt = executor.submit(task);
1671 private boolean previousReplayJobInProgress() {
1672 return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1675 private void cancelPreviousReplayJob() {
1677 LOG.error("cancelling already running bgp replay task");
1678 if (lastReplayJobFt != null) {
1679 lastReplayJobFt.cancel(true);
1680 lastReplayJobFt = null;
1681 staledFibEntriesMap.clear();
1683 if (routeCleanupFuture != null) {
1684 routeCleanupFuture.cancel(true);
1685 routeCleanupFuture = null;
1686 staledFibEntriesMap.clear();
1689 } catch (InterruptedException e) {
1690 LOG.error("Failed to cancel previous replay job ", e);
1694 private void doRouteSync() {
1695 LOG.error("Starting BGP route sync");
1697 bgpRouter.initRibSync(bgpSyncHandle);
1698 } catch (BgpRouterException e) {
1699 LOG.error("Route sync aborted, exception when initializing", e);
1702 while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
1703 for (af_afi afi : af_afi.values()) {
1704 Routes routes = null;
1706 routes = bgpRouter.doRibSync(bgpSyncHandle, afi);
1707 } catch (TException | BgpRouterException e) {
1708 LOG.error("Route sync aborted, exception when syncing", e);
1711 Iterator<Update> updates = routes.getUpdatesIterator();
1712 while (updates.hasNext()) {
1713 Update update = updates.next();
1714 String rd = update.getRd();
1715 String nexthop = update.getNexthop();
1717 // TODO: decide correct label here
1718 int label = update.getL3label();
1719 int l2label = update.getL2label();
1721 String prefix = update.getPrefix();
1722 int plen = update.getPrefixlen();
1725 // TODO: protocol type will not be available in "update"
1726 // use "rd" to query vrf table and obtain the protocol_type.
1727 // Currently using PROTOCOL_EVPN as default.
1729 protocol_type.PROTOCOL_EVPN,
1736 update.getMacaddress(),
1739 update.getRoutermac(),
1745 LOG.error("Ending BGP route-sync");
1746 bgpRouter.endRibSync(bgpSyncHandle);
1747 } catch (BgpRouterException e) {
1752 public void addTepToElanDS(String rd, String tepIp, String mac, Long l2vni) {
1753 boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
1755 LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
1756 bgpUtil.addTepToElanInstance(rd, tepIp);
1758 LOG.debug("Skipping the Elan update for RT2 from tep {} rd {}", tepIp, rd);
1762 public void deleteTepfromElanDS(String rd, String tepIp, String mac) {
1763 boolean needUpdate = deleteFromRt2TepMap(rd, tepIp, mac);
1765 LOG.info("Deleting tepIp {} with RD {} to ELan DS", tepIp, rd);
1766 bgpUtil.deleteTepFromElanInstance(rd, tepIp);
1768 LOG.debug("Skipping the Elan update for RT2 withdraw from tep {} rd {}", tepIp, rd);
1772 /* onUpdatePushRoute
1773 * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1774 * - Entry compare shall include NextHop, Label.
1775 * - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1776 * - If entry not found, add to FIB Config DS.
1777 * - If entry found, but either Label/NextHop doesn't match.
1778 * - Update FIB Config DS with modified values.
1779 * - delete from Stale Map.
1782 public void onUpdatePushRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1783 int ethtag, String esi, String macaddress, int label, int l2label, String routermac, af_afi afi) {
1784 boolean addroute = false;
1785 boolean macupdate = false;
1787 VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1788 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1789 encapType = VrfEntry.EncapType.Vxlan;
1790 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1791 if (vpnInstanceOpDataEntry != null) {
1792 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1793 LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
1794 vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
1795 addTepToElanDS(rd, nextHop, macaddress, (long)l2label);
1798 l3vni = vpnInstanceOpDataEntry.getL3vni();
1801 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1806 if (!staledFibEntriesMap.isEmpty()) {
1807 // restart Scenario, as MAP is not empty.
1808 Map<String, Long> map = staledFibEntriesMap.get(rd);
1810 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1811 Long labelInStaleMap = map.get(prefixNextHop);
1812 if (null == labelInStaleMap) {
1813 // New Entry, which happened to be added during restart.
1816 map.remove(prefixNextHop);
1817 if (isRouteModified(label, labelInStaleMap)) {
1818 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1819 // Existing entry, where in Label got modified during restart
1824 LOG.debug("rd {} map is null while processing prefix {} ", rd, prefix);
1828 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1832 LOG.info("ADD: Adding Mac Fib entry rd {} mac{} nexthop {} l2vni {}", rd, macaddress, nextHop, l2label);
1833 fibDSWriter.addMacEntryToDS(rd, macaddress, prefix, Collections.singletonList(nextHop),
1834 encapType, l2label, routermac, RouteOrigin.BGP);
1835 LOG.info("ADD: Added Mac Fib entry rd {} prefix {} nexthop {} label {}", rd, macaddress, nextHop, l2label);
1836 } else if (addroute) {
1837 LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
1838 rd, prefix, nextHop, label, afi);
1839 // TODO: modify addFibEntryToDS signature
1840 List<String> nextHopList = Collections.singletonList(nextHop);
1841 fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
1842 routermac, RouteOrigin.BGP);
1843 LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1844 String vpnName = bgpUtil.getVpnNameFromRd(rd);
1845 if (vpnName != null) {
1846 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, nextHopList, label, RouteOrigin.BGP,
1847 NwConstants.ADD_FLOW);
1852 public void onUpdateWithdrawRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1853 String macaddress) {
1855 boolean macupdate = false;
1856 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1857 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1858 if (vpnInstanceOpDataEntry != null) {
1859 vni = vpnInstanceOpDataEntry.getL3vni();
1860 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1861 LOG.debug("Got RT2 withdraw for RD %s from tep %s with mac %s remote RD %s",
1862 vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
1863 deleteTepfromElanDS(rd, nextHop, macaddress);
1864 LOG.debug("For rd %s. skipping fib update", rd);
1868 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1873 LOG.info("Removing Mac Fib entry rd {} mac{} nexthop {} ", rd, macaddress, nextHop);
1874 fibDSWriter.removeMacEntryFromDS(rd, macaddress);
1875 LOG.info("Removed Mac Fib entry rd {} prefix {} nexthop {} ", rd, macaddress, nextHop);
1877 LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
1878 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nextHop);
1879 LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
1883 //TODO: below function is for testing purpose with cli
1884 public void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
1885 LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
1886 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
1887 String vpnName = bgpUtil.getVpnNameFromRd(rd);
1888 if (vpnName != null) {
1889 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
1890 RouteOrigin.BGP, NwConstants.DEL_FLOW);
1894 private static boolean isRouteModified(int label, Long labelInStaleMap) {
1895 return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
1898 static class ReplayNbr {
1900 boolean shouldRetry = false;
1902 public Neighbors getNbr() {
1906 public boolean isShouldRetry() {
1910 public void setShouldRetry(boolean retryNbr) {
1911 this.shouldRetry = retryNbr;
1914 ReplayNbr(Neighbors nbr, boolean shouldRetry) {
1916 this.shouldRetry = shouldRetry;
1920 private static boolean replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1921 if (neighbors == null || neighbors.isEmpty()) {
1922 LOG.error("Replaying nbr configuration, received NULL list ");
1926 List<ReplayNbr> replayNbrList = new ArrayList<>();
1927 for (Neighbors nbr : neighbors) {
1929 replayNbrList.add(new ReplayNbr(nbr, true));
1932 final int numberOfNbrRetries = 3;
1933 RetryOnException nbrRetry = new RetryOnException(numberOfNbrRetries);
1935 for (ReplayNbr replayNbr : replayNbrList) {
1936 if (!replayNbr.isShouldRetry()) {
1939 boolean replayDone = false;
1940 LOG.debug("Replaying addNbr {}", replayNbr.getNbr().getAddress().getValue());
1943 final String md5password = extractMd5Secret(replayNbr.getNbr());
1944 br.addNeighbor(replayNbr.getNbr().getAddress().getValue(),
1945 replayNbr.getNbr().getRemoteAs().longValue(), md5password);
1946 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1948 LOG.debug("Replaying updatesource along with nbr: {} US-ip: {} to peer {}",
1949 replayNbr.getNbr().getAddress().getValue(),
1950 us.getSourceIp().getValue(),
1951 us.getPeerIp().getValue());
1952 br.addUpdateSource(us.getPeerIp().getValue(),
1953 us.getSourceIp().getValue());
1956 } catch (TException | BgpRouterException eNbr) {
1957 LOG.debug("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), eNbr);
1959 boolean replaySuccess = true;
1960 replaySuccess = replaySuccess && replayDone;
1961 LOG.debug("Replay addNbr {} successful", replayNbr.getNbr().getAddress().getValue());
1963 //Update Source handling
1964 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1965 if (replayDone == false && us != null) {
1966 LOG.debug("Replaying updatesource {} to peer {}", us.getSourceIp().getValue(),
1967 us.getPeerIp().getValue());
1970 br.addUpdateSource(us.getPeerIp().getValue(),
1971 us.getSourceIp().getValue());
1973 } catch (TException | BgpRouterException eUs) {
1974 LOG.debug("Replaying UpdateSource for Nbr {}, exception:",
1975 replayNbr.getNbr().getAddress().getValue(), eUs);
1977 LOG.debug("Replay updatesource {} successful", us.getSourceIp().getValue());
1978 replaySuccess = replaySuccess && replayDone;
1981 EbgpMultihop en = replayNbr.getNbr().getEbgpMultihop();
1985 br.addEbgpMultihop(en.getPeerIp().getValue(),
1986 en.getNhops().intValue());
1988 } catch (TException | BgpRouterException eEbgpMhop) {
1989 LOG.debug("Replaying EbgpMultihop for Nbr {}, exception: ",
1990 replayNbr.getNbr().getAddress().getValue(), eEbgpMhop);
1992 replaySuccess = replaySuccess && replayDone;
1996 List<AddressFamilies> afs = replayNbr.getNbr().getAddressFamilies();
1998 for (AddressFamilies af : afs) {
1999 af_afi afi = af_afi.findByValue(af.getAfi().intValue());
2000 af_safi safi = af_safi.findByValue(af.getSafi().intValue());
2003 br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
2005 } catch (TException | BgpRouterException eAFs) {
2006 LOG.debug("Replaying AddressFamily for Nbr {}, exception:",
2007 replayNbr.getNbr().getAddress().getValue(), eAFs);
2009 replaySuccess = replaySuccess && replayDone;
2012 //replay is success --> no need to replay this nbr in next iteration.
2013 replayNbr.setShouldRetry(replaySuccess ? false : true);
2015 } while (nbrRetry.decrementAndRetry());
2016 boolean replaySuccess = true;
2017 for (ReplayNbr replayNbr : replayNbrList) {
2018 replaySuccess = replaySuccess && !replayNbr.isShouldRetry();
2020 return replaySuccess;
2023 public String getConfigHost() {
2024 if (config == null) {
2027 ConfigServer ts = config.getConfigServer();
2028 return ts == null ? hostStartup : ts.getHost().getValue();
2031 public int getConfigPort() {
2032 if (config == null) {
2033 return Integer.parseInt(portStartup);
2035 ConfigServer ts = config.getConfigServer();
2036 return ts == null ? Integer.parseInt(portStartup) :
2037 ts.getPort().intValue();
2040 public Bgp getConfig() {
2041 AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COUNT);
2042 while (0 != bgpDSretryCount.decrementAndGet()) {
2044 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
2045 InstanceIdentifier.create(Bgp.class)).orNull();
2046 } catch (ReadFailedException e) {
2047 //Config DS may not be up, so sleep for 1 second and retry
2048 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
2050 Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
2051 } catch (InterruptedException timerEx) {
2052 LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
2053 + "config DS availability", timerEx);
2057 LOG.error("failed to get bgp config");
2061 @SuppressWarnings("checkstyle:IllegalCatch")
2062 public synchronized boolean replay() throws InterruptedException, TimeoutException, ExecutionException {
2063 boolean replaySucceded = true;
2064 String host = getConfigHost();
2065 int port = getConfigPort();
2066 LOG.error("connecting to bgp host {} ", host);
2067 boolean res = bgpRouter.connect(host, port);
2069 String msg = "Cannot connect to BGP config server at " + host + ":" + port;
2070 if (config != null) {
2071 msg += "; Configuration Replay aborted";
2074 return replaySucceded;
2076 config = getConfig();
2077 if (config == null) {
2078 LOG.error("bgp config is empty nothing to push to bgp");
2079 return replaySucceded;
2081 BgpRouter br = bgpRouter;
2082 AsId asId = config.getAsId();
2084 LOG.error("bgp as-id is null");
2085 return replaySucceded;
2087 long asNum = asId.getLocalAs();
2088 IpAddress routerId = asId.getRouterId();
2089 String rid = routerId == null ? "" : new String(routerId.getValue());
2090 int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, config.getAsId());
2091 boolean announceFbit = true;
2092 boolean replayDone = false;
2093 final int numberOfStartBgpRetries = 3;
2094 RetryOnException startBgpRetry = new RetryOnException(numberOfStartBgpRetries);
2097 LOG.debug("Replaying BGPConfig ");
2098 br.startBgp(asNum, rid, stalepathTime, announceFbit);
2099 LOG.debug("Replay BGPConfig successful");
2102 } catch (BgpRouterException bre) {
2103 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
2104 LOG.debug("Starting the routesync for exception", bre);
2105 startBgpRetry.errorOccured();
2106 if (!startBgpRetry.shouldRetry()) {
2107 LOG.debug("starting route sync for BgpRouter exception");
2111 LOG.error("Replay: startBgp() received exception error {} : ",
2112 bre.getErrorCode(), bre);
2113 startBgpRetry.errorOccured();
2115 } catch (TApplicationException tae) {
2116 if (tae.getType() == BgpRouterException.BGP_ERR_ACTIVE) {
2117 LOG.debug("Starting the routesync for exception", tae);
2118 startBgpRetry.errorOccured();
2119 if (!startBgpRetry.shouldRetry()) {
2120 LOG.debug("starting route sync for Thrift BGP_ERR_ACTIVE exception");
2123 } else if (tae.getType() == BgpRouterException.BGP_ERR_COMMON_FAILURE) {
2124 LOG.debug("Starting the routesync for AS-ID started exception", tae);
2125 startBgpRetry.errorOccured();
2126 if (!startBgpRetry.shouldRetry()) {
2127 LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception");
2131 LOG.error("Replay: startBgp() received exception type {}: ",
2132 tae.getType(), tae);
2133 startBgpRetry.errorOccured();
2135 } catch (Exception e) {
2136 //not unusual. We may have restarted & BGP is already on
2137 LOG.error("Replay:startBgp() received exception: ", e);
2138 startBgpRetry.errorOccured();
2140 } while (startBgpRetry.shouldRetry());
2142 replaySucceded = replayDone;
2144 startBgpCountersTask();
2145 startBgpAlarmsTask();
2148 * commenting this due to a bug with QBGP. Will uncomment once QBGP fix is done.
2149 * This wont have any functional impacts
2152 // br.delayEOR(delayEorSeconds);
2153 //} catch (TException | BgpRouterException e) {
2154 // LOG.error("Replay: delayEOR() number of seconds to wait for EOR from ODL:", e);
2157 List<Neighbors> neighbors = config.getNeighbors();
2158 if (neighbors != null) {
2159 LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
2160 boolean neighborConfigReplayResult = replayNbrConfig(neighbors, br);
2161 if (neighborConfigReplayResult == false) {
2162 replaySucceded = false;
2165 LOG.error("no Neighbors present for replay config ");
2168 Logging logging = config.getLogging();
2169 if (logging != null) {
2171 br.setLogging(logging.getFile(), logging.getLevel());
2172 } catch (TException | BgpRouterException e) {
2173 LOG.error("Replay:setLogging() received exception", e);
2177 GracefulRestart gracefulRestart = config.getGracefulRestart();
2178 if (gracefulRestart != null) {
2180 br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
2181 } catch (TException | BgpRouterException e) {
2182 LOG.error("Replay:addGr() received exception", e);
2186 List<Vrfs> vrfs = config.getVrfs();
2188 vrfs = new ArrayList<>();
2190 for (Vrfs vrf : vrfs) {
2191 for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf()) {
2193 br.addVrf(BgpUtil.getLayerType(adf), vrf.getRd(), vrf.getImportRts(),
2194 vrf.getExportRts(), adf.getAfi(), adf.getSafi());
2195 } catch (TException | BgpRouterException e) {
2196 LOG.error("Replay:addVrf() received exception", e);
2201 List<Networks> ln = config.getNetworks();
2203 for (Networks net : ln) {
2204 String rd = net.getRd();
2205 String pfxlen = net.getPrefixLen();
2206 String nh = net.getNexthop().getValue();
2207 Long label = net.getLabel();
2208 int lbl = label == null ? 0 : label.intValue();
2209 int l3vni = net.getL3vni() == null ? 0 : net.getL3vni().intValue();
2210 int l2vni = net.getL2vni() == null ? 0 : net.getL2vni().intValue();
2211 if (rd == null && lbl > 0) {
2212 //LU prefix is being deleted.
2213 rd = Integer.toString(lbl);
2216 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
2217 int ethernetTag = net.getEthtag().intValue();
2218 String esi = net.getEsi();
2219 String macaddress = net.getMacaddress();
2220 EncapType encapType = net.getEncapType();
2221 String routerMac = net.getRoutermac();
2224 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni,
2225 BgpUtil.convertToThriftProtocolType(protocolType),
2226 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
2227 } catch (TException | BgpRouterException e) {
2228 LOG.error("Replay:addPfx() received exception", e);
2234 List<Multipath> multipaths = config.getMultipath();
2236 if (multipaths != null) {
2237 for (Multipath multipath : multipaths) {
2238 if (multipath != null) {
2239 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
2240 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
2243 if (multipath.isMultipathEnabled()) {
2244 br.enableMultipath(afi, safi);
2246 br.disableMultipath(afi, safi);
2248 } catch (TException | BgpRouterException e) {
2249 LOG.info("Replay:multipaths() received exception: \"" + e + "\"");
2254 List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
2255 if (vrfMaxpaths != null) {
2256 for (VrfMaxpath vrfMaxpath : vrfMaxpaths) {
2258 br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
2259 } catch (TException | BgpRouterException e) {
2260 LOG.info("Replay:vrfMaxPath() received exception: \"" + e + "\"");
2265 //send End of Rib Marker to Qthriftd.
2266 final int numberOfEORRetries = 3;
2268 RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
2272 LOG.debug("Replay sendEOR {} successful");
2275 } catch (Exception e) {
2276 eorRetry.errorOccured();
2277 LOG.error("Replay:sedEOR() received exception:", e);
2279 } while (eorRetry.shouldRetry());
2281 return replaySucceded && replayDone;
2284 private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
2285 bgpUtil.update(LogicalDatastoreType.CONFIGURATION, iid, dto);
2288 private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
2289 bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, iid);
2292 public void startConfig(String bgpHost, int thriftPort) {
2293 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2294 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2295 InstanceIdentifier<ConfigServer> iid = iib.build();
2296 Ipv4Address ipAddr = new Ipv4Address(bgpHost);
2297 ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
2298 .setPort((long) thriftPort).build();
2302 public void startBgp(long as, String routerId, int spt, boolean fbit) {
2303 IpAddress rid = routerId == null ? null : new IpAddress(routerId.toCharArray());
2304 Long staleTime = (long) spt;
2305 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2306 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2307 InstanceIdentifier<AsId> iid = iib.build();
2308 AsId dto = new AsIdBuilder().setLocalAs(as)
2310 .setStalepathTime(staleTime)
2311 .setAnnounceFbit(fbit).build();
2315 public void addLogging(String fileName, String logLevel) {
2316 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2317 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2318 InstanceIdentifier<Logging> iid = iib.build();
2319 Logging dto = new LoggingBuilder().setFile(fileName)
2320 .setLevel(logLevel).build();
2324 public void addGracefulRestart(int staleTime) {
2325 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2326 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2327 InstanceIdentifier<GracefulRestart> iid = iib.build();
2328 GracefulRestart dto = new GracefulRestartBuilder()
2329 .setStalepathTime((long) staleTime).build();
2333 public void addNeighbor(
2334 String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2335 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2336 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2337 InstanceIdentifier.builder(Bgp.class)
2338 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2339 InstanceIdentifier<Neighbors> iid = iib.build();
2340 TcpSecurityOption tcpSecOption = null;
2341 if (md5Secret != null) {
2342 tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2343 } // else let tcpSecOption be null
2344 Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2345 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2347 } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2349 public void addUpdateSource(String nbrIp, String srcIp) {
2350 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2351 Ipv4Address srcAddr = new Ipv4Address(srcIp);
2352 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2353 InstanceIdentifier.builder(Bgp.class)
2354 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2355 .child(UpdateSource.class);
2356 InstanceIdentifier<UpdateSource> iid = iib.build();
2357 UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2358 .setSourceIp(srcAddr).build();
2362 public void addEbgpMultihop(String nbrIp, int hops) {
2363 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2364 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2365 InstanceIdentifier.builder(Bgp.class)
2366 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2367 .child(EbgpMultihop.class);
2368 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2369 EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2370 .setNhops((long) hops).build();
2374 public void addAddressFamily(String nbrIp, int afi, int safi) {
2375 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2376 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2377 InstanceIdentifier.builder(Bgp.class)
2378 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2379 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2380 InstanceIdentifier<AddressFamilies> iid = iib.build();
2381 AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2382 .setAfi((long) afi).setSafi((long) safi).build();
2386 public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2387 VrfEntry.EncapType encapType, long lbl, long l3vni, long l2vni, String gatewayMac) {
2388 for (String nh : nhList) {
2389 Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2391 InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2392 .child(Networks.class, new NetworksKey(pfx, rd)).build();
2393 NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2394 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
2395 buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, l2vni, macAddress, gatewayMac);
2396 update(iid, networksBuilder.build());
2400 private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
2401 long l3vni, long l2vni, String macAddress, String gatewayMac) {
2402 if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2403 builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2404 .setEncapType(EncapType.GRE);
2406 builder.setL3vni(l3vni).setL2vni(l2vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2407 .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2411 // TODO: add LayerType as arg - supports command
2412 public void addVrf(String rd, List<String> irts, List<String> erts, AddressFamily addressFamily) {
2413 Vrfs vrf = bgpUtil.getVrfFromRd(rd);
2414 List<AddressFamiliesVrf> adfList = new ArrayList<>(1);
2416 adfList = vrf.getAddressFamiliesVrf();
2418 AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2419 if (addressFamily.equals(AddressFamily.IPV4)) {
2420 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2421 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2422 } else if (addressFamily.equals(AddressFamily.IPV6)) {
2423 adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2424 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2425 } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2426 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2427 adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2429 AddressFamiliesVrf adf = adfBuilder.build();
2431 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = InstanceIdentifier.builder(Bgp.class)
2432 .child(Vrfs.class, new VrfsKey(rd));
2433 InstanceIdentifier<Vrfs> iid = iib.build();
2434 Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2435 .setExportRts(erts).setAddressFamiliesVrf(adfList).build();
2437 List<AddressFamiliesVrf> listAdFamilies = mapNewAdFamily.get(rd);
2438 if (listAdFamilies != null) {
2439 listAdFamilies.add(adf);
2441 mapNewAdFamily.put(rd, adfList);
2445 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2446 } catch (TransactionCommitFailedException e) {
2447 LOG.error("Error adding VRF to datastore", e);
2448 throw new RuntimeException(e);
2452 public void stopConfig() {
2453 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2454 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2455 InstanceIdentifier<ConfigServer> iid = iib.build();
2459 public void stopBgp() {
2460 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2461 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2462 InstanceIdentifier<AsId> iid = iib.build();
2466 public void delLogging() {
2467 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2468 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2469 InstanceIdentifier<Logging> iid = iib.build();
2473 public void delGracefulRestart() {
2474 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2475 InstanceIdentifier.builder(Bgp.class)
2476 .child(GracefulRestart.class);
2477 InstanceIdentifier<GracefulRestart> iid = iib.build();
2481 public void delNeighbor(String nbrIp) {
2482 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2483 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2484 InstanceIdentifier.builder(Bgp.class)
2485 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2486 InstanceIdentifier<Neighbors> iid = iib.build();
2490 public void delUpdateSource(String nbrIp) {
2491 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2492 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2493 InstanceIdentifier.builder(Bgp.class)
2494 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2495 .child(UpdateSource.class);
2496 InstanceIdentifier<UpdateSource> iid = iib.build();
2500 public void delEbgpMultihop(String nbrIp) {
2501 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2502 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2503 InstanceIdentifier.builder(Bgp.class)
2504 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2505 .child(EbgpMultihop.class);
2506 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2510 public void delAddressFamily(String nbrIp, int afi, int safi) {
2511 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2512 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2513 InstanceIdentifier.builder(Bgp.class)
2514 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2515 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2516 InstanceIdentifier<AddressFamilies> iid = iib.build();
2520 public void delPrefix(String rd, String pfx) {
2521 InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2522 InstanceIdentifier.builder(Bgp.class)
2523 .child(Networks.class, new NetworksKey(pfx, rd));
2524 InstanceIdentifier<Networks> iid = iib.build();
2528 public boolean delVrf(String rd, AddressFamily addressFamily) {
2529 if (addressFamily == null) {
2530 LOG.error("delVrf: vrf {}, addressFamily invalid", rd);
2533 AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2534 if (addressFamily.equals(AddressFamily.IPV4)) {
2535 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2536 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2537 } else if (addressFamily.equals(AddressFamily.IPV6)) {
2538 adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2539 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2540 } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2541 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2542 adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2544 Vrfs vrfOriginal = bgpUtil.getVrfFromRd(rd);
2545 if (vrfOriginal == null) {
2546 LOG.error("delVrf: no vrf with existing rd {}. step aborted", rd);
2550 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2551 InstanceIdentifier.builder(Bgp.class)
2552 .child(Vrfs.class, new VrfsKey(rd));
2554 InstanceIdentifier<Vrfs> iid = iib.build();
2556 @SuppressWarnings("static-access")
2557 InstanceIdentifier<Bgp> iid6 = iid.builder(Bgp.class).build()
2558 .child(Multipath.class, new MultipathKey(adfBuilder.getAfi(), adfBuilder.getSafi())).create(Bgp.class);
2559 InstanceIdentifierBuilder<Vrfs> iib3 = iid6.child(Vrfs.class, new VrfsKey(rd)).builder();
2560 InstanceIdentifier<Vrfs> iidFinal = iib3.build();
2562 //** update or delete the vrfs with the rest of AddressFamilies already present in the last list
2563 AddressFamiliesVrf adfToDel = adfBuilder.build();
2564 List<AddressFamiliesVrf> adfListOriginal = vrfOriginal.getAddressFamiliesVrf() == null
2565 ? new ArrayList<>() : vrfOriginal.getAddressFamiliesVrf();
2566 List<AddressFamiliesVrf> adfListToRemoveFromOriginal = new ArrayList<>();
2567 adfListOriginal.forEach(adf -> {
2568 if (adf.equals(adfToDel)) {
2569 adfListToRemoveFromOriginal.add(adfToDel);
2573 for (AddressFamiliesVrf adfToRemove : adfListToRemoveFromOriginal) {
2574 adfListOriginal.remove(adfToRemove);
2576 SingleTransactionDataBroker.syncWrite(dataBroker,
2577 LogicalDatastoreType.CONFIGURATION, iid, vrfOriginal);
2578 } catch (TransactionCommitFailedException e) {
2579 LOG.error("delVrf: Error updating VRF to datastore", e);
2580 throw new RuntimeException(e);
2583 if (adfListOriginal.isEmpty()) {
2587 // not all is removed
2591 public void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2592 long lafi = afi.getValue();
2593 long lsafi = safi.getValue();
2595 InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2598 .child(Multipath.class,
2599 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2601 Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2602 update(iib.build(), dto);
2605 public void multipaths(String rd, int maxpath) {
2606 InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2609 .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2611 VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2612 update(iib.build(), dto);
2616 * Remove Stale Marked Routes after timer expiry.
2618 private class RouteCleanup implements Callable<Integer> {
2621 public Integer call() {
2624 if (staledFibEntriesMap.isEmpty()) {
2625 LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2627 for (String rd : staledFibEntriesMap.keySet()) {
2628 if (Thread.interrupted()) {
2631 Map<String, Long> map = staledFibEntriesMap.get(rd);
2633 for (String key : map.keySet()) {
2634 if (Thread.interrupted()) {
2637 String prefix = extractPrefix(key);
2638 String nextHop = extractNextHop(key);
2640 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
2641 rd, prefix, nextHop);
2642 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
2648 staledFibEntriesMap.clear();
2650 LOG.error("cleared {} stale routes after bgp restart", totalCleared);
2656 * BGP restart scenario, ODL-BGP manager was/is running.
2657 * On re-sync notification, Get a copy of FIB database.
2659 public void createStaleFibMap() {
2660 totalStaledCount = 0;
2662 staledFibEntriesMap.clear();
2663 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2665 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2666 LogicalDatastoreType.CONFIGURATION, id);
2667 if (fibEntries.isPresent()) {
2668 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2669 for (VrfTables vrfTable : staleVrfTables) {
2670 Map<String, Long> staleFibEntMap = new HashMap<>();
2671 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2672 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2673 //Stale marking and cleanup is only meant for the routes learned through BGP.
2676 if (Thread.interrupted()) {
2680 //Create MAP from staleVrfTables.
2681 vrfEntry.getRoutePaths()
2683 routePath -> staleFibEntMap.put(
2684 appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2685 routePath.getNexthopAddress()), routePath.getLabel()));
2687 staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2690 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2692 } catch (ReadFailedException e) {
2693 LOG.error("createStaleFibMap:: error ", e);
2695 LOG.error("created {} staled entries ", totalStaledCount);
2699 * BGP config remove scenario, Need to remove all the
2700 * external routes from FIB.
2702 public void deleteExternalFibRoutes() {
2703 totalExternalRoutes = 0;
2704 totalExternalMacRoutes = 0;
2706 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2708 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2709 LogicalDatastoreType.CONFIGURATION, id);
2710 if (fibEntries.isPresent()) {
2711 if (fibEntries.get().getVrfTables() == null) {
2712 LOG.error("deleteExternalFibRoutes::getVrfTables is null");
2715 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2716 for (VrfTables vrfTable : staleVrfTables) {
2717 String rd = vrfTable.getRouteDistinguisher();
2718 if (vrfTable.getVrfEntry() != null) {
2719 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2720 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2721 //route cleanup is only meant for the routes learned through BGP.
2724 totalExternalRoutes++;
2725 fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
2727 } else if (vrfTable.getMacVrfEntry() != null) {
2728 for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
2729 if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
2730 //route cleanup is only meant for the routes learned through BGP.
2733 totalExternalMacRoutes++;
2734 fibDSWriter.removeMacEntryFromDS(rd, macEntry.getMac());
2739 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
2741 } catch (ReadFailedException e) {
2742 LOG.error("deleteExternalFibRoutes:: error ", e);
2744 LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
2747 public boolean addToRt2TepMap(String rd, String tepIp, String mac, Long l2vni) {
2748 boolean isFirstMacUpdateFromTep = false;
2749 if (rt2TepMap.containsKey(rd)) {
2750 if (rt2TepMap.get(rd).containsKey(tepIp)) {
2751 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and tep-ip {}. No Elan DS write required",
2752 mac, l2vni, rd, tepIp);
2753 rt2TepMap.get(rd).get(tepIp).put(mac, l2vni);
2755 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
2757 isFirstMacUpdateFromTep = true;
2758 Map<String, Long> macList = new HashMap<>();
2759 macList.put(mac, l2vni);
2760 rt2TepMap.get(rd).put(tepIp, macList);
2763 LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
2764 mac, l2vni, rd, tepIp);
2765 isFirstMacUpdateFromTep = true;
2766 Map<String, Long> macList = new HashMap<>();
2767 macList.put(mac, l2vni);
2768 Map<String, Map<String, Long>> tepIpMacMap = new HashMap<>();
2769 tepIpMacMap.put(tepIp, macList);
2770 rt2TepMap.put(rd, tepIpMacMap);
2772 return isFirstMacUpdateFromTep;
2775 public boolean deleteFromRt2TepMap(String rd, String tepIp, String mac) {
2776 boolean isLastMacUpdateFromTep = false;
2777 LOG.debug("RT2 withdraw with rd {} mac {} tep-ip {} ", rd, mac, tepIp);
2778 if (rt2TepMap.containsKey(rd)) {
2779 if (rt2TepMap.get(rd).containsKey(tepIp)) {
2780 if (rt2TepMap.get(rd).get(tepIp).containsKey(mac)) {
2781 LOG.debug("RT2 Withdraw : Removing the mac {} from Map", mac);
2782 rt2TepMap.get(rd).get(tepIp).remove(mac);
2783 if (rt2TepMap.get(rd).get(tepIp).isEmpty()) {
2784 isLastMacUpdateFromTep = true;
2785 LOG.debug("RT2 Withdraw : Removing the tep-ip {} from Map", tepIp);
2786 rt2TepMap.get(rd).remove(tepIp);
2787 if (rt2TepMap.get(rd).isEmpty()) {
2788 LOG.debug("RT2 Withdraw : Removing the rd {} from Map", rd);
2789 rt2TepMap.remove(rd);
2795 return isLastMacUpdateFromTep;
2798 public Collection<String> getTepIPs(String rd) {
2799 final Map<String, Map<String, Long>> tepIpMap = rt2TepMap.get(rd);
2800 return tepIpMap != null ? tepIpMap.keySet() : Collections.emptyList();
2803 public boolean isBgpConnected() {
2804 return bgpRouter.isBgpConnected();
2807 public long getLastConnectedTS() {
2808 return bgpRouter.getLastConnectedTS();
2811 public long getConnectTS() {
2812 return bgpRouter.getConnectTS();
2815 public long getStartTS() {
2816 return bgpRouter.getStartTS();
2819 public TTransport getTransport() {
2820 return bgpRouter.getTransport();
2823 public int getTotalStaledCount() {
2824 return totalStaledCount;
2827 public int getTotalCleared() {
2828 return totalCleared;
2831 public BgpCounters getBgpCounters() {
2832 return bgpCountersReference.get();
2835 private void startBgpCountersTask() {
2836 if (getBgpCounters() == null && bgpCountersReference.compareAndSet(null,
2837 new BgpCounters(getBgpSdncMipIp(), metricProvider))) {
2838 bgpCountersTask = executor.scheduleAtFixedRate(bgpCountersReference.get(), 0, 120 * 1000,
2839 TimeUnit.MILLISECONDS);
2840 LOG.info("Bgp Counters task scheduled for every two minutes.");
2842 bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2846 private void stopBgpCountersTask() {
2847 final BgpCounters bgpCounters = bgpCountersReference.getAndSet(null);
2848 if (bgpCounters != null) {
2849 bgpCountersTask.cancel(true);
2850 bgpCounters.close();
2854 private void startBgpAlarmsTask() {
2855 if (getBgpAlarms() == null && bgpAlarmsReference.compareAndSet(null, new BgpAlarms(this))) {
2856 bgpAlarmsReference.get().init();
2857 bgpAlarmsTask = executor.scheduleAtFixedRate(bgpAlarmsReference.get(), 0, 60 * 1000, TimeUnit.MILLISECONDS);
2858 LOG.info("Bgp Alarms task scheduled for every minute.");
2862 private void stopBgpAlarmsTask() {
2863 final BgpAlarms bgpAlarms = bgpAlarmsReference.getAndSet(null);
2864 if (bgpAlarms != null) {
2865 bgpAlarmsTask.cancel(true);
2870 public BgpAlarms getBgpAlarms() {
2871 return bgpAlarmsReference.get();
2874 private static String appendNextHopToPrefix(String prefix, String nextHop) {
2875 return prefix + ":" + nextHop;
2878 private static String extractPrefix(String prefixNextHop) {
2879 return prefixNextHop.split(":")[0];
2882 private static String extractNextHop(String prefixNextHop) {
2883 return prefixNextHop.split(":")[1];
2886 private static String extractMd5Secret(final Neighbors val) {
2887 String md5Secret = null;
2888 TcpSecurityOption tcpSecOpt = val.getTcpSecurityOption();
2889 if (tcpSecOpt != null) {
2890 if (tcpSecOpt instanceof TcpMd5SignatureOption) {
2891 md5Secret = ((TcpMd5SignatureOption) tcpSecOpt).getTcpMd5SignaturePassword().getValue();
2892 } else { // unknown TcpSecurityOption
2893 LOG.debug("neighbors Ignored unknown tcp-security-option of peer {}", val.getAddress().getValue());
2897 } // private method extractMd5Secret