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.net.InetAddresses;
12 import com.google.common.util.concurrent.ThreadFactoryBuilder;
13 import io.netty.util.concurrent.GlobalEventExecutor;
14 import java.io.IOException;
15 import java.lang.reflect.Constructor;
16 import java.lang.reflect.InvocationTargetException;
17 import java.net.InetAddress;
18 import java.net.InetSocketAddress;
19 import java.net.NetworkInterface;
20 import java.net.SocketException;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
29 import java.util.Objects;
30 import java.util.Timer;
31 import java.util.concurrent.Callable;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.Executors;
36 import java.util.concurrent.Future;
37 import java.util.concurrent.ScheduledExecutorService;
38 import java.util.concurrent.ScheduledFuture;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.TimeoutException;
41 import java.util.concurrent.atomic.AtomicInteger;
42 import java.util.concurrent.atomic.AtomicReference;
43 import javax.annotation.Nullable;
44 import javax.annotation.PreDestroy;
45 import javax.inject.Inject;
46 import javax.inject.Singleton;
47 import org.apache.thrift.TApplicationException;
48 import org.apache.thrift.TException;
49 import org.apache.thrift.transport.TTransport;
50 import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
51 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
52 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
53 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
54 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
55 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
56 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
57 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
58 import org.opendaylight.genius.mdsalutil.NwConstants;
59 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
60 import org.opendaylight.infrautils.metrics.MetricProvider;
61 import org.opendaylight.mdsal.eos.binding.api.Entity;
62 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
63 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
64 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
65 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
66 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
67 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
68 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
69 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
70 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
71 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
72 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
73 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
74 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
75 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
76 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
77 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
78 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
79 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
80 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
81 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
82 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
83 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
84 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
85 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
86 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
87 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
88 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
89 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
90 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
91 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Multipath;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathBuilder;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathKey;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
102 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
103 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
104 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
105 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
106 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpath;
107 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathBuilder;
108 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathKey;
109 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
110 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
111 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
112 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
113 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
114 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
115 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
116 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
117 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
118 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
119 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrf;
120 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrfBuilder;
121 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
122 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOption;
123 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
124 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
125 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
131 import org.opendaylight.yangtools.yang.binding.DataObject;
132 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
133 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
134 import org.osgi.framework.BundleContext;
135 import org.slf4j.Logger;
136 import org.slf4j.LoggerFactory;
139 public class BgpConfigurationManager {
140 private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
142 // to have stale FIB map (RD, Prefix)
143 // number of seconds wait for route sync-up between ODL and BGP
144 private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
145 private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
146 private static final String DEF_LOGLEVEL = "errors";
147 private static final String UPDATE_PORT = "bgp.thrift.service.port";
148 private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
149 private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
150 private static final String DEF_UPORT = "6644";
151 private static final String DEF_CHOST = "255.255.255.255"; // Invalid Host IP
152 private static final String DEF_CPORT = "0"; // Invalid Port
153 private static final String DEF_BGP_SDNC_MIP = "127.0.0.1";
154 private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.sdnc.mip";
155 private static final int RESTART_DEFAULT_GR = 90;
156 private static final int DS_RETRY_COUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
157 private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
158 private static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
159 private static final String BGP_ENTITY_NAME = "bgp";
160 private static final String ADD_WARN = "Config store updated; undo with Delete if needed.";
161 private static final String DEL_WARN = "Config store updated; undo with Add if needed.";
162 private static final String UPD_WARN = "Update operation not supported; Config store updated;"
163 + " restore with another Update if needed.";
165 private static final Class<?>[] REACTORS = {
166 ConfigServerReactor.class, AsIdReactor.class,
167 GracefulRestartReactor.class, LoggingReactor.class,
168 NeighborsReactor.class, UpdateSourceReactor.class,
169 EbgpMultihopReactor.class, AddressFamiliesReactor.class,
170 NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
171 MultipathReactor.class, VrfMaxpathReactor.class
174 private IBgpManager bgpManager;
175 private final DataBroker dataBroker;
176 private final FibDSWriter fibDSWriter;
177 private final IVpnLinkService vpnLinkService;
178 private final BundleContext bundleContext;
179 private final BgpUtil bgpUtil;
180 private volatile Bgp config;
181 private final BgpRouter bgpRouter;
182 private final BgpSyncHandle bgpSyncHandle = new BgpSyncHandle();
183 private volatile BgpThriftService bgpThriftService = null;
185 private final CountDownLatch initer = new CountDownLatch(1);
187 private final String hostStartup;
188 private final String portStartup;
190 private final AtomicReference<BgpCounters> bgpCountersReference = new AtomicReference<>();
191 private ScheduledFuture<?> bgpCountersTask;
193 private final AtomicReference<BgpAlarms> bgpAlarmsReference = new AtomicReference<>();
194 private ScheduledFuture<?> bgpAlarmsTask;
196 private Future<?> lastReplayJobFt;
197 private ScheduledFuture<?> routeCleanupFuture;
199 private long staleStartTime;
200 private long staleEndTime;
201 private long cfgReplayStartTime;
202 private long cfgReplayEndTime;
203 private long staleCleanupTime;
204 private int totalStaledCount;
205 private int totalCleared;
206 private int totalExternalRoutes;
207 private int totalExternalMacRoutes;
209 private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
210 new ThreadFactoryBuilder().setNameFormat("BgpConfigurationManager-%d").setDaemon(true).build());
213 * this map store the new address families to send to quagga. When it is sended you must clear it.
214 * The keys String are rd (route distinguisher).
216 private final ConcurrentHashMap<String, List<AddressFamiliesVrf>> mapNewAdFamily = new ConcurrentHashMap<>();
218 // map<rd, map<prefix/len:nexthop, label>>
219 private final Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
221 // map<rd, map<tep-ip, map<mac, l2vni>>>
222 private final Map<String, Map<String, Map<String, Long>>> rt2TepMap = new ConcurrentHashMap<>();
224 private final List<AutoCloseable> listeners = new ArrayList<>();
226 private final EntityOwnershipUtils entityOwnershipUtils;
227 private final EntityOwnershipCandidateRegistration candidateRegistration;
228 private final EntityOwnershipListenerRegistration entityListenerRegistration;
229 private final MetricProvider metricProvider;
232 public BgpConfigurationManager(final DataBroker dataBroker,
233 final EntityOwnershipService entityOwnershipService,
234 final FibDSWriter fibDSWriter,
235 final IVpnLinkService vpnLinkSrvce,
236 final BundleContext bundleContext,
237 final BgpUtil bgpUtil,
238 final MetricProvider metricProvider) {
239 this.dataBroker = dataBroker;
240 this.fibDSWriter = fibDSWriter;
241 this.vpnLinkService = vpnLinkSrvce;
242 this.bundleContext = bundleContext;
243 this.bgpUtil = bgpUtil;
244 this.metricProvider = metricProvider;
245 String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
246 hostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
247 portStartup = getProperty(CONFIG_PORT, DEF_CPORT);
248 LOG.info("ConfigServer at {}:{}", hostStartup, portStartup);
249 VtyshCli.setHostAddr(hostStartup);
250 ClearBgpCli.setHostAddr(hostStartup);
251 bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner);
254 entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
256 candidateRegistration = registerEntityCandidate(entityOwnershipService);
257 entityListenerRegistration = registerEntityListener(entityOwnershipService);
259 LOG.info("BGP Configuration manager initialized");
262 GlobalEventExecutor.INSTANCE.execute(() -> {
263 final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
264 IBgpManager.class, bundleContext);
265 bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
266 if (InetAddresses.isInetAddress(getBgpSdncMipIp())) {
267 InetSocketAddress bgpThriftServerSocketAddr = new InetSocketAddress(getBgpSdncMipIp(),
268 Integer.parseInt(updatePort));
269 bgpThriftService = new BgpThriftService(bgpThriftServerSocketAddr, bgpManager, this);
270 if (isBGPEntityOwner()) {
271 //I am EoS owner of BGP, opening bgp thrift UPDATE-SERVER port.
272 LOG.info("BGP Configuration manager initialized: UPDATE-SERVER started");
273 bgpThriftService.start();
275 LOG.info("UPDATE server started :ip:port={}:{}", getBgpSdncMipIp(), updatePort);
277 LOG.error("Failed to init UPDATE server invalid ip:port={}:{}", getBgpSdncMipIp(), updatePort);
279 LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
283 public String getBgpSdncMipIp() {
284 return getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
287 public long getStaleCleanupTime() {
288 return staleCleanupTime;
291 public void setStaleCleanupTime(long staleCleanupTime) {
292 this.staleCleanupTime = staleCleanupTime;
295 public long getCfgReplayEndTime() {
296 return cfgReplayEndTime;
299 public void setCfgReplayEndTime(long cfgReplayEndTime) {
300 this.cfgReplayEndTime = cfgReplayEndTime;
303 public long getCfgReplayStartTime() {
304 return cfgReplayStartTime;
307 public void setCfgReplayStartTime(long cfgReplayStartTime) {
308 this.cfgReplayStartTime = cfgReplayStartTime;
311 public long getStaleEndTime() {
315 public void setStaleEndTime(long staleEndTime) {
316 this.staleEndTime = staleEndTime;
319 public long getStaleStartTime() {
320 return staleStartTime;
323 public void setStaleStartTime(long staleStartTime) {
324 this.staleStartTime = staleStartTime;
327 private Object createListener(Class<?> cls) {
329 Constructor<?> ctor = cls.getConstructor(BgpConfigurationManager.class);
330 return ctor.newInstance(this);
331 } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
333 LOG.error("Failed to create listener object", e);
338 private void registerCallbacks() {
339 for (Class<?> reactor : REACTORS) {
340 Object obj = createListener(reactor);
342 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
343 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
349 @SuppressWarnings("checkstyle:IllegalCatch")
351 public void close() {
354 if (bgpThriftService != null) {
355 bgpThriftService.stop();
356 bgpThriftService = null;
359 if (isBgpConnected()) {
360 //disconnect the CONFIG SERVER port (which was )opened during I was Owner
361 bgpRouter.disconnect();
364 if (candidateRegistration != null) {
365 candidateRegistration.close();
368 entityListenerRegistration.close();
370 listeners.forEach(l -> {
373 } catch (Exception e) {
374 LOG.warn("Error closing {}", l ,e);
378 LOG.info("{} close", getClass().getSimpleName());
381 private String getProperty(String var, String def) {
382 String property = bundleContext.getProperty(var);
383 return property == null ? def : property;
386 private EntityOwnershipCandidateRegistration registerEntityCandidate(
387 final EntityOwnershipService entityOwnershipService) {
389 return entityOwnershipService.registerCandidate(
390 new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME));
391 } catch (CandidateAlreadyRegisteredException e) {
392 LOG.error("failed to register bgp entity", e);
397 private EntityOwnershipListenerRegistration registerEntityListener(
398 final EntityOwnershipService entityOwnershipService) {
399 return entityOwnershipService.registerListener(BGP_ENTITY_TYPE_FOR_OWNERSHIP, ownershipChange -> {
400 LOG.trace("entity owner change event fired: {}", ownershipChange);
402 if (ownershipChange.getState() == EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED) {
403 LOG.trace("This PL is the Owner");
404 if (bgpThriftService != null) {
405 //opening UPDATE-SERVER port.
406 bgpThriftService.start();
408 LOG.error("I am the owner of BGP entity, but bgpThriftService is not initialized yet");
412 LOG.debug("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
413 ownershipChange.getState().isOwner());
414 if ((bgpThriftService != null) && (bgpThriftService.isBgpThriftServiceStarted())) {
415 //close the bgp Thrift Update-SERVER port opened on non-Entity Owner
416 bgpThriftService.stop();
417 bgpThriftService = null;
419 if (isBgpConnected()) {
420 //disconnect the CONFIG SERVER port (which was )opened during I was Owner
421 bgpRouter.disconnect();
427 public boolean isBGPEntityOwner() {
428 return entityOwnershipUtils.isEntityOwner(new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME), 0, 1);
432 config = getConfig();
436 public class ConfigServerReactor
437 extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
438 implements ClusteredDataTreeChangeListener<ConfigServer> {
439 private static final String YANG_OBJ = "config-server ";
441 public ConfigServerReactor() {
442 super(ConfigServer.class, ConfigServerReactor.class);
446 protected void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
447 LOG.trace("received bgp connect config host {}", val.getHost().getValue());
448 if (!isBGPEntityOwner()) {
454 } catch (InterruptedException e) {
457 LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
458 bgpRouter.configServerUpdated();
459 synchronized (BgpConfigurationManager.this) {
460 boolean res = bgpRouter.connect(val.getHost().getValue(),
461 val.getPort().intValue());
463 LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
466 VtyshCli.setHostAddr(val.getHost().getValue());
467 ClearBgpCli.setHostAddr(val.getHost().getValue());
471 protected ConfigServerReactor getDataTreeChangeListener() {
472 return ConfigServerReactor.this;
476 protected InstanceIdentifier<ConfigServer> getWildCardPath() {
477 return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
481 protected void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
482 LOG.trace("received bgp disconnect");
483 if (!isBGPEntityOwner()) {
487 bgpRouter.configServerUpdated();
489 synchronized (BgpConfigurationManager.this) {
490 bgpRouter.disconnect();
495 protected void update(InstanceIdentifier<ConfigServer> iid,
496 ConfigServer oldval, ConfigServer newval) {
497 LOG.trace("received bgp Connection update");
498 if (!isBGPEntityOwner()) {
501 LOG.error(YANG_OBJ + UPD_WARN);
505 private BgpRouter getClient(String yangObj) {
506 if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
507 LOG.warn("{}: configuration received when BGP is inactive", yangObj);
513 public class AsIdReactor
514 extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
515 implements ClusteredDataTreeChangeListener<AsId> {
517 private static final String YANG_OBJ = "as-id ";
519 public AsIdReactor() {
520 super(AsId.class, AsIdReactor.class);
524 protected void add(InstanceIdentifier<AsId> iid, AsId val) {
525 LOG.error("received bgp add asid {}", val);
526 if (!isBGPEntityOwner()) {
529 LOG.debug("received add router config asNum {}", val.getLocalAs());
530 synchronized (BgpConfigurationManager.this) {
531 BgpRouter br = getClient(YANG_OBJ);
533 LOG.debug("{} Unable to process add for asNum {}; {} {}", YANG_OBJ, val.getLocalAs(),
534 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
539 startBgpCountersTask();
540 startBgpAlarmsTask();
545 protected AsIdReactor getDataTreeChangeListener() {
546 return AsIdReactor.this;
550 protected InstanceIdentifier<AsId> getWildCardPath() {
551 return InstanceIdentifier.create(Bgp.class).child(AsId.class);
555 protected void remove(InstanceIdentifier<AsId> iid, AsId val) {
556 LOG.error("received delete router config asNum {}", val.getLocalAs());
557 if (!isBGPEntityOwner()) {
560 synchronized (BgpConfigurationManager.this) {
561 long asNum = val.getLocalAs();
562 BgpRouter br = getClient(YANG_OBJ);
564 LOG.debug("{} Unable to process remove for asNum {}; {} {}", YANG_OBJ, asNum,
565 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
570 } catch (TException | BgpRouterException e) {
571 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
574 stopBgpCountersTask();
577 Bgp conf = getConfig();
579 LOG.error("Config Null while removing the as-id");
582 LOG.debug("Removing external routes from FIB");
583 deleteExternalFibRoutes();
584 List<Neighbors> nbrs = conf.getNeighbors();
585 if (nbrs != null && nbrs.size() > 0) {
586 LOG.error("Tring to remove the as-id when neighbor config is already present");
587 for (Neighbors nbr : nbrs) {
588 LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
589 delNeighbor(nbr.getAddress().getValue());
596 protected void update(InstanceIdentifier<AsId> iid,
597 AsId oldval, AsId newval) {
598 if (!isBGPEntityOwner()) {
601 LOG.error(YANG_OBJ + UPD_WARN);
605 public class GracefulRestartReactor
606 extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
607 implements ClusteredDataTreeChangeListener<GracefulRestart> {
609 private static final String YANG_OBJ = "graceful-restart ";
611 public GracefulRestartReactor() {
612 super(GracefulRestart.class, GracefulRestartReactor.class);
616 protected void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
617 if (!isBGPEntityOwner()) {
620 synchronized (BgpConfigurationManager.this) {
621 int stalePathTime = val.getStalepathTime().intValue();
622 BgpRouter br = getClient(YANG_OBJ);
624 LOG.error("{} Unable to add stale-path time {}; {} {}", YANG_OBJ, stalePathTime,
625 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
629 br.addGracefulRestart(stalePathTime);
630 } catch (TException | BgpRouterException e) {
631 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
637 protected GracefulRestartReactor getDataTreeChangeListener() {
638 return GracefulRestartReactor.this;
642 protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
643 return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
647 protected void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
648 if (!isBGPEntityOwner()) {
651 LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
652 synchronized (BgpConfigurationManager.this) {
653 BgpRouter br = getClient(YANG_OBJ);
655 LOG.error("{} Unable to delete stale-path time; {} {}", YANG_OBJ,
656 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
660 br.delGracefulRestart();
661 } catch (TException | BgpRouterException e) {
662 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
668 protected void update(InstanceIdentifier<GracefulRestart> iid,
669 GracefulRestart oldval, GracefulRestart newval) {
670 if (!isBGPEntityOwner()) {
673 LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
674 synchronized (BgpConfigurationManager.this) {
675 int stalePathTime = newval.getStalepathTime().intValue();
676 BgpRouter br = getClient(YANG_OBJ);
678 LOG.error("{} Unable to update stale-path time to {}; {} {}", YANG_OBJ, stalePathTime,
679 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
683 br.addGracefulRestart(stalePathTime);
684 } catch (TException | BgpRouterException e) {
685 LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
691 public class LoggingReactor
692 extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
693 implements ClusteredDataTreeChangeListener<Logging> {
695 private static final String YANG_OBJ = "logging ";
697 public LoggingReactor() {
698 super(Logging.class, LoggingReactor.class);
702 protected void add(InstanceIdentifier<Logging> iid, Logging val) {
703 if (!isBGPEntityOwner()) {
706 synchronized (BgpConfigurationManager.this) {
707 BgpRouter br = getClient(YANG_OBJ);
709 LOG.error("{} Unable to add logging for qbgp; {} {}", YANG_OBJ,
710 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
714 br.setLogging(val.getFile(), val.getLevel());
715 } catch (TException | BgpRouterException e) {
716 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
722 protected LoggingReactor getDataTreeChangeListener() {
723 return LoggingReactor.this;
727 protected InstanceIdentifier<Logging> getWildCardPath() {
728 return InstanceIdentifier.create(Bgp.class).child(Logging.class);
732 protected void remove(InstanceIdentifier<Logging> iid, Logging val) {
733 if (!isBGPEntityOwner()) {
736 LOG.debug("received remove Logging config val {}", val.getLevel());
737 synchronized (BgpConfigurationManager.this) {
738 BgpRouter br = getClient(YANG_OBJ);
740 LOG.error("{} Unable to remove logging for qbgp; {} {}", YANG_OBJ,
741 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
745 br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
746 } catch (TException | BgpRouterException e) {
747 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
753 protected void update(InstanceIdentifier<Logging> iid,
754 Logging oldval, Logging newval) {
755 if (!isBGPEntityOwner()) {
758 synchronized (BgpConfigurationManager.this) {
759 BgpRouter br = getClient(YANG_OBJ);
761 LOG.error("{} Unable to update logging for qbgp; {} {}", YANG_OBJ,
762 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
766 br.setLogging(newval.getFile(), newval.getLevel());
767 } catch (TException | BgpRouterException e) {
768 LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
774 public class NeighborsReactor
775 extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
776 implements ClusteredDataTreeChangeListener<Neighbors> {
778 private static final String YANG_OBJ = "neighbors ";
780 public NeighborsReactor() {
781 super(Neighbors.class, NeighborsReactor.class);
785 protected void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
786 if (!isBGPEntityOwner()) {
789 LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
790 synchronized (BgpConfigurationManager.this) {
791 String peerIp = val.getAddress().getValue();
792 long as = val.getRemoteAs();
793 final String md5Secret = extractMd5Secret(val);
794 BgpRouter br = getClient(YANG_OBJ);
796 LOG.debug("{} Unable to process add for peer {} as {}; {} {}", YANG_OBJ, peerIp, as,
797 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
801 //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
802 br.addNeighbor(peerIp, as, md5Secret);
804 } catch (TException | BgpRouterException e) {
805 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
811 protected NeighborsReactor getDataTreeChangeListener() {
812 return NeighborsReactor.this;
816 protected InstanceIdentifier<Neighbors> getWildCardPath() {
817 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
821 protected void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
822 if (!isBGPEntityOwner()) {
825 LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
826 synchronized (BgpConfigurationManager.this) {
827 String peerIp = val.getAddress().getValue();
828 BgpRouter br = getClient(YANG_OBJ);
830 LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
831 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
835 //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
836 br.delNeighbor(peerIp);
837 } catch (TException | BgpRouterException e) {
838 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
841 final BgpAlarms bgpAlarms = getBgpAlarms();
842 if (bgpAlarms != null) {
843 bgpAlarms.clearBgpNbrDownAlarm(peerIp);
849 protected void update(InstanceIdentifier<Neighbors> iid,
850 Neighbors oldval, Neighbors newval) {
851 if (!isBGPEntityOwner()) {
854 //purposefully nothing to do.
858 public class EbgpMultihopReactor
859 extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
860 implements ClusteredDataTreeChangeListener<EbgpMultihop> {
862 private static final String YANG_OBJ = "ebgp-multihop ";
864 public EbgpMultihopReactor() {
865 super(EbgpMultihop.class, EbgpMultihopReactor.class);
869 protected void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
870 if (!isBGPEntityOwner()) {
873 LOG.debug("received add 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 add for peer {}; {} {}", YANG_OBJ, peerIp,
879 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
883 br.addEbgpMultihop(peerIp, val.getNhops().intValue());
884 } catch (TException | BgpRouterException e) {
885 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
891 protected EbgpMultihopReactor getDataTreeChangeListener() {
892 return EbgpMultihopReactor.this;
896 protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
897 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
901 protected void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
902 if (!isBGPEntityOwner()) {
905 LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
906 synchronized (BgpConfigurationManager.this) {
907 String peerIp = val.getPeerIp().getValue();
908 BgpRouter br = getClient(YANG_OBJ);
910 LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
911 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
915 br.delEbgpMultihop(peerIp);
916 } catch (TException | BgpRouterException e) {
917 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
923 protected void update(InstanceIdentifier<EbgpMultihop> iid,
924 EbgpMultihop oldval, EbgpMultihop newval) {
925 if (!isBGPEntityOwner()) {
928 LOG.error(YANG_OBJ + UPD_WARN);
932 public class UpdateSourceReactor
933 extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
934 implements ClusteredDataTreeChangeListener<UpdateSource> {
936 private static final String YANG_OBJ = "update-source ";
938 public UpdateSourceReactor() {
939 super(UpdateSource.class, UpdateSourceReactor.class);
943 protected void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
944 if (!isBGPEntityOwner()) {
947 LOG.debug("received add 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 add for peer {}; {} {}", YANG_OBJ, peerIp,
953 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
957 br.addUpdateSource(peerIp, val.getSourceIp().getValue());
958 } catch (TException | BgpRouterException e) {
959 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
965 protected UpdateSourceReactor getDataTreeChangeListener() {
966 return UpdateSourceReactor.this;
970 protected InstanceIdentifier<UpdateSource> getWildCardPath() {
971 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
975 protected void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
976 if (!isBGPEntityOwner()) {
979 LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
980 synchronized (BgpConfigurationManager.this) {
981 String peerIp = val.getPeerIp().getValue();
982 BgpRouter br = getClient(YANG_OBJ);
984 LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
985 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
989 br.delUpdateSource(peerIp);
990 } catch (TException | BgpRouterException e) {
991 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
997 protected void update(InstanceIdentifier<UpdateSource> iid,
998 UpdateSource oldval, UpdateSource newval) {
999 if (!isBGPEntityOwner()) {
1002 LOG.error(YANG_OBJ + UPD_WARN);
1006 public class AddressFamiliesReactor
1007 extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
1008 implements ClusteredDataTreeChangeListener<AddressFamilies> {
1010 private static final String YANG_OBJ = "address-families ";
1012 public AddressFamiliesReactor() {
1013 super(AddressFamilies.class, AddressFamiliesReactor.class);
1017 protected void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1018 if (!isBGPEntityOwner()) {
1021 LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
1022 synchronized (BgpConfigurationManager.this) {
1023 String peerIp = val.getPeerIp().getValue();
1024 BgpRouter br = getClient(YANG_OBJ);
1026 LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
1027 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1030 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1031 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1033 br.addAddressFamily(peerIp, afi, safi);
1034 } catch (TException | BgpRouterException e) {
1035 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1041 protected AddressFamiliesReactor getDataTreeChangeListener() {
1042 return AddressFamiliesReactor.this;
1046 protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
1047 return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
1051 protected void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1052 if (!isBGPEntityOwner()) {
1055 LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
1056 synchronized (BgpConfigurationManager.this) {
1057 String peerIp = val.getPeerIp().getValue();
1058 BgpRouter br = getClient(YANG_OBJ);
1060 LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
1061 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1064 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1065 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1067 br.delAddressFamily(peerIp, afi, safi);
1068 } catch (TException | BgpRouterException e) {
1069 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1075 protected void update(InstanceIdentifier<AddressFamilies> iid,
1076 AddressFamilies oldval, AddressFamilies newval) {
1077 if (!isBGPEntityOwner()) {
1080 LOG.error(YANG_OBJ + UPD_WARN);
1084 public class NetworksReactor
1085 extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1086 implements ClusteredDataTreeChangeListener<Networks> {
1088 private static final String YANG_OBJ = "networks ";
1090 public NetworksReactor() {
1091 super(Networks.class, NetworksReactor.class);
1095 public NetworksReactor getDataTreeChangeListener() {
1096 return NetworksReactor.this;
1100 protected void add(InstanceIdentifier<Networks> iid, Networks val) {
1101 if (!isBGPEntityOwner()) {
1104 LOG.debug("received add Networks config val {}", val.getPrefixLen());
1105 synchronized (BgpConfigurationManager.this) {
1106 String rd = val.getRd();
1107 String pfxlen = val.getPrefixLen();
1108 String nh = val.getNexthop().getValue();
1109 BgpRouter br = getClient(YANG_OBJ);
1111 LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {} {}", YANG_OBJ, rd, pfxlen,
1112 nh, BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1115 Long label = val.getLabel();
1116 int lbl = label == null ? qbgpConstants.LBL_NO_LABEL
1118 int l3vni = val.getL3vni() == null ? qbgpConstants.LBL_NO_LABEL
1119 : val.getL3vni().intValue();
1120 int l2vni = val.getL2vni() == null ? qbgpConstants.LBL_NO_LABEL
1121 : val.getL2vni().intValue();
1123 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1124 int ethernetTag = val.getEthtag().intValue();
1125 String esi = val.getEsi();
1126 String macaddress = val.getMacaddress();
1127 EncapType encapType = val.getEncapType();
1128 String routerMac = val.getRoutermac();
1131 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni, BgpUtil.convertToThriftProtocolType(protocolType),
1132 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1133 } catch (TException | BgpRouterException e) {
1134 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1140 protected InstanceIdentifier<Networks> getWildCardPath() {
1141 return InstanceIdentifier.create(Bgp.class).child(Networks.class);
1145 protected void remove(InstanceIdentifier<Networks> iid, Networks val) {
1146 if (!isBGPEntityOwner()) {
1149 LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1150 synchronized (BgpConfigurationManager.this) {
1151 String rd = val.getRd();
1152 String pfxlen = val.getPrefixLen();
1153 BgpRouter br = getClient(YANG_OBJ);
1155 LOG.debug("{} Unable to process remove for rd {} prefix {}; {} {}", YANG_OBJ, rd, pfxlen,
1156 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1159 Long label = val.getLabel();
1160 int lbl = label == null ? 0 : label.intValue();
1161 if (rd == null && lbl > 0) {
1162 //LU prefix is being deleted.
1163 rd = Integer.toString(lbl);
1166 br.delPrefix(rd, pfxlen);
1167 } catch (TException | BgpRouterException e) {
1168 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1173 /**get the value AFI from a prefix as "x.x.x.x/x".
1175 * @param pfxlen the prefix to get an afi
1176 * @return the afi value as you are need
1178 public int testValueAFI(String pfxlen) {
1179 int afiNew = af_afi.AFI_IP.getValue();
1181 String ipOnly = pfxlen.substring(0, pfxlen.lastIndexOf("/"));
1182 java.net.Inet6Address.getByName(ipOnly);
1183 afiNew = af_afi.AFI_IPV6.getValue();
1184 } catch (java.net.UnknownHostException e) {
1185 //ce n'est pas de l'ipv6
1192 protected void update(final InstanceIdentifier<Networks> iid,
1193 final Networks oldval, final Networks newval) {
1194 if (!isBGPEntityOwner()) {
1197 if (oldval.equals(newval)) {
1198 //Update: OLD and New values are same, no need to trigger remove/add.
1199 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1200 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1203 LOG.debug("update networks old val RD: {}, Prefix: {}, Label: {}, NH: {} "
1204 + "new val RD: {}, Prefix: {}, Label: {}, NH: {}",
1205 oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop(),
1206 newval.getRd(), newval.getPrefixLen(), newval.getLabel(), newval.getNexthop());
1207 remove(iid, oldval);
1212 static Timer timer = new Timer();
1214 public class VrfsReactor
1215 extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1216 implements ClusteredDataTreeChangeListener<Vrfs> {
1218 private static final String YANG_OBJ = "vrfs ";
1220 public VrfsReactor() {
1221 super(Vrfs.class, VrfsReactor.class);
1225 protected void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
1226 if (!isBGPEntityOwner()) {
1229 LOG.debug("received add Vrfs config value {}", vrfs.getRd());
1230 synchronized (BgpConfigurationManager.this) {
1231 String rd = vrfs.getRd();
1232 BgpRouter br = getClient(YANG_OBJ);
1234 LOG.debug("{} Unable to process add for rd {}; {} {}", YANG_OBJ, rd,
1235 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1239 List<AddressFamiliesVrf> vrfAddrFamilyList = vrfs.getAddressFamiliesVrf();
1240 for (AddressFamiliesVrf vrfAddrFamily : vrfAddrFamilyList) {
1241 /*add to br the new vrfs arguments*/
1242 br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(), vrfs.getExportRts()
1245 /*add to br the vrfs contained in mapNewAdFamily*/
1246 List<AddressFamiliesVrf> vrfAddrFamilyListFromMap = mapNewAdFamily.get(rd);
1247 if (vrfAddrFamilyListFromMap == null) {
1251 for (AddressFamiliesVrf adf : vrfAddrFamilyListFromMap) {
1252 if (vrfAddrFamilyList.contains(adf)) {
1253 mapNewAdFamily.remove(rd);
1254 } else if (adf != null) {
1256 br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(), vrfs.getExportRts()
1258 // remove AddressFamiliesVrf which was already added to BGP
1259 vrfAddrFamilyListFromMap.remove(adf);
1260 if (vrfAddrFamilyListFromMap.isEmpty()) {
1261 // remove Vrf entry from temp mapNewAdFamily if all its AddressFamiliesVrf was
1263 mapNewAdFamily.remove(rd);
1267 } catch (TException | BgpRouterException e) {
1268 LOG.error("{} get {}, Add received exception", YANG_OBJ, ADD_WARN, e);
1274 protected VrfsReactor getDataTreeChangeListener() {
1275 return VrfsReactor.this;
1279 protected InstanceIdentifier<Vrfs> getWildCardPath() {
1280 return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
1284 protected void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1285 if (!isBGPEntityOwner()) {
1288 LOG.debug("received remove Vrfs config val {}", val.getRd());
1289 synchronized (BgpConfigurationManager.this) {
1290 String rd = val.getRd();
1291 BgpRouter br = getClient(YANG_OBJ);
1293 LOG.debug("{} Unable to process remove for rd {}; {} {}", YANG_OBJ, rd,
1294 BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1298 List<AddressFamiliesVrf> adf = mapNewAdFamily.get(rd);
1299 adf = adf != null ? adf : new ArrayList<>();
1300 for (AddressFamiliesVrf s : val.getAddressFamiliesVrf()) {
1301 br.delVrf(rd, s.getAfi(), s.getSafi());
1302 adf.remove(s);// remove in the map the vrf in waiting for advertise quagga
1304 if (adf.isEmpty()) {
1305 mapNewAdFamily.remove(rd);
1307 } catch (TException | BgpRouterException e) {
1308 LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1314 protected void update(InstanceIdentifier<Vrfs> iid,
1315 Vrfs oldval, Vrfs newval) {
1316 if (oldval != null && newval != null) {
1317 LOG.debug("received update Vrfs config val {}, VRFS: Update getting triggered for VRFS rd {}",
1318 newval.getRd(), oldval.getRd());
1320 LOG.debug("received update Vrfs config val {}, from old vrf {}",
1323 if (!isBGPEntityOwner()) {
1327 List<AddressFamiliesVrf> adFamilyVrfToDel = new ArrayList<>();
1328 List<AddressFamiliesVrf> adFamilyVrfToAdd = new ArrayList<>();
1329 List<AddressFamiliesVrf> oldlistAdFamilies = new ArrayList<>();
1330 List<AddressFamiliesVrf> newlistAdFamilies = new ArrayList<>();
1331 if (oldval != null) {
1332 oldlistAdFamilies = oldval.getAddressFamiliesVrf() == null
1333 ? new ArrayList<>() : oldval.getAddressFamiliesVrf();
1335 if (newval != null) {
1336 newlistAdFamilies = newval.getAddressFamiliesVrf() == null
1337 ? new ArrayList<>() : newval.getAddressFamiliesVrf();
1339 /*find old AddressFamily to remove from new configuration*/
1340 for (AddressFamiliesVrf adVrf : oldlistAdFamilies) {
1341 if (!newlistAdFamilies.contains(adVrf)) {
1342 adFamilyVrfToDel.add(adVrf);
1345 /*find new AddressFamily to add to unexisting configuration*/
1346 for (AddressFamiliesVrf adVrf : newlistAdFamilies) {
1347 if (!oldlistAdFamilies.contains(adVrf)) {
1348 adFamilyVrfToAdd.add(adVrf);
1351 String rd = newval != null ? newval.getRd() : null;
1353 BgpRouter br = getClient(YANG_OBJ);
1355 LOG.debug("{} Unable to process add for rd {}; {} {}", YANG_OBJ, rd,
1356 BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1360 for (AddressFamiliesVrf adfvrf : adFamilyVrfToAdd) {
1362 LOG.debug("call addVRf rd {} afi {} safi {}", rd, adfvrf.getAfi(), adfvrf.getSafi());
1363 br.addVrf(BgpUtil.getLayerType(adfvrf), rd, newval.getImportRts(),
1364 newval.getExportRts());
1365 } catch (TException | BgpRouterException e) {
1366 LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1370 for (AddressFamiliesVrf adfToDel : adFamilyVrfToDel) {
1372 LOG.debug("call delVRf rd {} afi {} safi {}", rd, adfToDel.getAfi(), adfToDel.getSafi());
1373 br.delVrf(rd, adfToDel.getAfi(), adfToDel.getSafi());
1374 } catch (TException | BgpRouterException e) {
1375 LOG.error("{} delVrf received exception; {}", YANG_OBJ, ADD_WARN, e);
1382 protected void activateMIP() {
1384 LOG.trace("BgpReactor: Executing MIP Activate command");
1385 Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
1386 Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
1387 LOG.trace("bgpMIP Activated");
1389 } catch (IOException io) {
1390 LOG.error("IO Exception got while activating mip: {}", io.getMessage());
1394 public class BgpReactor
1395 extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1396 implements ClusteredDataTreeChangeListener<Bgp> {
1398 private static final String YANG_OBJ = "Bgp ";
1400 public BgpReactor() {
1401 super(Bgp.class, BgpReactor.class);
1406 protected void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1407 LOG.debug("received add Bgp config");
1411 } catch (InterruptedException e) {
1414 synchronized (BgpConfigurationManager.this) {
1416 if (!isBGPEntityOwner()) {
1424 protected BgpReactor getDataTreeChangeListener() {
1425 return BgpReactor.this;
1429 protected InstanceIdentifier<Bgp> getWildCardPath() {
1430 return InstanceIdentifier.create(Bgp.class);
1434 protected void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1435 if (!isBGPEntityOwner()) {
1438 LOG.debug("received remove Bgp config");
1444 protected void update(InstanceIdentifier<Bgp> iid,
1445 Bgp oldval, Bgp newval) {
1446 if (!isBGPEntityOwner()) {
1454 @SuppressWarnings("deprecation")
1455 public class MultipathReactor
1456 extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1457 implements ClusteredDataTreeChangeListener<Multipath> {
1459 private static final String YANG_OBJ = "multipath ";
1461 public MultipathReactor() {
1462 super(Multipath.class, MultipathReactor.class);
1467 protected MultipathReactor getDataTreeChangeListener() {
1468 return MultipathReactor.this;
1472 protected InstanceIdentifier<Multipath> getWildCardPath() {
1473 return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
1477 protected void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1478 executor.execute(new MultipathStatusChange(val));
1482 protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1483 executor.execute(new MultipathStatusChange(newval));
1487 protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1488 executor.execute(new MultipathStatusChange(dataObjectModification));
1491 class MultipathStatusChange implements Runnable {
1493 Multipath multipath;
1495 MultipathStatusChange(Multipath multipath) {
1496 this.multipath = multipath;
1501 if (isBGPEntityOwner()) {
1502 synchronized (BgpConfigurationManager.this) {
1504 BgpRouter br = getClient(YANG_OBJ);
1507 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1508 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1511 if (multipath.isMultipathEnabled()) {
1512 br.enableMultipath(afi, safi);
1514 br.disableMultipath(afi, safi);
1516 } catch (TException | BgpRouterException e) {
1517 LOG.error("{} received exception", YANG_OBJ, e);
1527 public void close() {
1532 @SuppressWarnings("deprecation")
1533 public class VrfMaxpathReactor
1534 extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1535 implements ClusteredDataTreeChangeListener<VrfMaxpath> {
1537 private static final String YANG_OBJ = "vrfMaxpath ";
1539 public VrfMaxpathReactor() {
1540 super(VrfMaxpath.class, VrfMaxpathReactor.class);
1545 protected VrfMaxpathReactor getDataTreeChangeListener() {
1546 return VrfMaxpathReactor.this;
1550 protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1551 return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
1554 class VrfMaxPathConfigurator implements Runnable {
1556 VrfMaxpath vrfMaxpathVal;
1558 VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1559 this.vrfMaxpathVal = vrfMaxPathVal;
1564 if (isBGPEntityOwner()) {
1565 synchronized (BgpConfigurationManager.this) {
1566 BgpRouter br = getClient(YANG_OBJ);
1569 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
1570 LOG.debug("Maxpath for vrf {} is {}", vrfMaxpathVal.getRd(),
1571 vrfMaxpathVal.getMaxpaths());
1572 } catch (TException | BgpRouterException e) {
1573 LOG.error("{} received exception", YANG_OBJ, e);
1582 protected void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1583 executor.execute(new VrfMaxPathConfigurator(vrfMaxPathVal));
1587 protected void update(InstanceIdentifier<VrfMaxpath> iid,
1588 VrfMaxpath oldval, VrfMaxpath newval) {
1589 if (!Objects.equals(oldval.getMaxpaths(), newval.getMaxpaths())) {
1590 executor.execute(new VrfMaxPathConfigurator(newval));
1595 protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1596 executor.execute(new VrfMaxPathConfigurator(vrfMaxpathVal));
1600 public void close() {
1605 public boolean isIpAvailable(String odlip) {
1608 if (odlip != null) {
1609 if ("127.0.0.1".equals(odlip)) {
1612 Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1613 while (networkInterfaceEnumeration.hasMoreElements()) {
1614 NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
1615 Enumeration<InetAddress> inetAddressEnumeration = networkInterface.getInetAddresses();
1616 while (inetAddressEnumeration.hasMoreElements()) {
1617 InetAddress inetAddress = inetAddressEnumeration.nextElement();
1618 if (odlip.equals(inetAddress.getHostAddress())) {
1624 } catch (SocketException e) {
1630 public long getStalePathtime(int defValue, AsId asId) {
1633 spt = getConfig().getGracefulRestart().getStalepathTime();
1634 } catch (NullPointerException e) {
1636 spt = asId.getStalepathTime();
1637 LOG.trace("BGP config/Stale-path time is not set using graceful");
1638 } catch (NullPointerException ignore) {
1639 LOG.trace("BGP AS id is not set using graceful");
1644 LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1650 public static boolean isValidConfigBgpHostPort(String bgpHost, int bgpPort) {
1651 if (!bgpHost.equals(DEF_CHOST) && bgpPort != Integer.parseInt(DEF_CPORT)) {
1658 public synchronized void bgpRestarted() {
1660 * If there a thread which in the process of stale cleanup, cancel it
1661 * and start a new thread (to avoid processing same again).
1663 if (previousReplayJobInProgress()) {
1664 cancelPreviousReplayJob();
1666 Runnable task = () -> {
1668 LOG.info("running bgp replay task ");
1669 if (get() == null) {
1670 String host = getConfigHost();
1671 int port = getConfigPort();
1672 LOG.info("connecting to bgp host {} ", host);
1673 bgpRouter.connect(host, port);
1674 LOG.info("no config to push in bgp replay task ");
1677 setStaleStartTime(System.currentTimeMillis());
1678 LOG.info("started creating stale fibDSWriter map ");
1679 createStaleFibMap();
1680 setStaleEndTime(System.currentTimeMillis());
1681 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1682 LOG.info("started bgp config replay ");
1683 setCfgReplayStartTime(System.currentTimeMillis());
1684 boolean replaySucceded = replay();
1685 setCfgReplayEndTime(System.currentTimeMillis());
1686 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1687 if (replaySucceded) {
1688 LOG.info("starting the stale cleanup timer");
1689 long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1690 setStaleCleanupTime(routeSyncTime);
1691 routeCleanupFuture = executor.schedule(new RouteCleanup(), routeSyncTime, TimeUnit.SECONDS);
1693 staledFibEntriesMap.clear();
1695 } catch (InterruptedException | TimeoutException | ExecutionException eCancel) {
1696 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1699 lastReplayJobFt = executor.submit(task);
1702 private boolean previousReplayJobInProgress() {
1703 return lastReplayJobFt != null && !lastReplayJobFt.isDone();
1706 private void cancelPreviousReplayJob() {
1708 LOG.error("cancelling already running bgp replay task");
1709 if (lastReplayJobFt != null) {
1710 lastReplayJobFt.cancel(true);
1711 lastReplayJobFt = null;
1712 staledFibEntriesMap.clear();
1714 if (routeCleanupFuture != null) {
1715 routeCleanupFuture.cancel(true);
1716 routeCleanupFuture = null;
1717 staledFibEntriesMap.clear();
1720 } catch (InterruptedException e) {
1721 LOG.error("Failed to cancel previous replay job ", e);
1725 private void doRouteSync() {
1726 LOG.error("Starting BGP route sync");
1728 bgpRouter.initRibSync(bgpSyncHandle);
1729 } catch (BgpRouterException e) {
1730 LOG.error("Route sync aborted, exception when initializing", e);
1733 while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
1734 for (af_afi afi : af_afi.values()) {
1735 Routes routes = null;
1737 routes = bgpRouter.doRibSync(bgpSyncHandle, afi);
1738 } catch (TException | BgpRouterException e) {
1739 LOG.error("Route sync aborted, exception when syncing", e);
1742 Iterator<Update> updates = routes.getUpdatesIterator();
1743 while (updates.hasNext()) {
1744 Update update = updates.next();
1745 String rd = update.getRd();
1746 String nexthop = update.getNexthop();
1748 // TODO: decide correct label here
1749 int label = update.getL3label();
1750 int l2label = update.getL2label();
1752 String prefix = update.getPrefix();
1753 int plen = update.getPrefixlen();
1756 // TODO: protocol type will not be available in "update"
1757 // use "rd" to query vrf table and obtain the protocol_type.
1758 // Currently using PROTOCOL_EVPN as default.
1760 protocol_type.PROTOCOL_EVPN,
1765 update.getMacaddress(),
1768 update.getRoutermac(),
1774 LOG.error("Ending BGP route-sync");
1775 bgpRouter.endRibSync(bgpSyncHandle);
1776 } catch (BgpRouterException e) {
1781 public void addTepToElanDS(String rd, String tepIp, String mac, Long l2vni) {
1782 boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
1784 LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
1785 bgpUtil.addTepToElanInstance(rd, tepIp);
1787 LOG.debug("Skipping the Elan update for RT2 from tep {} rd {}", tepIp, rd);
1791 public void deleteTepfromElanDS(String rd, String tepIp, String mac) {
1792 boolean needUpdate = deleteFromRt2TepMap(rd, tepIp, mac);
1794 LOG.info("Deleting tepIp {} with RD {} to ELan DS", tepIp, rd);
1795 bgpUtil.deleteTepFromElanInstance(rd, tepIp);
1797 LOG.debug("Skipping the Elan update for RT2 withdraw from tep {} rd {}", tepIp, rd);
1801 /* onUpdatePushRoute
1802 * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1803 * - Entry compare shall include NextHop, Label.
1804 * - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1805 * - If entry not found, add to FIB Config DS.
1806 * - If entry found, but either Label/NextHop doesn't match.
1807 * - Update FIB Config DS with modified values.
1808 * - delete from Stale Map.
1811 public void onUpdatePushRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1812 String macaddress, int label, int l2label, String routermac, af_afi afi) {
1813 boolean addroute = false;
1814 boolean macupdate = false;
1816 VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
1817 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1818 encapType = VrfEntry.EncapType.Vxlan;
1819 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1820 if (vpnInstanceOpDataEntry != null) {
1821 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1822 LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
1823 vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
1824 addTepToElanDS(rd, nextHop, macaddress, (long)l2label);
1827 l3vni = vpnInstanceOpDataEntry.getL3vni();
1830 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1835 if (!staledFibEntriesMap.isEmpty()) {
1836 // restart Scenario, as MAP is not empty.
1837 Map<String, Long> map = staledFibEntriesMap.get(rd);
1839 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
1840 Long labelInStaleMap = map.get(prefixNextHop);
1841 if (null == labelInStaleMap) {
1842 // New Entry, which happened to be added during restart.
1845 map.remove(prefixNextHop);
1846 if (isRouteModified(label, labelInStaleMap)) {
1847 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1848 // Existing entry, where in Label got modified during restart
1853 LOG.debug("rd {} map is null while processing prefix {} ", rd, prefix);
1857 LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
1861 LOG.info("ADD: Adding Mac Fib entry rd {} mac{} nexthop {} l2vni {}", rd, macaddress, nextHop, l2label);
1862 fibDSWriter.addMacEntryToDS(rd, macaddress, prefix, Collections.singletonList(nextHop),
1863 encapType, l2label, routermac, RouteOrigin.BGP);
1864 LOG.info("ADD: Added Mac Fib entry rd {} prefix {} nexthop {} label {}", rd, macaddress, nextHop, l2label);
1865 } else if (addroute) {
1866 LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
1867 rd, prefix, nextHop, label, afi);
1868 // TODO: modify addFibEntryToDS signature
1869 List<String> nextHopList = Collections.singletonList(nextHop);
1870 fibDSWriter.addFibEntryToDS(rd, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
1871 routermac, RouteOrigin.BGP);
1872 LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
1873 String vpnName = bgpUtil.getVpnNameFromRd(rd);
1874 if (vpnName != null) {
1875 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, nextHopList, label, RouteOrigin.BGP,
1876 NwConstants.ADD_FLOW);
1881 public void onUpdateWithdrawRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
1882 String macaddress) {
1884 boolean macupdate = false;
1885 if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
1886 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
1887 if (vpnInstanceOpDataEntry != null) {
1888 vni = vpnInstanceOpDataEntry.getL3vni();
1889 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
1890 LOG.debug("Got RT2 withdraw for RD {} {} from tep {} with mac {} remote RD {}",
1891 vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
1892 deleteTepfromElanDS(rd, nextHop, macaddress);
1893 LOG.debug("For rd {}. skipping fib update", rd);
1897 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
1902 LOG.info("Removing Mac Fib entry rd {} mac{} nexthop {} ", rd, macaddress, nextHop);
1903 fibDSWriter.removeMacEntryFromDS(rd, macaddress);
1904 LOG.info("Removed Mac Fib entry rd {} prefix {} nexthop {} ", rd, macaddress, nextHop);
1906 LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
1907 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nextHop);
1908 LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
1912 //TODO: below function is for testing purpose with cli
1913 public void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
1914 LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
1915 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
1916 String vpnName = bgpUtil.getVpnNameFromRd(rd);
1917 if (vpnName != null) {
1918 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
1919 RouteOrigin.BGP, NwConstants.DEL_FLOW);
1923 private static boolean isRouteModified(int label, Long labelInStaleMap) {
1924 return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
1927 static class ReplayNbr {
1929 boolean shouldRetry = false;
1931 public Neighbors getNbr() {
1935 public boolean isShouldRetry() {
1939 public void setShouldRetry(boolean retryNbr) {
1940 this.shouldRetry = retryNbr;
1943 ReplayNbr(Neighbors nbr, boolean shouldRetry) {
1945 this.shouldRetry = shouldRetry;
1949 private static boolean replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
1950 if (neighbors == null || neighbors.isEmpty()) {
1951 LOG.error("Replaying nbr configuration, received NULL list ");
1955 List<ReplayNbr> replayNbrList = new ArrayList<>();
1956 for (Neighbors nbr : neighbors) {
1958 replayNbrList.add(new ReplayNbr(nbr, true));
1961 final int numberOfNbrRetries = 3;
1962 RetryOnException nbrRetry = new RetryOnException(numberOfNbrRetries);
1964 for (ReplayNbr replayNbr : replayNbrList) {
1965 if (!replayNbr.isShouldRetry()) {
1968 boolean replayDone = false;
1969 LOG.debug("Replaying addNbr {}", replayNbr.getNbr().getAddress().getValue());
1972 final String md5password = extractMd5Secret(replayNbr.getNbr());
1973 br.addNeighbor(replayNbr.getNbr().getAddress().getValue(),
1974 replayNbr.getNbr().getRemoteAs().longValue(), md5password);
1975 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1977 LOG.debug("Replaying updatesource along with nbr: {} US-ip: {} to peer {}",
1978 replayNbr.getNbr().getAddress().getValue(),
1979 us.getSourceIp().getValue(),
1980 us.getPeerIp().getValue());
1981 br.addUpdateSource(us.getPeerIp().getValue(),
1982 us.getSourceIp().getValue());
1985 } catch (TException | BgpRouterException eNbr) {
1986 LOG.debug("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), eNbr);
1988 boolean replaySuccess = true;
1989 replaySuccess = replaySuccess && replayDone;
1990 LOG.debug("Replay addNbr {} successful", replayNbr.getNbr().getAddress().getValue());
1992 //Update Source handling
1993 UpdateSource us = replayNbr.getNbr().getUpdateSource();
1994 if (replayDone == false && us != null) {
1995 LOG.debug("Replaying updatesource {} to peer {}", us.getSourceIp().getValue(),
1996 us.getPeerIp().getValue());
1999 br.addUpdateSource(us.getPeerIp().getValue(),
2000 us.getSourceIp().getValue());
2002 } catch (TException | BgpRouterException eUs) {
2003 LOG.debug("Replaying UpdateSource for Nbr {}, exception:",
2004 replayNbr.getNbr().getAddress().getValue(), eUs);
2006 LOG.debug("Replay updatesource {} successful", us.getSourceIp().getValue());
2007 replaySuccess = replaySuccess && replayDone;
2010 EbgpMultihop en = replayNbr.getNbr().getEbgpMultihop();
2014 br.addEbgpMultihop(en.getPeerIp().getValue(),
2015 en.getNhops().intValue());
2017 } catch (TException | BgpRouterException eEbgpMhop) {
2018 LOG.debug("Replaying EbgpMultihop for Nbr {}, exception: ",
2019 replayNbr.getNbr().getAddress().getValue(), eEbgpMhop);
2021 replaySuccess = replaySuccess && replayDone;
2025 List<AddressFamilies> afs = replayNbr.getNbr().getAddressFamilies();
2027 for (AddressFamilies af : afs) {
2028 af_afi afi = af_afi.findByValue(af.getAfi().intValue());
2029 af_safi safi = af_safi.findByValue(af.getSafi().intValue());
2032 br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
2034 } catch (TException | BgpRouterException eAFs) {
2035 LOG.debug("Replaying AddressFamily for Nbr {}, exception:",
2036 replayNbr.getNbr().getAddress().getValue(), eAFs);
2038 replaySuccess = replaySuccess && replayDone;
2041 //replay is success --> no need to replay this nbr in next iteration.
2042 replayNbr.setShouldRetry(replaySuccess ? false : true);
2044 } while (nbrRetry.decrementAndRetry());
2045 boolean replaySuccess = true;
2046 for (ReplayNbr replayNbr : replayNbrList) {
2047 replaySuccess = replaySuccess && !replayNbr.isShouldRetry();
2049 return replaySuccess;
2052 public String getConfigHost() {
2053 if (config == null) {
2056 ConfigServer ts = config.getConfigServer();
2057 return ts == null ? hostStartup : ts.getHost().getValue();
2060 public int getConfigPort() {
2061 if (config == null) {
2062 return Integer.parseInt(portStartup);
2064 ConfigServer ts = config.getConfigServer();
2065 return ts == null ? Integer.parseInt(portStartup) :
2066 ts.getPort().intValue();
2069 public Bgp getConfig() {
2070 AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COUNT);
2071 while (0 != bgpDSretryCount.decrementAndGet()) {
2073 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
2074 InstanceIdentifier.create(Bgp.class)).orNull();
2075 } catch (ReadFailedException e) {
2076 //Config DS may not be up, so sleep for 1 second and retry
2077 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
2079 Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
2080 } catch (InterruptedException timerEx) {
2081 LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
2082 + "config DS availability", timerEx);
2086 LOG.error("failed to get bgp config");
2090 @SuppressWarnings("checkstyle:IllegalCatch")
2091 public synchronized boolean replay() throws InterruptedException, TimeoutException, ExecutionException {
2092 boolean replaySucceded = true;
2093 String host = getConfigHost();
2094 int port = getConfigPort();
2095 LOG.error("connecting to bgp host {} ", host);
2096 boolean res = bgpRouter.connect(host, port);
2098 LOG.error("Cannot connect to BGP config server at {}:{}{}", host, port,
2099 config != null ? "; Configuration Replay aborted" : "");
2100 return replaySucceded;
2102 config = getConfig();
2103 if (config == null) {
2104 LOG.error("bgp config is empty nothing to push to bgp");
2105 return replaySucceded;
2107 BgpRouter br = bgpRouter;
2108 AsId asId = config.getAsId();
2110 LOG.error("bgp as-id is null");
2111 return replaySucceded;
2113 long asNum = asId.getLocalAs();
2114 IpAddress routerId = asId.getRouterId();
2115 String rid = routerId == null ? "" : new String(routerId.getValue());
2116 int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, config.getAsId());
2117 boolean announceFbit = true;
2118 boolean replayDone = false;
2119 final int numberOfStartBgpRetries = 3;
2120 RetryOnException startBgpRetry = new RetryOnException(numberOfStartBgpRetries);
2123 LOG.debug("Replaying BGPConfig ");
2124 br.startBgp(asNum, rid, stalepathTime, announceFbit);
2125 LOG.debug("Replay BGPConfig successful");
2128 } catch (BgpRouterException bre) {
2129 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
2130 LOG.debug("Starting the routesync for exception", bre);
2131 startBgpRetry.errorOccured();
2132 if (!startBgpRetry.shouldRetry()) {
2133 LOG.debug("starting route sync for BgpRouter exception");
2137 LOG.error("Replay: startBgp() received exception error {} : ",
2138 bre.getErrorCode(), bre);
2139 startBgpRetry.errorOccured();
2141 } catch (TApplicationException tae) {
2142 if (tae.getType() == BgpRouterException.BGP_ERR_ACTIVE) {
2143 LOG.debug("Starting the routesync for exception", tae);
2144 startBgpRetry.errorOccured();
2145 if (!startBgpRetry.shouldRetry()) {
2146 LOG.debug("starting route sync for Thrift BGP_ERR_ACTIVE exception");
2149 } else if (tae.getType() == BgpRouterException.BGP_ERR_COMMON_FAILURE) {
2150 LOG.debug("Starting the routesync for AS-ID started exception", tae);
2151 startBgpRetry.errorOccured();
2152 if (!startBgpRetry.shouldRetry()) {
2153 LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception");
2157 LOG.error("Replay: startBgp() received exception type {}: ",
2158 tae.getType(), tae);
2159 startBgpRetry.errorOccured();
2161 } catch (Exception e) {
2162 //not unusual. We may have restarted & BGP is already on
2163 LOG.error("Replay:startBgp() received exception: ", e);
2164 startBgpRetry.errorOccured();
2166 } while (startBgpRetry.shouldRetry());
2168 replaySucceded = replayDone;
2170 startBgpCountersTask();
2171 startBgpAlarmsTask();
2174 * commenting this due to a bug with QBGP. Will uncomment once QBGP fix is done.
2175 * This wont have any functional impacts
2178 // br.delayEOR(delayEorSeconds);
2179 //} catch (TException | BgpRouterException e) {
2180 // LOG.error("Replay: delayEOR() number of seconds to wait for EOR from ODL:", e);
2183 List<Neighbors> neighbors = config.getNeighbors();
2184 if (neighbors != null) {
2185 LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
2186 boolean neighborConfigReplayResult = replayNbrConfig(neighbors, br);
2187 if (neighborConfigReplayResult == false) {
2188 replaySucceded = false;
2191 LOG.error("no Neighbors present for replay config ");
2194 Logging logging = config.getLogging();
2195 if (logging != null) {
2197 br.setLogging(logging.getFile(), logging.getLevel());
2198 } catch (TException | BgpRouterException e) {
2199 LOG.error("Replay:setLogging() received exception", e);
2203 GracefulRestart gracefulRestart = config.getGracefulRestart();
2204 if (gracefulRestart != null) {
2206 br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
2207 } catch (TException | BgpRouterException e) {
2208 LOG.error("Replay:addGr() received exception", e);
2212 List<Vrfs> vrfs = config.getVrfs();
2214 vrfs = new ArrayList<>();
2216 for (Vrfs vrf : vrfs) {
2217 for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf()) {
2219 br.addVrf(BgpUtil.getLayerType(adf), vrf.getRd(), vrf.getImportRts(),
2220 vrf.getExportRts());
2221 } catch (TException | BgpRouterException e) {
2222 LOG.error("Replay:addVrf() received exception", e);
2227 List<Networks> ln = config.getNetworks();
2229 for (Networks net : ln) {
2230 String rd = net.getRd();
2231 String pfxlen = net.getPrefixLen();
2232 String nh = net.getNexthop().getValue();
2233 Long label = net.getLabel();
2234 int lbl = label == null ? 0 : label.intValue();
2235 int l3vni = net.getL3vni() == null ? 0 : net.getL3vni().intValue();
2236 int l2vni = net.getL2vni() == null ? 0 : net.getL2vni().intValue();
2237 if (rd == null && lbl > 0) {
2238 //LU prefix is being deleted.
2239 rd = Integer.toString(lbl);
2242 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
2243 int ethernetTag = net.getEthtag().intValue();
2244 String esi = net.getEsi();
2245 String macaddress = net.getMacaddress();
2246 EncapType encapType = net.getEncapType();
2247 String routerMac = net.getRoutermac();
2250 br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni,
2251 BgpUtil.convertToThriftProtocolType(protocolType),
2252 ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
2253 } catch (TException | BgpRouterException e) {
2254 LOG.error("Replay:addPfx() received exception", e);
2260 List<Multipath> multipaths = config.getMultipath();
2262 if (multipaths != null) {
2263 for (Multipath multipath : multipaths) {
2264 if (multipath != null) {
2265 af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
2266 af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
2269 if (multipath.isMultipathEnabled()) {
2270 br.enableMultipath(afi, safi);
2272 br.disableMultipath(afi, safi);
2274 } catch (TException | BgpRouterException e) {
2275 LOG.info("Replay:multipaths() received exception", e);
2280 List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
2281 if (vrfMaxpaths != null) {
2282 for (VrfMaxpath vrfMaxpath : vrfMaxpaths) {
2284 br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
2285 } catch (TException | BgpRouterException e) {
2286 LOG.info("Replay:vrfMaxPath() received exception", e);
2291 //send End of Rib Marker to Qthriftd.
2292 final int numberOfEORRetries = 3;
2294 RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
2298 LOG.debug("Replay sendEOR {} successful");
2301 } catch (Exception e) {
2302 eorRetry.errorOccured();
2303 LOG.error("Replay:sedEOR() received exception:", e);
2305 } while (eorRetry.shouldRetry());
2307 return replaySucceded && replayDone;
2310 private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
2311 bgpUtil.update(iid, dto);
2314 private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
2315 bgpUtil.delete(iid);
2318 public void startConfig(String bgpHost, int thriftPort) {
2319 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2320 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2321 InstanceIdentifier<ConfigServer> iid = iib.build();
2322 Ipv4Address ipAddr = new Ipv4Address(bgpHost);
2323 ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
2324 .setPort((long) thriftPort).build();
2328 public void startBgp(long as, String routerId, int spt, boolean fbit) {
2329 IpAddress rid = routerId == null ? null : new IpAddress(routerId.toCharArray());
2330 Long staleTime = (long) spt;
2331 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2332 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2333 InstanceIdentifier<AsId> iid = iib.build();
2334 AsId dto = new AsIdBuilder().setLocalAs(as)
2336 .setStalepathTime(staleTime)
2337 .setAnnounceFbit(fbit).build();
2341 public void addLogging(String fileName, String logLevel) {
2342 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2343 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2344 InstanceIdentifier<Logging> iid = iib.build();
2345 Logging dto = new LoggingBuilder().setFile(fileName)
2346 .setLevel(logLevel).build();
2350 public void addGracefulRestart(int staleTime) {
2351 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2352 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2353 InstanceIdentifier<GracefulRestart> iid = iib.build();
2354 GracefulRestart dto = new GracefulRestartBuilder()
2355 .setStalepathTime((long) staleTime).build();
2359 public void addNeighbor(
2360 String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2361 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2362 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2363 InstanceIdentifier.builder(Bgp.class)
2364 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2365 InstanceIdentifier<Neighbors> iid = iib.build();
2366 TcpSecurityOption tcpSecOption = null;
2367 if (md5Secret != null) {
2368 tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2369 } // else let tcpSecOption be null
2370 Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2371 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2373 } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2375 public void addUpdateSource(String nbrIp, String srcIp) {
2376 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2377 Ipv4Address srcAddr = new Ipv4Address(srcIp);
2378 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2379 InstanceIdentifier.builder(Bgp.class)
2380 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2381 .child(UpdateSource.class);
2382 InstanceIdentifier<UpdateSource> iid = iib.build();
2383 UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2384 .setSourceIp(srcAddr).build();
2388 public void addEbgpMultihop(String nbrIp, int hops) {
2389 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2390 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2391 InstanceIdentifier.builder(Bgp.class)
2392 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2393 .child(EbgpMultihop.class);
2394 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2395 EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2396 .setNhops((long) hops).build();
2400 public void addAddressFamily(String nbrIp, int afi, int safi) {
2401 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2402 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2403 InstanceIdentifier.builder(Bgp.class)
2404 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2405 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2406 InstanceIdentifier<AddressFamilies> iid = iib.build();
2407 AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2408 .setAfi((long) afi).setSafi((long) safi).build();
2412 public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2413 VrfEntry.EncapType encapType, long lbl, long l3vni, long l2vni, String gatewayMac) {
2414 for (String nh : nhList) {
2415 Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2417 InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2418 .child(Networks.class, new NetworksKey(pfx, rd)).build();
2419 NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2420 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
2421 buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, l2vni, macAddress, gatewayMac);
2422 update(iid, networksBuilder.build());
2426 private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
2427 long l3vni, long l2vni, String macAddress, String gatewayMac) {
2428 if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2429 builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2430 .setEncapType(EncapType.GRE);
2432 builder.setL3vni(l3vni).setL2vni(l2vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2433 .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2437 // TODO: add LayerType as arg - supports command
2438 public void addVrf(String rd, List<String> irts, List<String> erts, AddressFamily addressFamily) {
2439 Vrfs vrf = bgpUtil.getVrfFromRd(rd);
2440 List<AddressFamiliesVrf> adfList = new ArrayList<>(1);
2442 adfList = vrf.getAddressFamiliesVrf();
2444 AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2445 if (addressFamily.equals(AddressFamily.IPV4)) {
2446 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2447 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2448 } else if (addressFamily.equals(AddressFamily.IPV6)) {
2449 adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2450 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2451 } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2452 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2453 adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2455 AddressFamiliesVrf adf = adfBuilder.build();
2457 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = InstanceIdentifier.builder(Bgp.class)
2458 .child(Vrfs.class, new VrfsKey(rd));
2459 InstanceIdentifier<Vrfs> iid = iib.build();
2460 Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2461 .setExportRts(erts).setAddressFamiliesVrf(adfList).build();
2463 List<AddressFamiliesVrf> listAdFamilies = mapNewAdFamily.get(rd);
2464 if (listAdFamilies != null) {
2465 listAdFamilies.add(adf);
2467 mapNewAdFamily.put(rd, adfList);
2471 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2472 } catch (TransactionCommitFailedException e) {
2473 LOG.error("Error adding VRF to datastore", e);
2474 throw new RuntimeException(e);
2478 public void stopConfig() {
2479 InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2480 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2481 InstanceIdentifier<ConfigServer> iid = iib.build();
2485 public void stopBgp() {
2486 InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2487 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2488 InstanceIdentifier<AsId> iid = iib.build();
2492 public void delLogging() {
2493 InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2494 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2495 InstanceIdentifier<Logging> iid = iib.build();
2499 public void delGracefulRestart() {
2500 InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2501 InstanceIdentifier.builder(Bgp.class)
2502 .child(GracefulRestart.class);
2503 InstanceIdentifier<GracefulRestart> iid = iib.build();
2507 public void delNeighbor(String nbrIp) {
2508 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2509 InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2510 InstanceIdentifier.builder(Bgp.class)
2511 .child(Neighbors.class, new NeighborsKey(nbrAddr));
2512 InstanceIdentifier<Neighbors> iid = iib.build();
2516 public void delUpdateSource(String nbrIp) {
2517 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2518 InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2519 InstanceIdentifier.builder(Bgp.class)
2520 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2521 .child(UpdateSource.class);
2522 InstanceIdentifier<UpdateSource> iid = iib.build();
2526 public void delEbgpMultihop(String nbrIp) {
2527 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2528 InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2529 InstanceIdentifier.builder(Bgp.class)
2530 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2531 .child(EbgpMultihop.class);
2532 InstanceIdentifier<EbgpMultihop> iid = iib.build();
2536 public void delAddressFamily(String nbrIp, int afi, int safi) {
2537 Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2538 InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2539 InstanceIdentifier.builder(Bgp.class)
2540 .child(Neighbors.class, new NeighborsKey(nbrAddr))
2541 .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2542 InstanceIdentifier<AddressFamilies> iid = iib.build();
2546 public void delPrefix(String rd, String pfx) {
2547 InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2548 InstanceIdentifier.builder(Bgp.class)
2549 .child(Networks.class, new NetworksKey(pfx, rd));
2550 InstanceIdentifier<Networks> iid = iib.build();
2554 public boolean delVrf(String rd, AddressFamily addressFamily) {
2555 if (addressFamily == null) {
2556 LOG.error("delVrf: vrf {}, addressFamily invalid", rd);
2559 AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2560 if (addressFamily.equals(AddressFamily.IPV4)) {
2561 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2562 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2563 } else if (addressFamily.equals(AddressFamily.IPV6)) {
2564 adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2565 adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2566 } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2567 adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2568 adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2570 Vrfs vrfOriginal = bgpUtil.getVrfFromRd(rd);
2571 if (vrfOriginal == null) {
2572 LOG.error("delVrf: no vrf with existing rd {}. step aborted", rd);
2576 InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2577 InstanceIdentifier.builder(Bgp.class)
2578 .child(Vrfs.class, new VrfsKey(rd));
2580 InstanceIdentifier<Vrfs> iid = iib.build();
2582 @SuppressWarnings("static-access")
2583 InstanceIdentifier<Bgp> iid6 = iid.builder(Bgp.class).build()
2584 .child(Multipath.class, new MultipathKey(adfBuilder.getAfi(), adfBuilder.getSafi())).create(Bgp.class);
2585 InstanceIdentifierBuilder<Vrfs> iib3 = iid6.child(Vrfs.class, new VrfsKey(rd)).builder();
2586 InstanceIdentifier<Vrfs> iidFinal = iib3.build();
2588 //** update or delete the vrfs with the rest of AddressFamilies already present in the last list
2589 AddressFamiliesVrf adfToDel = adfBuilder.build();
2590 List<AddressFamiliesVrf> adfListOriginal = vrfOriginal.getAddressFamiliesVrf() == null
2591 ? new ArrayList<>() : vrfOriginal.getAddressFamiliesVrf();
2592 List<AddressFamiliesVrf> adfListToRemoveFromOriginal = new ArrayList<>();
2593 adfListOriginal.forEach(adf -> {
2594 if (adf.equals(adfToDel)) {
2595 adfListToRemoveFromOriginal.add(adfToDel);
2599 for (AddressFamiliesVrf adfToRemove : adfListToRemoveFromOriginal) {
2600 adfListOriginal.remove(adfToRemove);
2602 SingleTransactionDataBroker.syncWrite(dataBroker,
2603 LogicalDatastoreType.CONFIGURATION, iid, vrfOriginal);
2604 } catch (TransactionCommitFailedException e) {
2605 LOG.error("delVrf: Error updating VRF to datastore", e);
2606 throw new RuntimeException(e);
2609 if (adfListOriginal.isEmpty()) {
2613 // not all is removed
2617 public void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2618 long lafi = afi.getValue();
2619 long lsafi = safi.getValue();
2621 InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2624 .child(Multipath.class,
2625 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2627 Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2628 update(iib.build(), dto);
2631 public void multipaths(String rd, int maxpath) {
2632 InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2635 .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2637 VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2638 update(iib.build(), dto);
2642 * Remove Stale Marked Routes after timer expiry.
2644 private class RouteCleanup implements Callable<Integer> {
2647 public Integer call() {
2650 if (staledFibEntriesMap.isEmpty()) {
2651 LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2653 for (String rd : staledFibEntriesMap.keySet()) {
2654 if (Thread.interrupted()) {
2657 Map<String, Long> map = staledFibEntriesMap.get(rd);
2659 for (String key : map.keySet()) {
2660 if (Thread.interrupted()) {
2663 String prefix = extractPrefix(key);
2664 String nextHop = extractNextHop(key);
2666 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
2667 rd, prefix, nextHop);
2668 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
2674 staledFibEntriesMap.clear();
2676 LOG.error("cleared {} stale routes after bgp restart", totalCleared);
2682 * BGP restart scenario, ODL-BGP manager was/is running.
2683 * On re-sync notification, Get a copy of FIB database.
2685 public void createStaleFibMap() {
2686 totalStaledCount = 0;
2688 staledFibEntriesMap.clear();
2689 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2691 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2692 LogicalDatastoreType.CONFIGURATION, id);
2693 if (fibEntries.isPresent()) {
2694 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2695 for (VrfTables vrfTable : staleVrfTables) {
2696 Map<String, Long> staleFibEntMap = new HashMap<>();
2697 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2698 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2699 //Stale marking and cleanup is only meant for the routes learned through BGP.
2702 if (Thread.interrupted()) {
2706 //Create MAP from staleVrfTables.
2707 vrfEntry.getRoutePaths()
2709 routePath -> staleFibEntMap.put(
2710 appendNextHopToPrefix(vrfEntry.getDestPrefix(),
2711 routePath.getNexthopAddress()), routePath.getLabel()));
2713 staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
2716 LOG.error("createStaleFibMap:: FIBentries.class is not present");
2718 } catch (ReadFailedException e) {
2719 LOG.error("createStaleFibMap:: error ", e);
2721 LOG.error("created {} staled entries ", totalStaledCount);
2725 * BGP config remove scenario, Need to remove all the
2726 * external routes from FIB.
2728 public void deleteExternalFibRoutes() {
2729 totalExternalRoutes = 0;
2730 totalExternalMacRoutes = 0;
2732 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
2734 Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2735 LogicalDatastoreType.CONFIGURATION, id);
2736 if (fibEntries.isPresent()) {
2737 if (fibEntries.get().getVrfTables() == null) {
2738 LOG.error("deleteExternalFibRoutes::getVrfTables is null");
2741 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
2742 for (VrfTables vrfTable : staleVrfTables) {
2743 String rd = vrfTable.getRouteDistinguisher();
2744 if (vrfTable.getVrfEntry() != null) {
2745 for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
2746 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
2747 //route cleanup is only meant for the routes learned through BGP.
2750 totalExternalRoutes++;
2751 fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
2753 } else if (vrfTable.getMacVrfEntry() != null) {
2754 for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
2755 if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
2756 //route cleanup is only meant for the routes learned through BGP.
2759 totalExternalMacRoutes++;
2760 fibDSWriter.removeMacEntryFromDS(rd, macEntry.getMac());
2765 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
2767 } catch (ReadFailedException e) {
2768 LOG.error("deleteExternalFibRoutes:: error ", e);
2770 LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
2773 public boolean addToRt2TepMap(String rd, String tepIp, String mac, Long l2vni) {
2774 boolean isFirstMacUpdateFromTep = false;
2775 if (rt2TepMap.containsKey(rd)) {
2776 if (rt2TepMap.get(rd).containsKey(tepIp)) {
2777 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and tep-ip {}. No Elan DS write required",
2778 mac, l2vni, rd, tepIp);
2779 rt2TepMap.get(rd).get(tepIp).put(mac, l2vni);
2781 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
2782 mac, l2vni, rd, tepIp);
2783 isFirstMacUpdateFromTep = true;
2784 Map<String, Long> macList = new HashMap<>();
2785 macList.put(mac, l2vni);
2786 rt2TepMap.get(rd).put(tepIp, macList);
2789 LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
2790 mac, l2vni, rd, tepIp);
2791 isFirstMacUpdateFromTep = true;
2792 Map<String, Long> macList = new HashMap<>();
2793 macList.put(mac, l2vni);
2794 Map<String, Map<String, Long>> tepIpMacMap = new HashMap<>();
2795 tepIpMacMap.put(tepIp, macList);
2796 rt2TepMap.put(rd, tepIpMacMap);
2798 return isFirstMacUpdateFromTep;
2801 public boolean deleteFromRt2TepMap(String rd, String tepIp, String mac) {
2802 boolean isLastMacUpdateFromTep = false;
2803 LOG.debug("RT2 withdraw with rd {} mac {} tep-ip {} ", rd, mac, tepIp);
2804 if (rt2TepMap.containsKey(rd)) {
2805 if (rt2TepMap.get(rd).containsKey(tepIp)) {
2806 if (rt2TepMap.get(rd).get(tepIp).containsKey(mac)) {
2807 LOG.debug("RT2 Withdraw : Removing the mac {} from Map", mac);
2808 rt2TepMap.get(rd).get(tepIp).remove(mac);
2809 if (rt2TepMap.get(rd).get(tepIp).isEmpty()) {
2810 isLastMacUpdateFromTep = true;
2811 LOG.debug("RT2 Withdraw : Removing the tep-ip {} from Map", tepIp);
2812 rt2TepMap.get(rd).remove(tepIp);
2813 if (rt2TepMap.get(rd).isEmpty()) {
2814 LOG.debug("RT2 Withdraw : Removing the rd {} from Map", rd);
2815 rt2TepMap.remove(rd);
2821 return isLastMacUpdateFromTep;
2824 public Collection<String> getTepIPs(String rd) {
2825 final Map<String, Map<String, Long>> tepIpMap = rt2TepMap.get(rd);
2826 return tepIpMap != null ? tepIpMap.keySet() : Collections.emptyList();
2829 public boolean isBgpConnected() {
2830 return bgpRouter.isBgpConnected();
2833 public long getLastConnectedTS() {
2834 return bgpRouter.getLastConnectedTS();
2837 public long getConnectTS() {
2838 return bgpRouter.getConnectTS();
2841 public long getStartTS() {
2842 return bgpRouter.getStartTS();
2845 public TTransport getTransport() {
2846 return bgpRouter.getTransport();
2849 public int getTotalStaledCount() {
2850 return totalStaledCount;
2853 public int getTotalCleared() {
2854 return totalCleared;
2857 public BgpCounters getBgpCounters() {
2858 return bgpCountersReference.get();
2861 private void startBgpCountersTask() {
2862 if (getBgpCounters() == null && bgpCountersReference.compareAndSet(null,
2863 new BgpCounters(getBgpSdncMipIp(), metricProvider))) {
2864 bgpCountersTask = executor.scheduleAtFixedRate(bgpCountersReference.get(), 0, 120 * 1000,
2865 TimeUnit.MILLISECONDS);
2866 LOG.info("Bgp Counters task scheduled for every two minutes.");
2868 bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
2872 private void stopBgpCountersTask() {
2873 final BgpCounters bgpCounters = bgpCountersReference.getAndSet(null);
2874 if (bgpCounters != null) {
2875 bgpCountersTask.cancel(true);
2876 bgpCounters.close();
2880 private void startBgpAlarmsTask() {
2881 if (getBgpAlarms() == null && bgpAlarmsReference.compareAndSet(null, new BgpAlarms(this))) {
2882 bgpAlarmsReference.get().init();
2883 bgpAlarmsTask = executor.scheduleAtFixedRate(bgpAlarmsReference.get(), 0, 60 * 1000, TimeUnit.MILLISECONDS);
2884 LOG.info("Bgp Alarms task scheduled for every minute.");
2888 private void stopBgpAlarmsTask() {
2889 final BgpAlarms bgpAlarms = bgpAlarmsReference.getAndSet(null);
2890 if (bgpAlarms != null) {
2891 bgpAlarmsTask.cancel(true);
2896 public BgpAlarms getBgpAlarms() {
2897 return bgpAlarmsReference.get();
2900 private static String appendNextHopToPrefix(String prefix, String nextHop) {
2901 return prefix + ":" + nextHop;
2904 private static String extractPrefix(String prefixNextHop) {
2905 return prefixNextHop.split(":")[0];
2908 private static String extractNextHop(String prefixNextHop) {
2909 return prefixNextHop.split(":")[1];
2912 private static String extractMd5Secret(final Neighbors val) {
2913 String md5Secret = null;
2914 TcpSecurityOption tcpSecOpt = val.getTcpSecurityOption();
2915 if (tcpSecOpt != null) {
2916 if (tcpSecOpt instanceof TcpMd5SignatureOption) {
2917 md5Secret = ((TcpMd5SignatureOption) tcpSecOpt).getTcpMd5SignaturePassword().getValue();
2918 } else { // unknown TcpSecurityOption
2919 LOG.debug("neighbors Ignored unknown tcp-security-option of peer {}", val.getAddress().getValue());
2923 } // private method extractMd5Secret