Optimizing BGP routesync operation
[netvirt.git] / bgpmanager / impl / src / main / java / org / opendaylight / netvirt / bgpmanager / BgpConfigurationManager.java
1 /*
2  * Copyright © 2015, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.bgpmanager;
9
10 import static org.opendaylight.netvirt.bgpmanager.oam.BgpConstants.HISTORY_LIMIT;
11 import static org.opendaylight.netvirt.bgpmanager.oam.BgpConstants.HISTORY_THRESHOLD;
12
13 import com.google.common.base.Optional;
14 import com.google.common.base.Preconditions;
15 import com.google.common.net.InetAddresses;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import com.google.common.util.concurrent.ThreadFactoryBuilder;
19 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
20 import io.netty.util.concurrent.GlobalEventExecutor;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.net.InetAddress;
24 import java.net.InetSocketAddress;
25 import java.net.NetworkInterface;
26 import java.net.SocketException;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.Enumeration;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.Timer;
37 import java.util.concurrent.Callable;
38 import java.util.concurrent.ConcurrentHashMap;
39 import java.util.concurrent.CountDownLatch;
40 import java.util.concurrent.ExecutionException;
41 import java.util.concurrent.Executors;
42 import java.util.concurrent.Future;
43 import java.util.concurrent.ScheduledExecutorService;
44 import java.util.concurrent.ScheduledFuture;
45 import java.util.concurrent.TimeUnit;
46 import java.util.concurrent.TimeoutException;
47 import java.util.concurrent.atomic.AtomicBoolean;
48 import java.util.concurrent.atomic.AtomicInteger;
49 import java.util.concurrent.atomic.AtomicReference;
50 import javax.annotation.PreDestroy;
51 import javax.inject.Inject;
52 import javax.inject.Singleton;
53 import org.apache.thrift.TApplicationException;
54 import org.apache.thrift.TException;
55 import org.apache.thrift.transport.TTransport;
56 import org.eclipse.jdt.annotation.Nullable;
57 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
58 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
59 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
60 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
61 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
62 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
63 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
64 import org.opendaylight.genius.mdsalutil.NwConstants;
65 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
66 import org.opendaylight.infrautils.metrics.MetricProvider;
67 import org.opendaylight.mdsal.eos.binding.api.Entity;
68 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
69 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
70 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
71 import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException;
72 import org.opendaylight.mdsal.eos.common.api.EntityOwnershipChangeState;
73 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
74 import org.opendaylight.netvirt.bgpmanager.commands.ClearBgpCli;
75 import org.opendaylight.netvirt.bgpmanager.oam.BgpAlarms;
76 import org.opendaylight.netvirt.bgpmanager.oam.BgpConstants;
77 import org.opendaylight.netvirt.bgpmanager.oam.BgpCounters;
78 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouter;
79 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpRouterException;
80 import org.opendaylight.netvirt.bgpmanager.thrift.client.BgpSyncHandle;
81 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Routes;
82 import org.opendaylight.netvirt.bgpmanager.thrift.gen.Update;
83 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_afi;
84 import org.opendaylight.netvirt.bgpmanager.thrift.gen.af_safi;
85 import org.opendaylight.netvirt.bgpmanager.thrift.gen.protocol_type;
86 import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
87 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
88 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
89 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
90 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionHistory;
91 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
92 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebfd.rev190219.BfdConfig;
93 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebfd.rev190219.BfdConfigBuilder;
94 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
95 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
96 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
97 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EbgpService;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.InitiateEorInput;
100 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.InitiateEorOutput;
101 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.InitiateEorOutputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
103 //import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
104 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
105 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
107 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
108 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.DcgwTepList;
109 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
110 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
111 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
112 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
113 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathContainer;
114 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsContainer;
115 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksContainer;
116 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathContainer;
117 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsContainer;
118 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.dcgw.tep.list.DcgwTep;
119 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.dcgw.tep.list.DcgwTepBuilder;
120 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.dcgw.tep.list.DcgwTepKey;
121 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.multipathcontainer.Multipath;
122 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.multipathcontainer.MultipathBuilder;
123 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.multipathcontainer.MultipathKey;
124 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.Neighbors;
125 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.NeighborsBuilder;
126 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.NeighborsKey;
127 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.AddressFamilies;
128 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.AddressFamiliesBuilder;
129 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.AddressFamiliesKey;
130 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.EbgpMultihop;
131 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.EbgpMultihopBuilder;
132 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.UpdateSource;
133 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.UpdateSourceBuilder;
134 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.networkscontainer.Networks;
135 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.networkscontainer.NetworksBuilder;
136 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.networkscontainer.NetworksKey;
137 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfmaxpathcontainer.VrfMaxpath;
138 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfmaxpathcontainer.VrfMaxpathBuilder;
139 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfmaxpathcontainer.VrfMaxpathKey;
140 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.Vrfs;
141 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.VrfsBuilder;
142 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.VrfsKey;
143 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.vrfs.AddressFamiliesVrf;
144 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.vrfs.AddressFamiliesVrfBuilder;
145 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
146 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOption;
147 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
148 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
149 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
150 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
156 import org.opendaylight.yangtools.yang.binding.DataObject;
157 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
158 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
159 import org.opendaylight.yangtools.yang.common.RpcError;
160 import org.opendaylight.yangtools.yang.common.RpcResult;
161 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
162 import org.opendaylight.yangtools.yang.common.Uint32;
163 import org.osgi.framework.BundleContext;
164 import org.osgi.util.tracker.ServiceTracker;
165 import org.slf4j.Logger;
166 import org.slf4j.LoggerFactory;
167
168 @Singleton
169 public class BgpConfigurationManager implements EbgpService {
170     private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
171
172     // to have stale FIB map (RD, Prefix)
173     //  number of seconds wait for route sync-up between ODL and BGP
174     private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
175     private static final String UPDATE_PORT = "bgp.thrift.service.port";
176     private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
177     private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
178     private static final String DEF_UPORT = "6644";
179     private static final String DEF_CHOST = "255.255.255.255"; // Invalid Host IP
180     private static final String DEF_CPORT = "7644";
181     private static final String DEF_BGP_SDNC_MIP = "127.0.0.1";
182     //vpnservice.bgp.thrift.bgp.mip is the MIP present with ODL. Here we open 6644 port
183     private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.bgp.mip";
184     private static final String BGP_GR_RESTART_TIMER_PROPERTY = "vpnservice.bgp.gr.timer";
185     private static final String BGP_KA_TIMER_PROPERTY = "vpnservice.bgp.ka.timer";
186     private static final String BGP_HOLD_TIMER_PROPERTY = "vpnservice.bgp.hold.timer";
187     private static final String BGP_EOR_DELAY_PROPERTY = "vpnservice.bgp.eordelay";
188     private static final int DEF_BGP_KA_TIME = 60;
189     private static final int DEF_BGP_HOLD_TIME = 180;
190     private static final int DEF_BGP_GR_TIME = 4000;
191     private static final int RESTART_DEFAULT_GR = 90;
192     private static final int DS_RETRY_COUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
193     private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
194     private static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
195     private static final String BGP_EOR_DELAY = "vpnservice.bgp.eordelay";
196     private static final String DEF_BGP_EOR_DELAY = "1800";
197     private static final String BGP_ENTITY_NAME = "bgp";
198     private static final String ADD_WARN = "Config store updated; undo with Delete if needed.";
199     private static final String DEL_WARN = "Config store updated; undo with Add if needed.";
200     private static final String UPD_WARN = "Update operation not supported; Config store updated;"
201             + " restore with another Update if needed.";
202     private static long bgp_as_num = 0;
203     private int bgpKaTime = 0;
204     private int bgpHoldTime = 0;
205     private int bgpGrRestartTime = 0;
206
207     private static final Class<?>[] REACTORS = {
208         ConfigServerReactor.class, AsIdReactor.class,
209         GracefulRestartReactor.class, LoggingReactor.class,
210         NeighborsReactor.class, UpdateSourceReactor.class,
211         EbgpMultihopReactor.class, AddressFamiliesReactor.class,
212         NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
213         MultipathReactor.class, VrfMaxpathReactor.class, BfdConfigReactor.class
214     };
215
216     private IBgpManager bgpManager;
217     private final DataBroker dataBroker;
218     private final FibDSWriter fibDSWriter;
219     private final IVpnLinkService vpnLinkService;
220     private final BundleContext bundleContext;
221     private final BgpUtil bgpUtil;
222     private volatile Bgp config;
223     private final BgpRouter bgpRouter;
224     private final BgpSyncHandle bgpSyncHandle = new BgpSyncHandle();
225     private volatile BgpThriftService bgpThriftService = null;
226     private final int delayEorSeconds;
227
228     private final CountDownLatch initer = new CountDownLatch(1);
229
230     private final String hostStartup;
231     private final String portStartup;
232
233     private final AtomicReference<BgpCounters> bgpCountersReference = new AtomicReference<>();
234     private ScheduledFuture<?> bgpCountersTask;
235
236     private final AtomicReference<BgpAlarms> bgpAlarmsReference = new AtomicReference<>();
237     private ScheduledFuture<?> bgpAlarmsTask;
238
239     private Future<?> lastReplayJobFt;
240     private ScheduledFuture<?> routeCleanupFuture;
241
242     private long staleStartTime;
243     private long staleEndTime;
244     private long cfgReplayStartTime;
245     private long cfgReplayEndTime;
246     private long staleCleanupTime;
247     private int totalStaledCount;
248     private int totalCleared;
249     private int totalExternalRoutes;
250     private int totalExternalMacRoutes;
251
252     private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
253             new ThreadFactoryBuilder().setNameFormat("bgp-config-%d").setDaemon(true).build());
254
255     /**
256      * this map store the new address families to send to quagga. When it is sended you must clear it.
257      * The keys String are rd (route distinguisher).
258      * */
259     private final ConcurrentHashMap<String, List<AddressFamiliesVrf>> mapNewAdFamily = new ConcurrentHashMap<>();
260
261     // map<rd, map<prefix/len:nexthop, label>>
262     private final Map<String, Map<String, Uint32>> staledFibEntriesMap = new ConcurrentHashMap<>();
263
264     // map<rd, map<tep-ip, map<mac, l2vni>>>
265     private final Map<String, Map<String, Map<String, Uint32>>> rt2TepMap = new ConcurrentHashMap<>();
266
267     private final List<AutoCloseable> listeners = new ArrayList<>();
268
269     private final EntityOwnershipUtils entityOwnershipUtils;
270     private final EntityOwnershipCandidateRegistration candidateRegistration;
271     private final EntityOwnershipListenerRegistration entityListenerRegistration;
272     private final MetricProvider metricProvider;
273     private final TransactionHistory bgpUpdatesHistory;
274
275     private volatile AtomicBoolean eorSupressedDuetoUpgradeFlag = new AtomicBoolean(false);
276
277     @Inject
278     public BgpConfigurationManager(final DataBroker dataBroker,
279             final EntityOwnershipService entityOwnershipService,
280             final FibDSWriter fibDSWriter,
281             final IVpnLinkService vpnLinkSrvce,
282             final BundleContext bundleContext,
283             final BgpUtil bgpUtil,
284             final MetricProvider metricProvider) {
285         this.dataBroker = dataBroker;
286         this.fibDSWriter = fibDSWriter;
287         this.vpnLinkService = vpnLinkSrvce;
288         this.bundleContext = bundleContext;
289         this.bgpUtil = bgpUtil;
290         this.metricProvider = metricProvider;
291         hostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
292         portStartup = getProperty(CONFIG_PORT, DEF_CPORT);
293         bgpKaTime =
294                 Integer.parseInt(getProperty(BGP_KA_TIMER_PROPERTY,
295                         Integer.toString(DEF_BGP_KA_TIME)));
296         bgpHoldTime =
297                 Integer.parseInt(getProperty(BGP_HOLD_TIMER_PROPERTY,
298                         Integer.toString(DEF_BGP_HOLD_TIME)));
299         bgpGrRestartTime =
300                 Integer.parseInt(getProperty(BGP_GR_RESTART_TIMER_PROPERTY,
301                         Integer.toString(DEF_BGP_GR_TIME)));
302         LOG.info("ConfigServer at {}:{}", hostStartup, portStartup);
303         VtyshCli.setHostAddr(hostStartup);
304         ClearBgpCli.setHostAddr(hostStartup);
305         bgpUpdatesHistory = new TransactionHistory(HISTORY_LIMIT, HISTORY_THRESHOLD);
306         bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner, bgpUpdatesHistory);
307         delayEorSeconds = Integer.parseInt(getProperty(BGP_EOR_DELAY, DEF_BGP_EOR_DELAY));
308
309         entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
310
311         candidateRegistration = registerEntityCandidate(entityOwnershipService);
312         entityListenerRegistration = registerEntityListener(entityOwnershipService);
313
314         LOG.info("BGP Configuration manager initialized");
315         initer.countDown();
316
317         GlobalEventExecutor.INSTANCE.execute(() -> {
318             ServiceTracker<IBgpManager, ?> tracker = null;
319             try {
320                 tracker = new ServiceTracker<>(bundleContext, IBgpManager.class, null);
321                 tracker.open();
322                 bgpManager = (IBgpManager) tracker.waitForService(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
323                 Preconditions.checkState(bgpManager != null, "IBgpManager service not found");
324             } catch (InterruptedException e) {
325                 throw new IllegalStateException("Error retrieving IBgpManager service", e);
326             } finally {
327                 if (tracker != null) {
328                     tracker.close();
329                 }
330             }
331
332             String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
333             if (InetAddresses.isInetAddress(getBgpSdncMipIp())) {
334                 InetSocketAddress bgpThriftServerSocketAddr = new InetSocketAddress(getBgpSdncMipIp(),
335                         Integer.parseInt(updatePort));
336                 bgpThriftService = new BgpThriftService(bgpThriftServerSocketAddr, bgpManager, this);
337                 if (isBGPEntityOwner()) {
338                     //I am EoS owner of BGP, opening bgp thrift UPDATE-SERVER port.
339                     LOG.info("BGP Configuration manager initialized: UPDATE-SERVER started");
340                     bgpThriftService.start();
341                 }
342                 LOG.info("UPDATE server started :ip:port={}:{}", getBgpSdncMipIp(), updatePort);
343             } else {
344                 LOG.error("Failed to init UPDATE server invalid ip:port={}:{}", getBgpSdncMipIp(), updatePort);
345             }
346         });
347         registerCallbacks();
348         LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
349     }
350
351     public String getBgpSdncMipIp() {
352         return getProperty(BGP_SDNC_MIP, DEF_BGP_SDNC_MIP);
353     }
354
355     public long getStaleCleanupTime() {
356         return staleCleanupTime;
357     }
358
359     public void setStaleCleanupTime(long staleCleanupTime) {
360         this.staleCleanupTime = staleCleanupTime;
361     }
362
363     public long getCfgReplayEndTime() {
364         return cfgReplayEndTime;
365     }
366
367     public void setCfgReplayEndTime(long cfgReplayEndTime) {
368         this.cfgReplayEndTime = cfgReplayEndTime;
369     }
370
371     public TransactionHistory getBgpUpdatesHistory() {
372         return bgpUpdatesHistory;
373     }
374
375     public long getCfgReplayStartTime() {
376         return cfgReplayStartTime;
377     }
378
379     public void setCfgReplayStartTime(long cfgReplayStartTime) {
380         this.cfgReplayStartTime = cfgReplayStartTime;
381     }
382
383     public long getStaleEndTime() {
384         return staleEndTime;
385     }
386
387     public void setStaleEndTime(long staleEndTime) {
388         this.staleEndTime = staleEndTime;
389     }
390
391     public long getStaleStartTime() {
392         return staleStartTime;
393     }
394
395     public void setStaleStartTime(long staleStartTime) {
396         this.staleStartTime = staleStartTime;
397     }
398
399     private Object createListener(Class<?> cls) {
400         try {
401             Constructor<?> ctor = cls.getConstructor(BgpConfigurationManager.class);
402             return ctor.newInstance(this);
403         } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException
404                 e) {
405             LOG.error("Failed to create listener object", e);
406             return null;
407         }
408     }
409
410     private void registerCallbacks() {
411         for (Class<?> reactor : REACTORS) {
412             Object obj = createListener(reactor);
413             if (obj != null) {
414                 AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
415                 dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
416                 listeners.add(dcl);
417             }
418         }
419     }
420
421     @SuppressWarnings("checkstyle:IllegalCatch")
422     @PreDestroy
423     public void close() {
424         executor.shutdown();
425
426         if (bgpThriftService != null) {
427             bgpThriftService.stop();
428             bgpThriftService = null;
429         }
430
431         if (isBgpConnected()) {
432             //disconnect the CONFIG SERVER port (which was )opened during I was Owner
433             bgpRouter.disconnect();
434         }
435
436         if (candidateRegistration != null) {
437             candidateRegistration.close();
438         }
439
440         entityListenerRegistration.close();
441
442         listeners.forEach(l -> {
443             try {
444                 l.close();
445             } catch (Exception e) {
446                 LOG.warn("Error closing {}", l ,e);
447             }
448         });
449
450         LOG.info("{} close", getClass().getSimpleName());
451     }
452
453     private String getProperty(String var, String def) {
454         String property = bundleContext.getProperty(var);
455         return property == null ? def : property;
456     }
457
458     private EntityOwnershipCandidateRegistration registerEntityCandidate(
459             final EntityOwnershipService entityOwnershipService) {
460         try {
461             return entityOwnershipService.registerCandidate(
462                     new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME));
463         } catch (CandidateAlreadyRegisteredException e) {
464             LOG.error("failed to register bgp entity", e);
465             return null;
466         }
467     }
468
469     private EntityOwnershipListenerRegistration registerEntityListener(
470             final EntityOwnershipService entityOwnershipService) {
471         return entityOwnershipService.registerListener(BGP_ENTITY_TYPE_FOR_OWNERSHIP, ownershipChange -> {
472             LOG.info("entity owner change event fired: {}", ownershipChange);
473
474             if (ownershipChange.getState() == EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED) {
475                 LOG.info("This PL is the Owner");
476                 if (bgpThriftService != null) {
477                     //opening UPDATE-SERVER port.
478                     bgpThriftService.start();
479                 } else {
480                     LOG.error("I am the owner of BGP entity, but bgpThriftService is not initialized yet");
481                 }
482                 bgpRestarted();
483             } else {
484                 LOG.info("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
485                         ownershipChange.getState().isOwner());
486                 if (bgpThriftService != null && bgpThriftService.isBgpThriftServiceStarted()) {
487                     //close the bgp Thrift Update-SERVER port opened on non-Entity Owner
488                     bgpThriftService.stop();
489                 }
490                 if (isBgpConnected()) {
491                     //disconnect the CONFIG SERVER port (which was )opened during I was Owner
492                     bgpRouter.disconnect();
493                 }
494             }
495         });
496     }
497
498     public boolean isBGPEntityOwner() {
499         if (entityOwnershipUtils == null) {
500             LOG.error("entityOwnershipUtils is NULL when listener callbacks fired");
501             return false;
502         }
503         return entityOwnershipUtils.isEntityOwner(new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME), 0, 1);
504     }
505
506     public Bgp get() {
507         config = getConfig();
508         return config;
509     }
510
511     public class ConfigServerReactor
512             extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
513             implements ClusteredDataTreeChangeListener<ConfigServer> {
514         private static final String YANG_OBJ = "config-server ";
515
516         public ConfigServerReactor() {
517             super(ConfigServer.class, ConfigServerReactor.class);
518         }
519
520         @Override
521         protected void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
522             LOG.trace("received bgp connect config host {}", val.getHost().getValue());
523             if (!isBGPEntityOwner()) {
524                 return;
525             }
526
527             try {
528                 initer.await();
529             } catch (InterruptedException e) {
530                 // Ignored
531             }
532             LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
533             bgpRouter.configServerUpdated();
534             synchronized (BgpConfigurationManager.this) {
535                 boolean res = bgpRouter.connect(val.getHost().getValue(),
536                         val.getPort().intValue());
537                 if (!res) {
538                     LOG.error(YANG_OBJ + "Add failed; " + ADD_WARN);
539                 }
540             }
541             VtyshCli.setHostAddr(val.getHost().getValue());
542             ClearBgpCli.setHostAddr(val.getHost().getValue());
543         }
544
545         @Override
546         protected ConfigServerReactor getDataTreeChangeListener() {
547             return ConfigServerReactor.this;
548         }
549
550         @Override
551         protected InstanceIdentifier<ConfigServer> getWildCardPath() {
552             return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
553         }
554
555         @Override
556         protected void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
557             LOG.trace("received bgp disconnect");
558             if (!isBGPEntityOwner()) {
559                 return;
560             }
561
562             bgpRouter.configServerUpdated();
563
564             synchronized (BgpConfigurationManager.this) {
565                 if (bgp_as_num != 0) {
566                     try {
567                         bgpRouter.stopBgp(bgp_as_num);
568                         stopBgpCountersTask();
569                         stopBgpAlarmsTask();
570                     } catch (TException | BgpRouterException e) {
571                         LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
572                     }
573                 } else {
574                     LOG.debug("bgp as-id is null while removing config-server");
575                 }
576                 bgpRouter.disconnect();
577             }
578         }
579
580         @Override
581         protected void update(InstanceIdentifier<ConfigServer> iid,
582                 ConfigServer oldval, ConfigServer newval) {
583             LOG.trace("received bgp Connection update");
584             if (!isBGPEntityOwner()) {
585                 return;
586             }
587             LOG.error(YANG_OBJ + UPD_WARN);
588         }
589     }
590
591     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
592             justification = "https://github.com/spotbugs/spotbugs/issues/811")
593     private BgpRouter getClient(String yangObj) {
594         if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
595             LOG.warn("{}: configuration received when BGP is inactive", yangObj);
596             return null;
597         }
598         return bgpRouter;
599     }
600
601     public class AsIdReactor
602             extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
603             implements ClusteredDataTreeChangeListener<AsId> {
604
605         private static final String YANG_OBJ = "as-id ";
606
607         public AsIdReactor() {
608             super(AsId.class, AsIdReactor.class);
609         }
610
611         @Override
612         protected void add(InstanceIdentifier<AsId> iid, AsId val) {
613             LOG.error("received bgp add asid {}", val);
614             if (!isBGPEntityOwner()) {
615                 return;
616             }
617             LOG.debug("received add router config asNum {}", val.getLocalAs());
618             bgp_as_num = val.getLocalAs().longValue();
619             synchronized (BgpConfigurationManager.this) {
620                 BgpRouter br = getClient(YANG_OBJ);
621                 if (br == null) {
622                     LOG.debug("{} Unable to process add for asNum {}; {} {}", YANG_OBJ, val.getLocalAs(),
623                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
624                     return;
625                 }
626                 bgpRestarted();
627
628                 startBgpCountersTask();
629                 startBgpAlarmsTask();
630             }
631         }
632
633         @Override
634         protected AsIdReactor getDataTreeChangeListener() {
635             return AsIdReactor.this;
636         }
637
638         @Override
639         protected InstanceIdentifier<AsId> getWildCardPath() {
640             return InstanceIdentifier.create(Bgp.class).child(AsId.class);
641         }
642
643         @Override
644         protected void remove(InstanceIdentifier<AsId> iid, AsId val) {
645             LOG.error("received delete router config asNum {}", val.getLocalAs());
646             if (!isBGPEntityOwner()) {
647                 return;
648             }
649             synchronized (BgpConfigurationManager.this) {
650                 long asNum = val.getLocalAs().toJava();
651                 BgpRouter br = getClient(YANG_OBJ);
652                 bgp_as_num = 0;
653                 if (br == null) {
654                     LOG.debug("{} Unable to process remove for asNum {}; {} {}", YANG_OBJ, asNum,
655                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
656                     return;
657                 }
658                 try {
659                     br.stopBgp(asNum);
660                 } catch (TException | BgpRouterException e) {
661                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
662                 }
663
664                 stopBgpCountersTask();
665                 stopBgpAlarmsTask();
666
667                 Bgp conf = getConfig();
668                 if (conf == null) {
669                     LOG.error("Config Null while removing the as-id");
670                     return;
671                 }
672                 LOG.debug("Removing external routes from FIB");
673                 deleteExternalFibRoutes();
674                 List<Neighbors> nbrs = conf.getNeighborsContainer().getNeighbors();
675                 if (nbrs != null && nbrs.size() > 0) {
676                     LOG.error("Tring to remove the as-id when neighbor config is already present");
677                     for (Neighbors nbr : nbrs) {
678                         LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
679                         delNeighbor(nbr.getAddress().getValue());
680                     }
681                 }
682             }
683         }
684
685         @Override
686         protected void update(InstanceIdentifier<AsId> iid,
687                 AsId oldval, AsId newval) {
688             if (!isBGPEntityOwner()) {
689                 return;
690             }
691             LOG.error(YANG_OBJ + UPD_WARN);
692         }
693     }
694
695     public class GracefulRestartReactor
696             extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
697             implements ClusteredDataTreeChangeListener<GracefulRestart> {
698
699         private static final String YANG_OBJ = "graceful-restart ";
700
701         public GracefulRestartReactor() {
702             super(GracefulRestart.class, GracefulRestartReactor.class);
703         }
704
705         @Override
706         protected void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
707             if (!isBGPEntityOwner()) {
708                 return;
709             }
710             synchronized (BgpConfigurationManager.this) {
711                 int stalePathTime = val.getStalepathTime().intValue();
712                 BgpRouter br = getClient(YANG_OBJ);
713                 if (br == null) {
714                     LOG.error("{} Unable to add stale-path time {}; {} {}", YANG_OBJ, stalePathTime,
715                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
716                     return;
717                 }
718                 try {
719                     br.addGracefulRestart(stalePathTime);
720                 } catch (TException | BgpRouterException e) {
721                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
722                 }
723             }
724         }
725
726         @Override
727         protected GracefulRestartReactor getDataTreeChangeListener() {
728             return GracefulRestartReactor.this;
729         }
730
731         @Override
732         protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
733             return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
734         }
735
736         @Override
737         protected void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
738             if (!isBGPEntityOwner()) {
739                 return;
740             }
741             LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
742             synchronized (BgpConfigurationManager.this) {
743                 BgpRouter br = getClient(YANG_OBJ);
744                 if (br == null) {
745                     LOG.error("{} Unable to delete stale-path time; {} {}", YANG_OBJ,
746                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
747                     return;
748                 }
749                 try {
750                     br.delGracefulRestart();
751                 } catch (TException | BgpRouterException e) {
752                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
753                 }
754             }
755         }
756
757         @Override
758         protected void update(InstanceIdentifier<GracefulRestart> iid,
759                 GracefulRestart oldval, GracefulRestart newval) {
760             if (!isBGPEntityOwner()) {
761                 return;
762             }
763             LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
764             synchronized (BgpConfigurationManager.this) {
765                 int stalePathTime = newval.getStalepathTime().intValue();
766                 BgpRouter br = getClient(YANG_OBJ);
767                 if (br == null) {
768                     LOG.error("{} Unable to update stale-path time to {}; {} {}", YANG_OBJ, stalePathTime,
769                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
770                     return;
771                 }
772                 try {
773                     br.addGracefulRestart(stalePathTime);
774                 } catch (TException | BgpRouterException e) {
775                     LOG.error("{} update received exception; {}", YANG_OBJ, ADD_WARN, e);
776                 }
777             }
778         }
779     }
780
781     public class LoggingReactor
782             extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
783             implements ClusteredDataTreeChangeListener<Logging> {
784
785         private static final String YANG_OBJ = "logging ";
786
787         public LoggingReactor() {
788             super(Logging.class, LoggingReactor.class);
789         }
790
791         @Override
792         protected void add(InstanceIdentifier<Logging> iid, Logging val) {
793             if (!isBGPEntityOwner()) {
794                 return;
795             }
796             synchronized (BgpConfigurationManager.this) {
797                 BgpRouter br = getClient(YANG_OBJ);
798                 if (br == null) {
799                     LOG.error("{} Unable to add logging for qbgp; {} {}", YANG_OBJ,
800                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
801                     return;
802                 }
803                 try {
804                     br.setLogging(val.getFile(), val.getLevel());
805                 } catch (TException | BgpRouterException e) {
806                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
807                 }
808             }
809         }
810
811         @Override
812         protected LoggingReactor getDataTreeChangeListener() {
813             return LoggingReactor.this;
814         }
815
816         @Override
817         protected InstanceIdentifier<Logging> getWildCardPath() {
818             return InstanceIdentifier.create(Bgp.class).child(Logging.class);
819         }
820
821         @Override
822         protected void remove(InstanceIdentifier<Logging> iid, Logging val) {
823             if (!isBGPEntityOwner()) {
824                 return;
825             }
826             LOG.debug("received remove Logging config val {}", val.getLevel());
827             synchronized (BgpConfigurationManager.this) {
828                 BgpRouter br = getClient(YANG_OBJ);
829                 if (br == null) {
830                     LOG.error("{} Unable to remove logging for qbgp; {} {}", YANG_OBJ,
831                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
832                     return;
833                 }
834                 try {
835                     br.setLogging(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
836                 } catch (TException | BgpRouterException e) {
837                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
838                 }
839             }
840         }
841
842         @Override
843         protected void update(InstanceIdentifier<Logging> iid,
844                 Logging oldval, Logging newval) {
845             if (!isBGPEntityOwner()) {
846                 return;
847             }
848             synchronized (BgpConfigurationManager.this) {
849                 BgpRouter br = getClient(YANG_OBJ);
850                 if (br == null) {
851                     LOG.error("{} Unable to update logging for qbgp; {} {}", YANG_OBJ,
852                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
853                     return;
854                 }
855                 try {
856                     br.setLogging(newval.getFile(), newval.getLevel());
857                 } catch (TException | BgpRouterException e) {
858                     LOG.error("{} newval received exception; {}", YANG_OBJ, ADD_WARN, e);
859                 }
860             }
861         }
862     }
863
864     public class NeighborsReactor
865             extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
866             implements ClusteredDataTreeChangeListener<Neighbors> {
867
868         private static final String YANG_OBJ = "neighbors ";
869
870         public NeighborsReactor() {
871             super(Neighbors.class, NeighborsReactor.class);
872         }
873
874         @Override
875         protected void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
876             if (!isBGPEntityOwner()) {
877                 return;
878             }
879             LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
880             synchronized (BgpConfigurationManager.this) {
881                 String peerIp = val.getAddress().getValue();
882                 long as = val.getRemoteAs().toJava();
883                 final String md5Secret = extractMd5Secret(val);
884                 BgpRouter br = getClient(YANG_OBJ);
885                 if (br == null) {
886                     LOG.debug("{} Unable to process add for peer {} as {}; {} {}", YANG_OBJ, peerIp, as,
887                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
888                     return;
889                 }
890                 try {
891                     //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
892                     br.addNeighbor(peerIp, as, md5Secret);
893
894                 } catch (TException | BgpRouterException e) {
895                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
896                 }
897             }
898         }
899
900         @Override
901         protected NeighborsReactor getDataTreeChangeListener() {
902             return NeighborsReactor.this;
903         }
904
905         @Override
906         protected InstanceIdentifier<Neighbors> getWildCardPath() {
907             return InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class);
908         }
909
910         @Override
911         protected void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
912             if (!isBGPEntityOwner()) {
913                 return;
914             }
915             LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
916             synchronized (BgpConfigurationManager.this) {
917                 String peerIp = val.getAddress().getValue();
918                 BgpRouter br = getClient(YANG_OBJ);
919                 if (br == null) {
920                     LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
921                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
922                     return;
923                 }
924                 try {
925                     //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
926                     br.delNeighbor(peerIp);
927                 } catch (TException | BgpRouterException e) {
928                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
929                 }
930
931                 final BgpAlarms bgpAlarms = getBgpAlarms();
932                 if (bgpAlarms != null) {
933                     bgpAlarms.clearBgpNbrDownAlarm(peerIp);
934                 }
935
936                 if (bgpUtil.isBfdEnabled()) {
937                     final BgpCounters bgpCounters = getBgpCounters();
938                     if (bgpCounters != null) {
939                         bgpCounters.clearBfdNbrCounters(peerIp);
940                     }
941                 }
942             }
943         }
944
945         @Override
946         protected void update(InstanceIdentifier<Neighbors> iid,
947                 Neighbors oldval, Neighbors newval) {
948             if (!isBGPEntityOwner()) {
949                 return;
950             }
951             //purposefully nothing to do.
952         }
953     }
954
955     public class EbgpMultihopReactor
956             extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
957             implements ClusteredDataTreeChangeListener<EbgpMultihop> {
958
959         private static final String YANG_OBJ = "ebgp-multihop ";
960
961         public EbgpMultihopReactor() {
962             super(EbgpMultihop.class, EbgpMultihopReactor.class);
963         }
964
965         @Override
966         protected void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
967             if (!isBGPEntityOwner()) {
968                 return;
969             }
970             LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
971             synchronized (BgpConfigurationManager.this) {
972                 String peerIp = val.getPeerIp().getValue();
973                 BgpRouter br = getClient(YANG_OBJ);
974                 if (br == null) {
975                     LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
976                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
977                     return;
978                 }
979                 try {
980                     br.addEbgpMultihop(peerIp, val.getNhops().intValue());
981                 } catch (TException | BgpRouterException e) {
982                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
983                 }
984             }
985         }
986
987         @Override
988         protected EbgpMultihopReactor getDataTreeChangeListener() {
989             return EbgpMultihopReactor.this;
990         }
991
992         @Override
993         protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
994             return InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class)
995                     .child(EbgpMultihop.class);
996         }
997
998         @Override
999         protected void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
1000             if (!isBGPEntityOwner()) {
1001                 return;
1002             }
1003             LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
1004             synchronized (BgpConfigurationManager.this) {
1005                 String peerIp = val.getPeerIp().getValue();
1006                 BgpRouter br = getClient(YANG_OBJ);
1007                 if (br == null) {
1008                     LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
1009                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1010                     return;
1011                 }
1012                 try {
1013                     br.delEbgpMultihop(peerIp);
1014                 } catch (TException | BgpRouterException e) {
1015                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1016                 }
1017             }
1018         }
1019
1020         @Override
1021         protected void update(InstanceIdentifier<EbgpMultihop> iid,
1022                 EbgpMultihop oldval, EbgpMultihop newval) {
1023             if (!isBGPEntityOwner()) {
1024                 return;
1025             }
1026             LOG.error(YANG_OBJ + UPD_WARN);
1027         }
1028     }
1029
1030     public class UpdateSourceReactor
1031             extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
1032             implements ClusteredDataTreeChangeListener<UpdateSource> {
1033
1034         private static final String YANG_OBJ = "update-source ";
1035
1036         public UpdateSourceReactor() {
1037             super(UpdateSource.class, UpdateSourceReactor.class);
1038         }
1039
1040         @Override
1041         protected void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
1042             if (!isBGPEntityOwner()) {
1043                 return;
1044             }
1045             LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
1046             synchronized (BgpConfigurationManager.this) {
1047                 String peerIp = val.getPeerIp().getValue();
1048                 BgpRouter br = getClient(YANG_OBJ);
1049                 if (br == null) {
1050                     LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
1051                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1052                     return;
1053                 }
1054                 try {
1055                     br.addUpdateSource(peerIp, val.getSourceIp().getValue());
1056                 } catch (TException | BgpRouterException e) {
1057                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1058                 }
1059             }
1060         }
1061
1062         @Override
1063         protected UpdateSourceReactor getDataTreeChangeListener() {
1064             return UpdateSourceReactor.this;
1065         }
1066
1067         @Override
1068         protected InstanceIdentifier<UpdateSource> getWildCardPath() {
1069             return InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class)
1070                     .child(UpdateSource.class);
1071         }
1072
1073         @Override
1074         protected void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
1075             if (!isBGPEntityOwner()) {
1076                 return;
1077             }
1078             LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
1079             synchronized (BgpConfigurationManager.this) {
1080                 String peerIp = val.getPeerIp().getValue();
1081                 BgpRouter br = getClient(YANG_OBJ);
1082                 if (br == null) {
1083                     LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
1084                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1085                     return;
1086                 }
1087                 try {
1088                     br.delUpdateSource(peerIp);
1089                 } catch (TException | BgpRouterException e) {
1090                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1091                 }
1092             }
1093         }
1094
1095         @Override
1096         protected void update(InstanceIdentifier<UpdateSource> iid,
1097                 UpdateSource oldval, UpdateSource newval) {
1098             if (!isBGPEntityOwner()) {
1099                 return;
1100             }
1101             LOG.error(YANG_OBJ + UPD_WARN);
1102         }
1103     }
1104
1105     public class AddressFamiliesReactor
1106             extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
1107             implements ClusteredDataTreeChangeListener<AddressFamilies> {
1108
1109         private static final String YANG_OBJ = "address-families ";
1110
1111         public AddressFamiliesReactor() {
1112             super(AddressFamilies.class, AddressFamiliesReactor.class);
1113         }
1114
1115         @Override
1116         protected void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1117             if (!isBGPEntityOwner()) {
1118                 return;
1119             }
1120             LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
1121             synchronized (BgpConfigurationManager.this) {
1122                 String peerIp = val.getPeerIp().getValue();
1123                 BgpRouter br = getClient(YANG_OBJ);
1124                 if (br == null) {
1125                     LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
1126                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1127                     return;
1128                 }
1129                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1130                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1131                 try {
1132                     br.addAddressFamily(peerIp, afi, safi);
1133                 } catch (TException | BgpRouterException e) {
1134                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1135                 }
1136             }
1137         }
1138
1139         @Override
1140         protected AddressFamiliesReactor getDataTreeChangeListener() {
1141             return AddressFamiliesReactor.this;
1142         }
1143
1144         @Override
1145         protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
1146             return InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class)
1147                     .child(AddressFamilies.class);
1148         }
1149
1150         @Override
1151         protected void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
1152             if (!isBGPEntityOwner()) {
1153                 return;
1154             }
1155             LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
1156             synchronized (BgpConfigurationManager.this) {
1157                 String peerIp = val.getPeerIp().getValue();
1158                 BgpRouter br = getClient(YANG_OBJ);
1159                 if (br == null) {
1160                     LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
1161                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1162                     return;
1163                 }
1164                 af_afi afi = af_afi.findByValue(val.getAfi().intValue());
1165                 af_safi safi = af_safi.findByValue(val.getSafi().intValue());
1166                 try {
1167                     br.delAddressFamily(peerIp, afi, safi);
1168                 } catch (TException | BgpRouterException e) {
1169                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1170                 }
1171             }
1172         }
1173
1174         @Override
1175         protected void update(InstanceIdentifier<AddressFamilies> iid,
1176                 AddressFamilies oldval, AddressFamilies newval) {
1177             if (!isBGPEntityOwner()) {
1178                 return;
1179             }
1180             LOG.error(YANG_OBJ + UPD_WARN);
1181         }
1182     }
1183
1184     public class NetworksReactor
1185             extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
1186             implements ClusteredDataTreeChangeListener<Networks> {
1187
1188         private static final String YANG_OBJ = "networks ";
1189
1190         public NetworksReactor() {
1191             super(Networks.class, NetworksReactor.class);
1192         }
1193
1194         @Override
1195         public NetworksReactor getDataTreeChangeListener() {
1196             return NetworksReactor.this;
1197         }
1198
1199         @Override
1200         protected void add(InstanceIdentifier<Networks> iid, Networks val) {
1201             if (!isBGPEntityOwner()) {
1202                 return;
1203             }
1204             LOG.debug("received add Networks config val {}", val.getPrefixLen());
1205             synchronized (BgpConfigurationManager.this) {
1206                 String rd = val.getRd();
1207                 String pfxlen = val.getPrefixLen();
1208                 String nh = val.getNexthop().getValue();
1209                 BgpRouter br = getClient(YANG_OBJ);
1210                 if (br == null) {
1211                     LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {} {}", YANG_OBJ, rd, pfxlen,
1212                             nh, BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1213                     return;
1214                 }
1215                 Long label = val.getLabel().toJava();
1216                 int lbl = label == null ? qbgpConstants.LBL_NO_LABEL
1217                         : label.intValue();
1218                 int l3vni = val.getL3vni() == null ? qbgpConstants.LBL_NO_LABEL
1219                         : val.getL3vni().intValue();
1220                 int l2vni = val.getL2vni() == null ? qbgpConstants.LBL_NO_LABEL
1221                         : val.getL2vni().intValue();
1222
1223                 BgpControlPlaneType protocolType = val.getBgpControlPlaneType();
1224                 int ethernetTag = val.getEthtag().intValue();
1225                 String esi = val.getEsi();
1226                 String macaddress = val.getMacaddress();
1227                 EncapType encapType = val.getEncapType();
1228                 String routerMac = val.getRoutermac();
1229
1230                 try {
1231                     br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni, BgpUtil.convertToThriftProtocolType(protocolType),
1232                             ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
1233                 } catch (TException | BgpRouterException e) {
1234                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1235                 }
1236             }
1237         }
1238
1239         @Override
1240         protected InstanceIdentifier<Networks> getWildCardPath() {
1241             return InstanceIdentifier.create(Bgp.class).child(NetworksContainer.class).child(Networks.class);
1242         }
1243
1244         @Override
1245         protected void remove(InstanceIdentifier<Networks> iid, Networks val) {
1246             if (!isBGPEntityOwner()) {
1247                 return;
1248             }
1249             LOG.debug("received remove Networks config val {}", val.getPrefixLen());
1250             synchronized (BgpConfigurationManager.this) {
1251                 String rd = val.getRd();
1252                 String pfxlen = val.getPrefixLen();
1253                 BgpRouter br = getClient(YANG_OBJ);
1254                 if (br == null) {
1255                     LOG.debug("{} Unable to process remove for rd {} prefix {}; {} {}", YANG_OBJ, rd, pfxlen,
1256                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1257                     return;
1258                 }
1259                 Long label = val.getLabel().toJava();
1260                 int lbl = label == null ? 0 : label.intValue();
1261                 if (rd == null && lbl > 0) {
1262                     //LU prefix is being deleted.
1263                     rd = Integer.toString(lbl);
1264                 }
1265                 try {
1266                     br.delPrefix(rd, pfxlen);
1267                 } catch (TException | BgpRouterException e) {
1268                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1269                 }
1270             }
1271         }
1272
1273         /**get the value AFI from a prefix as "x.x.x.x/x".
1274          *
1275          * @param pfxlen the prefix to get an afi
1276          * @return the afi value as you are need
1277          */
1278         public  int  testValueAFI(String pfxlen) {
1279             int afiNew = af_afi.AFI_IP.getValue();
1280             try {
1281                 String ipOnly = pfxlen.substring(0, pfxlen.lastIndexOf("/"));
1282                 java.net.Inet6Address.getByName(ipOnly);
1283                 afiNew = af_afi.AFI_IPV6.getValue();
1284             } catch (java.net.UnknownHostException e) {
1285                 //ce n'est pas de l'ipv6
1286             }
1287             return afiNew;
1288         }
1289
1290
1291         @Override
1292         protected void update(final InstanceIdentifier<Networks> iid,
1293                 final Networks oldval, final Networks newval) {
1294             if (!isBGPEntityOwner()) {
1295                 return;
1296             }
1297             if (oldval.equals(newval)) {
1298                 //Update: OLD and New values are same, no need to trigger remove/add.
1299                 LOG.debug("received Updated for the same OLD and New values. RD: {}, Prefix: {}, Label: {}, NH: {}",
1300                         oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop());
1301                 return;
1302             }
1303             LOG.debug("update networks old val RD: {}, Prefix: {}, Label: {}, NH: {} "
1304                             + "new val RD: {}, Prefix: {}, Label: {}, NH: {}",
1305                     oldval.getRd(), oldval.getPrefixLen(), oldval.getLabel(), oldval.getNexthop(),
1306                     newval.getRd(), newval.getPrefixLen(), newval.getLabel(), newval.getNexthop());
1307             remove(iid, oldval);
1308             add(iid, newval);
1309         }
1310     }
1311
1312     static Timer timer = new Timer();
1313
1314     public class VrfsReactor
1315             extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
1316             implements ClusteredDataTreeChangeListener<Vrfs> {
1317
1318         private static final String YANG_OBJ = "vrfs ";
1319
1320         public VrfsReactor() {
1321             super(Vrfs.class, VrfsReactor.class);
1322         }
1323
1324         @Override
1325         protected void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
1326             if (!isBGPEntityOwner()) {
1327                 return;
1328             }
1329             LOG.debug("received add Vrfs config value {}", vrfs.getRd());
1330             synchronized (BgpConfigurationManager.this) {
1331                 String rd = vrfs.getRd();
1332                 BgpRouter br = getClient(YANG_OBJ);
1333                 if (br == null) {
1334                     LOG.debug("{} Unable to process add for rd {}; {} {}", YANG_OBJ, rd,
1335                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1336                     return;
1337                 }
1338                 try {
1339                     List<AddressFamiliesVrf> vrfAddrFamilyList = vrfs.getAddressFamiliesVrf();
1340                     for (AddressFamiliesVrf vrfAddrFamily : vrfAddrFamilyList) {
1341                         /*add to br the new vrfs arguments*/
1342                         br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(),
1343                                 vrfs.getExportRts(), vrfAddrFamily.getAfi().toJava(), vrfAddrFamily.getSafi().toJava());
1344                     }
1345                     /*add to br the vrfs contained in mapNewAdFamily*/
1346                     List<AddressFamiliesVrf> vrfAddrFamilyListFromMap = mapNewAdFamily.get(rd);
1347                     if (vrfAddrFamilyListFromMap == null) {
1348                         return;
1349                     }
1350
1351                     for (AddressFamiliesVrf adf : vrfAddrFamilyListFromMap) {
1352                         if (vrfAddrFamilyList.contains(adf)) {
1353                             mapNewAdFamily.remove(rd);
1354                         } else  if (adf != null) {
1355
1356                             br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(),
1357                                     vrfs.getExportRts(), adf.getAfi().toJava(), adf.getSafi().toJava());
1358                             // remove AddressFamiliesVrf which was already added to BGP
1359                             vrfAddrFamilyListFromMap.remove(adf);
1360                             if (vrfAddrFamilyListFromMap.isEmpty()) {
1361                                 // remove Vrf entry from temp mapNewAdFamily if all its AddressFamiliesVrf was
1362                                 // added to BGP
1363                                 mapNewAdFamily.remove(rd);
1364                             }
1365                         }
1366                     }
1367                 } catch (TException | BgpRouterException e) {
1368                     LOG.error("{} get {}, Add received exception", YANG_OBJ, ADD_WARN, e);
1369                 }
1370             }
1371         }
1372
1373         @Override
1374         protected VrfsReactor getDataTreeChangeListener() {
1375             return VrfsReactor.this;
1376         }
1377
1378         @Override
1379         protected InstanceIdentifier<Vrfs> getWildCardPath() {
1380             return InstanceIdentifier.create(Bgp.class).child(VrfsContainer.class).child(Vrfs.class);
1381         }
1382
1383         @Override
1384         protected void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
1385             if (!isBGPEntityOwner()) {
1386                 return;
1387             }
1388             LOG.debug("received remove Vrfs config val {}", val.getRd());
1389             synchronized (BgpConfigurationManager.this) {
1390                 String rd = val.getRd();
1391                 BgpRouter br = getClient(YANG_OBJ);
1392                 if (br == null) {
1393                     LOG.debug("{} Unable to process remove for rd {}; {} {}", YANG_OBJ, rd,
1394                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
1395                     return;
1396                 }
1397                 try {
1398                     List<AddressFamiliesVrf> adf = mapNewAdFamily.get(rd);
1399                     adf = adf != null ? adf : new ArrayList<>();
1400                     for (AddressFamiliesVrf s : val.getAddressFamiliesVrf()) {
1401                         br.delVrf(rd, s.getAfi().toJava(), s.getSafi().toJava());
1402                         adf.remove(s);// remove in the map the vrf in waiting for advertise quagga
1403                     }
1404                     if (adf.isEmpty()) {
1405                         mapNewAdFamily.remove(rd);
1406                     }
1407                 } catch (TException | BgpRouterException e) {
1408                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
1409                 }
1410             }
1411         }
1412
1413         @Override
1414         protected void update(InstanceIdentifier<Vrfs> iid,
1415                 Vrfs oldval, Vrfs newval) {
1416             if (oldval != null && newval != null) {
1417                 LOG.debug("received update Vrfs config val {}, VRFS: Update getting triggered for VRFS rd {}",
1418                         newval.getRd(), oldval.getRd());
1419             } else {
1420                 LOG.debug("received update Vrfs config val {}, from old vrf {}",
1421                         newval, oldval);
1422             }
1423             if (!isBGPEntityOwner()) {
1424                 return;
1425             }
1426
1427             List<AddressFamiliesVrf> adFamilyVrfToDel = new ArrayList<>();
1428             List<AddressFamiliesVrf> adFamilyVrfToAdd = new ArrayList<>();
1429             List<AddressFamiliesVrf> oldlistAdFamilies = new ArrayList<>();
1430             List<AddressFamiliesVrf> newlistAdFamilies = new ArrayList<>();
1431             if (oldval != null) {
1432                 oldlistAdFamilies = oldval.getAddressFamiliesVrf() == null
1433                         ? new ArrayList<>() : oldval.getAddressFamiliesVrf();
1434             }
1435             if (newval != null) {
1436                 newlistAdFamilies = newval.getAddressFamiliesVrf() == null
1437                         ? new ArrayList<>() : newval.getAddressFamiliesVrf();
1438             }
1439             /*find old AddressFamily to remove from new configuration*/
1440             for (AddressFamiliesVrf adVrf : oldlistAdFamilies) {
1441                 if (!newlistAdFamilies.contains(adVrf)) {
1442                     adFamilyVrfToDel.add(adVrf);
1443                 }
1444             }
1445             /*find new AddressFamily to add to unexisting configuration*/
1446             for (AddressFamiliesVrf adVrf : newlistAdFamilies) {
1447                 if (!oldlistAdFamilies.contains(adVrf)) {
1448                     adFamilyVrfToAdd.add(adVrf);
1449                 }
1450             }
1451             String rd = newval != null ? newval.getRd() : null;
1452             if (rd != null) {
1453                 BgpRouter br = getClient(YANG_OBJ);
1454                 if (br == null) {
1455                     LOG.debug("{} Unable to process add for rd {}; {} {}", YANG_OBJ, rd,
1456                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1457                     return;
1458                 }
1459
1460                 for (AddressFamiliesVrf adfvrf : adFamilyVrfToAdd) {
1461                     try {
1462                         LOG.debug("call addVRf rd {} afi {} safi {}", rd, adfvrf.getAfi(), adfvrf.getSafi());
1463                         br.addVrf(BgpUtil.getLayerType(adfvrf), rd, newval.getImportRts(),
1464                                 newval.getExportRts(),adfvrf.getAfi().toJava(), adfvrf.getSafi().toJava());
1465                     } catch (TException | BgpRouterException e) {
1466                         LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
1467                     }
1468                 }
1469
1470                 for (AddressFamiliesVrf adfToDel : adFamilyVrfToDel) {
1471                     try {
1472                         LOG.debug("call delVRf rd {} afi {} safi {}", rd, adfToDel.getAfi(), adfToDel.getSafi());
1473                         br.delVrf(rd, adfToDel.getAfi().toJava(), adfToDel.getSafi().toJava());
1474                     } catch (TException | BgpRouterException e) {
1475                         LOG.error("{} delVrf received exception; {}", YANG_OBJ, ADD_WARN, e);
1476                     }
1477                 }
1478             }
1479         }
1480     }
1481
1482     public class BgpReactor
1483             extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
1484             implements ClusteredDataTreeChangeListener<Bgp> {
1485
1486         private static final String YANG_OBJ = "Bgp ";
1487
1488         public BgpReactor() {
1489             super(Bgp.class, BgpReactor.class);
1490         }
1491
1492
1493         @Override
1494         protected void add(InstanceIdentifier<Bgp> iid, Bgp val) {
1495             LOG.debug("received add Bgp config");
1496
1497             try {
1498                 initer.await();
1499             } catch (InterruptedException e) {
1500                 // Ignored
1501             }
1502             synchronized (BgpConfigurationManager.this) {
1503                 config = val;
1504                 if (!isBGPEntityOwner()) {
1505                     return;
1506                 }
1507             }
1508         }
1509
1510         @Override
1511         protected BgpReactor getDataTreeChangeListener() {
1512             return BgpReactor.this;
1513         }
1514
1515         @Override
1516         protected InstanceIdentifier<Bgp> getWildCardPath() {
1517             return InstanceIdentifier.create(Bgp.class);
1518         }
1519
1520         @Override
1521         protected void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
1522             if (!isBGPEntityOwner()) {
1523                 return;
1524             }
1525             LOG.debug("received remove Bgp config");
1526
1527             config = null;
1528         }
1529
1530         @Override
1531         protected void update(InstanceIdentifier<Bgp> iid,
1532                 Bgp oldval, Bgp newval) {
1533             if (!isBGPEntityOwner()) {
1534                 return;
1535             }
1536
1537             config = newval;
1538         }
1539     }
1540
1541     @SuppressWarnings("deprecation")
1542     public class MultipathReactor
1543             extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
1544             implements ClusteredDataTreeChangeListener<Multipath> {
1545
1546         private static final String YANG_OBJ = "multipath ";
1547
1548         public MultipathReactor() {
1549             super(Multipath.class, MultipathReactor.class);
1550         }
1551
1552
1553         @Override
1554         protected MultipathReactor getDataTreeChangeListener() {
1555             return MultipathReactor.this;
1556         }
1557
1558         @Override
1559         protected InstanceIdentifier<Multipath> getWildCardPath() {
1560             return InstanceIdentifier.create(Bgp.class).child(MultipathContainer.class).child(Multipath.class);
1561         }
1562
1563         @Override
1564         protected void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
1565             executor.execute(new MultipathStatusChange(val));
1566         }
1567
1568         @Override
1569         protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
1570             executor.execute(new MultipathStatusChange(newval));
1571         }
1572
1573         @Override
1574         protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
1575             executor.execute(new MultipathStatusChange(dataObjectModification));
1576         }
1577
1578         class MultipathStatusChange implements Runnable {
1579
1580             Multipath multipath;
1581
1582             MultipathStatusChange(Multipath multipath) {
1583                 this.multipath = multipath;
1584             }
1585
1586             @Override
1587             public void run() {
1588                 if (isBGPEntityOwner()) {
1589                     synchronized (BgpConfigurationManager.this) {
1590
1591                         BgpRouter br = getClient(YANG_OBJ);
1592
1593                         if (br != null) {
1594                             af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
1595                             af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
1596
1597                             try {
1598                                 if (multipath.isMultipathEnabled()) {
1599                                     br.enableMultipath(afi, safi);
1600                                 } else {
1601                                     br.disableMultipath(afi, safi);
1602                                 }
1603                             } catch (TException | BgpRouterException e) {
1604                                 LOG.error("{} received exception", YANG_OBJ, e);
1605                             }
1606                         }
1607                     }
1608                 }
1609             }
1610
1611         }
1612
1613         @Override
1614         public void close() {
1615             super.close();
1616         }
1617     }
1618
1619     @SuppressWarnings("deprecation")
1620     public class VrfMaxpathReactor
1621             extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
1622             implements ClusteredDataTreeChangeListener<VrfMaxpath> {
1623
1624         private static final String YANG_OBJ = "vrfMaxpath ";
1625
1626         public VrfMaxpathReactor() {
1627             super(VrfMaxpath.class, VrfMaxpathReactor.class);
1628         }
1629
1630
1631         @Override
1632         protected VrfMaxpathReactor getDataTreeChangeListener() {
1633             return VrfMaxpathReactor.this;
1634         }
1635
1636         @Override
1637         protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
1638             return InstanceIdentifier.create(Bgp.class).child(VrfMaxpathContainer.class).child(VrfMaxpath.class);
1639         }
1640
1641         class VrfMaxPathConfigurator implements Runnable {
1642
1643             VrfMaxpath vrfMaxpathVal;
1644
1645             VrfMaxPathConfigurator(VrfMaxpath vrfMaxPathVal) {
1646                 this.vrfMaxpathVal = vrfMaxPathVal;
1647             }
1648
1649             @Override
1650             public void run() {
1651                 if (isBGPEntityOwner()) {
1652                     synchronized (BgpConfigurationManager.this) {
1653                         BgpRouter br = getClient(YANG_OBJ);
1654                         if (br != null) {
1655                             try {
1656                                 br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths().toJava());
1657                                 LOG.debug("Maxpath for vrf {} is {}", vrfMaxpathVal.getRd(),
1658                                         vrfMaxpathVal.getMaxpaths());
1659                             } catch (TException | BgpRouterException e) {
1660                                 LOG.error("{} received exception", YANG_OBJ, e);
1661                             }
1662                         }
1663                     }
1664                 }
1665             }
1666         }
1667
1668         @Override
1669         protected void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
1670             if (isBGPEntityOwner()) {
1671                 synchronized (BgpConfigurationManager.this) {
1672                     BgpRouter br = getClient(YANG_OBJ);
1673                     if (br != null) {
1674                         try {
1675                             br.multipaths(vrfMaxPathVal.getRd(), BgpConstants.BGP_DEFAULT_MULTIPATH);
1676                             LOG.debug("Del Maxpath for vrf: {} ", vrfMaxPathVal.getRd());
1677                         } catch (TException | BgpRouterException e) {
1678                             LOG.error(YANG_OBJ + " del received exception:", e);
1679                         }
1680                     }
1681                 }
1682             }
1683         }
1684
1685         @Override
1686         protected void update(InstanceIdentifier<VrfMaxpath> iid,
1687                               VrfMaxpath oldval, VrfMaxpath newval) {
1688             if (!Objects.equals(oldval.getMaxpaths(), newval.getMaxpaths())) {
1689                 executor.execute(new VrfMaxPathConfigurator(newval));
1690             }
1691         }
1692
1693         @Override
1694         protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
1695             executor.execute(new VrfMaxPathConfigurator(vrfMaxpathVal));
1696         }
1697
1698         @Override
1699         public void close() {
1700             super.close();
1701         }
1702     }
1703
1704     public class BfdConfigReactor
1705             extends AsyncDataTreeChangeListenerBase<BfdConfig, BfdConfigReactor>
1706             implements ClusteredDataTreeChangeListener<BfdConfig> {
1707
1708         private static final String YANG_OBJ = "BfdConfig ";
1709
1710         public BfdConfigReactor() {
1711             super(BfdConfig.class, BfdConfigReactor.class);
1712         }
1713
1714         @Override
1715         protected void add(InstanceIdentifier<BfdConfig> iid, BfdConfig val) {
1716             if (!isBGPEntityOwner()) {
1717                 return;
1718             }
1719             BgpRouter br = getClient(YANG_OBJ);
1720             LOG.debug("received bfd config: bfd enabled {} min-rx {} min-tx {} detect-mul {} mhop {}",
1721                     val.isBfdEnabled(), val.getMinRx(), val.getMinTx(),
1722                     val.getDetectMult(), val.isMultihop());
1723             if (br == null) {
1724                 LOG.debug(YANG_OBJ + "{} Unable to process add  {}",
1725                         BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1726                 return;
1727             }
1728             if (val.isBfdEnabled() == false) {
1729                 LOG.debug("BFD not enabled. Ignoring the config add");
1730                 return;
1731             }
1732             int minRx = val.getMinRx().intValue();
1733             int minTx = val.getMinTx().intValue();
1734             int detectMult = val.getDetectMult().intValue();
1735             boolean multiHop = val.isMultihop();
1736             try {
1737                 br.addBfd(detectMult, minRx, minTx,multiHop);
1738             } catch (TException | BgpRouterException e) {
1739                 LOG.error("{} get {}, Add received exception;", YANG_OBJ, ADD_WARN, e);
1740             }
1741         }
1742
1743         @Override
1744         protected BfdConfigReactor getDataTreeChangeListener() {
1745             return BfdConfigReactor.this;
1746         }
1747
1748         @Override
1749         protected InstanceIdentifier<BfdConfig> getWildCardPath() {
1750             return InstanceIdentifier.create(BfdConfig.class);
1751         }
1752
1753         @Override
1754         protected void remove(InstanceIdentifier<BfdConfig> iid, BfdConfig val) {
1755             if (!isBGPEntityOwner()) {
1756                 return;
1757             }
1758             LOG.debug("received bfd config removal");
1759             BgpRouter br = getClient(YANG_OBJ);
1760             if (br == null) {
1761                 LOG.debug("{} Unable to process del {}  {}", YANG_OBJ,
1762                         BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
1763                 return;
1764             }
1765             try {
1766                 br.delBfd();
1767             } catch (TException | BgpRouterException e) {
1768                 LOG.error("{} get {}, Del received exception;", YANG_OBJ, ADD_WARN, e);
1769             }
1770
1771         }
1772
1773         @Override
1774         protected void update(InstanceIdentifier<BfdConfig> iid,
1775                               BfdConfig oldval, BfdConfig newval) {
1776             LOG.debug("received bfd config: updated oldval bfd enabled {}"
1777                     + "min-rx {} min-tx {} detect-mul {} mhop {}",
1778                     oldval.isBfdEnabled(), oldval.getMinRx(), oldval.getMinTx(),
1779                     oldval.getDetectMult(), oldval.isMultihop());
1780             LOG.debug("received bfd config: updated newval bfd enabled {}"
1781                     + "min-rx {} min-tx {} detect-mul {} mhop {}",
1782                     newval.isBfdEnabled(), newval.getMinRx(), newval.getMinTx(),
1783                     newval.getDetectMult(), newval.isMultihop());
1784             if (oldval.isBfdEnabled()) {
1785                 LOG.debug("deleting bfd config on an update");
1786                 remove(iid, oldval);
1787             }
1788             LOG.debug("adding bfd config on an update");
1789             add(iid, newval);
1790         }
1791     }
1792
1793
1794     public boolean isIpAvailable(String odlip) {
1795
1796         try {
1797             if (odlip != null) {
1798                 if ("127.0.0.1".equals(odlip)) {
1799                     return true;
1800                 }
1801                 Enumeration<NetworkInterface> networkInterfaceEnumeration = NetworkInterface.getNetworkInterfaces();
1802                 while (networkInterfaceEnumeration.hasMoreElements()) {
1803                     NetworkInterface networkInterface = networkInterfaceEnumeration.nextElement();
1804                     Enumeration<InetAddress>  inetAddressEnumeration = networkInterface.getInetAddresses();
1805                     while (inetAddressEnumeration.hasMoreElements()) {
1806                         InetAddress inetAddress = inetAddressEnumeration.nextElement();
1807                         if (odlip.equals(inetAddress.getHostAddress())) {
1808                             return true;
1809                         }
1810                     }
1811                 }
1812             }
1813         } catch (SocketException e) {
1814             // Ignored?
1815         }
1816         return false;
1817     }
1818
1819     public long getStalePathtime(int defValue, AsId asId) {
1820         long spt = 0;
1821         try {
1822             spt = getConfig().getGracefulRestart().getStalepathTime().toJava();
1823         } catch (NullPointerException e) {
1824             try {
1825                 spt = asId.getStalepathTime().toJava();
1826                 LOG.trace("BGP config/Stale-path time is not set using graceful");
1827             } catch (NullPointerException ignore) {
1828                 LOG.trace("BGP AS id is not set using graceful");
1829                 spt = defValue;
1830             }
1831         }
1832         if (spt == 0) {
1833             LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
1834             spt = defValue;
1835         }
1836         return spt;
1837     }
1838
1839     public static boolean isValidConfigBgpHostPort(String bgpHost, int bgpPort) {
1840         if (!bgpHost.equals(DEF_CHOST)) {
1841             return true;
1842         } else {
1843             return false;
1844         }
1845     }
1846
1847     public synchronized void bgpRestarted() {
1848         /*
1849          * If there a thread which in the process of stale cleanup, cancel it
1850          * and start a new thread (to avoid processing same again).
1851          */
1852         if (previousReplayJobInProgress()) {
1853             cancelPreviousReplayJob();
1854         }
1855         Runnable task = () -> {
1856             try {
1857                 LOG.info("running bgp replay task ");
1858                 if (get() == null) {
1859                     String host = getConfigHost();
1860                     int port = getConfigPort();
1861                     LOG.info("connecting  to bgp host {} ", host);
1862                     bgpRouter.connect(host, port);
1863                     LOG.info("no config to push in bgp replay task ");
1864                     return;
1865                 }
1866                 setStaleStartTime(System.currentTimeMillis());
1867                 LOG.info("started creating stale fibDSWriter  map ");
1868                 createStaleFibMap();
1869                 setStaleEndTime(System.currentTimeMillis());
1870                 LOG.info("took {} msecs for stale fibDSWriter map creation ", getStaleEndTime() - getStaleStartTime());
1871                 LOG.info("started bgp config replay ");
1872                 setCfgReplayStartTime(System.currentTimeMillis());
1873                 boolean replaySucceded = replay();
1874                 setCfgReplayEndTime(System.currentTimeMillis());
1875                 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
1876                 if (replaySucceded) {
1877                     long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
1878                     setStaleCleanupTime(routeSyncTime);
1879                     LOG.error("starting the stale cleanup timer: {} seconds", routeSyncTime);
1880                     routeCleanupFuture = executor.schedule(new RouteCleanup(), routeSyncTime, TimeUnit.SECONDS);
1881                 } else {
1882                     LOG.error("skipping stale cleanup, may be due to exception while replay");
1883                     staledFibEntriesMap.clear();
1884                 }
1885             } catch (InterruptedException | TimeoutException | ExecutionException eCancel) {
1886                 LOG.error("Stale Cleanup Task Cancelled", eCancel);
1887             }
1888         };
1889         lastReplayJobFt = executor.submit(task);
1890     }
1891
1892     private boolean previousReplayJobInProgress() {
1893         return ((lastReplayJobFt != null && !lastReplayJobFt.isDone())
1894                 || (routeCleanupFuture != null && !routeCleanupFuture.isDone()));
1895     }
1896
1897     private void cancelPreviousReplayJob() {
1898         try {
1899             LOG.error("cancelling already running bgp replay task");
1900             if (lastReplayJobFt != null) {
1901                 lastReplayJobFt.cancel(true);
1902                 lastReplayJobFt = null;
1903                 staledFibEntriesMap.clear();
1904             }
1905             if (routeCleanupFuture != null) {
1906                 routeCleanupFuture.cancel(true);
1907                 routeCleanupFuture = null;
1908                 staledFibEntriesMap.clear();
1909             }
1910             Thread.sleep(2000);
1911         } catch (InterruptedException e) {
1912             LOG.error("Failed to cancel previous replay job ", e);
1913         }
1914     }
1915
1916     private void doRouteSync() {
1917         for (af_afi afi : af_afi.values()) {
1918             try {
1919                 bgpRouter.initRibSync(bgpSyncHandle);
1920             } catch (BgpRouterException e) {
1921                 LOG.error("Route sync aborted, exception when initializing", e);
1922                 return;
1923             }
1924             LOG.error("Starting BGP route sync for afi {}", afi.getValue());
1925             while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
1926                 Routes routes = null;
1927                 int noUpdates = 0;
1928                 try {
1929                     routes = bgpRouter.doRibSync(bgpSyncHandle, afi);
1930                 } catch (TException | BgpRouterException e) {
1931                     LOG.error("Route sync aborted, exception when syncing", e);
1932                     return;
1933                 }
1934                 Iterator<Update> updates = routes.getUpdatesIterator();
1935                 while (updates.hasNext()) {
1936                     noUpdates++;
1937                     Update update = updates.next();
1938                     String rd = update.getRd();
1939                     String nexthop = update.getNexthop();
1940
1941                     // TODO: decide correct label here
1942                     int label = update.getL3label();
1943                     int l2label = update.getL2label();
1944
1945                     String prefix = update.getPrefix();
1946                     int plen = update.getPrefixlen();
1947
1948
1949                     // TODO: protocol type will not be available in "update"
1950                     // use "rd" to query vrf table and obtain the protocol_type.
1951                     // Currently using PROTOCOL_EVPN as default.
1952                     onUpdatePushRoute(
1953                            protocol_type.PROTOCOL_L3VPN,
1954                            rd,
1955                            prefix,
1956                            plen,
1957                            nexthop,
1958                            update.getMacaddress(),
1959                            Uint32.valueOf(label),
1960                            Uint32.valueOf(l2label),
1961                            update.getRoutermac(),
1962                            afi);
1963                 }
1964                 LOG.error("No of updates for afi {} is {}", afi.getValue(), noUpdates);
1965             }
1966         }
1967         try {
1968             LOG.error("Ending BGP route-sync");
1969             bgpRouter.endRibSync(bgpSyncHandle);
1970         } catch (BgpRouterException e) {
1971             LOG.error("Route sync aborted, exception when ending", e);
1972         }
1973     }
1974
1975     public void addTepToElanDS(String rd, String tepIp, String mac, Uint32 l2vni) {
1976         boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
1977         if (needUpdate) {
1978             LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
1979             bgpUtil.addTepToElanInstance(rd, tepIp);
1980         } else {
1981             LOG.debug("Skipping the Elan update for RT2 from tep {} rd {}", tepIp, rd);
1982         }
1983     }
1984
1985     public void deleteTepfromElanDS(String rd, String tepIp, String mac) {
1986         boolean needUpdate = deleteFromRt2TepMap(rd, tepIp, mac);
1987         if (needUpdate) {
1988             LOG.info("Deleting tepIp {} with RD {} to ELan DS", tepIp, rd);
1989             bgpUtil.deleteTepFromElanInstance(rd, tepIp);
1990         } else {
1991             LOG.debug("Skipping the Elan update for RT2 withdraw from tep {} rd {}", tepIp, rd);
1992         }
1993     }
1994
1995     /* onUpdatePushRoute
1996      * Get Stale fibDSWriter map, and compare current route/fibDSWriter entry.
1997      *  - Entry compare shall include NextHop, Label.
1998      *  - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
1999      *  - If entry not found, add to FIB Config DS.
2000      *  - If entry found, but either Label/NextHop doesn't match.
2001      *      - Update FIB Config DS with modified values.
2002      *      - delete from Stale Map.
2003      */
2004
2005     public void onUpdatePushRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
2006                                   String macaddress, Uint32 label, Uint32 l2label, String routermac, af_afi afi) {
2007         PrefixUpdateEvent prefixUpdateEvent = new PrefixUpdateEvent(protocolType,rd,prefix,plen,nextHop,
2008                 macaddress,label,l2label,routermac,afi);
2009         bgpUpdatesHistory.addToHistory(TransactionType.ADD, prefixUpdateEvent);
2010         boolean addroute = false;
2011         boolean macupdate = false;
2012         Uint32 l3vni = Uint32.ZERO;
2013         VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
2014         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
2015             encapType = VrfEntry.EncapType.Vxlan;
2016             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
2017             if (vpnInstanceOpDataEntry != null) {
2018                 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
2019                     LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
2020                             vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
2021                     addTepToElanDS(rd, nextHop, macaddress, l2label);
2022                     macupdate = true;
2023                 } else {
2024                     l3vni = vpnInstanceOpDataEntry.getL3vni();
2025                 }
2026             } else {
2027                 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
2028                 return;
2029             }
2030         }
2031
2032         if (!staledFibEntriesMap.isEmpty()) {
2033             // restart Scenario, as MAP is not empty.
2034             Map<String, Uint32> map = staledFibEntriesMap.get(rd);
2035             if (map != null) {
2036                 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
2037                 Uint32 labelInStaleMap = map.get(prefixNextHop);
2038                 if (null == labelInStaleMap) {
2039                     // New Entry, which happened to be added during restart.
2040                     addroute = true;
2041                 } else {
2042                     map.remove(prefixNextHop);
2043                     if (isRouteModified(label, labelInStaleMap)) {
2044                         LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
2045                         // Existing entry, where in Label got modified during restart
2046                         addroute = true;
2047                     }
2048                 }
2049             } else {
2050                 LOG.debug("rd {} map is null while processing prefix {} ", rd, prefix);
2051                 addroute = true;
2052             }
2053         } else {
2054             LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix, plen, nextHop, label);
2055             addroute = true;
2056         }
2057         if (macupdate) {
2058             LOG.info("ADD: Adding Mac Fib entry rd {} mac{} nexthop {} l2vni {}", rd, macaddress, nextHop, l2label);
2059             fibDSWriter.addMacEntryToDS(rd, macaddress, prefix, Collections.singletonList(nextHop),
2060                     encapType, l2label, routermac, RouteOrigin.BGP);
2061             LOG.info("ADD: Added Mac Fib entry rd {} prefix {} nexthop {} label {}", rd, macaddress, nextHop, l2label);
2062         } else if (addroute) {
2063             LOG.info("ADD: Adding Fib entry rd {} prefix {} nexthop {} label {} afi {}",
2064                     rd, prefix, nextHop, label, afi);
2065             // TODO: modify addFibEntryToDS signature
2066             List<String> nextHopList = Collections.singletonList(nextHop);
2067             fibDSWriter.addFibEntryToDS(rd, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
2068                                         routermac, RouteOrigin.BGP);
2069             LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
2070             String vpnName = bgpUtil.getVpnNameFromRd(rd);
2071             if (vpnName != null) {
2072                 vpnLinkService.leakRouteIfNeeded(vpnName, prefix, nextHopList, label, RouteOrigin.BGP,
2073                                                  NwConstants.ADD_FLOW);
2074             }
2075         }
2076     }
2077
2078     public void onUpdateWithdrawRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
2079             String macaddress) {
2080         PrefixWithdrawEvent prefixWithdrawEvent = new PrefixWithdrawEvent(protocolType,rd,prefix,plen,
2081                 nextHop,macaddress);
2082         bgpUpdatesHistory.addToHistory(TransactionType.ADD, prefixWithdrawEvent);
2083         boolean macupdate = false;
2084         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
2085             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
2086             if (vpnInstanceOpDataEntry != null) {
2087                 Uint32 vni = vpnInstanceOpDataEntry.getL3vni();
2088                 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
2089                     LOG.debug("Got RT2 withdraw for RD {} {} from tep {} with mac {} remote RD {}",
2090                             vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
2091                     deleteTepfromElanDS(rd, nextHop, macaddress);
2092                     LOG.debug("For rd {}. skipping fib update", rd);
2093                     macupdate = true;
2094                 }
2095             } else {
2096                 LOG.error("No corresponding vpn instance found for rd {}. Aborting.", rd);
2097                 return;
2098             }
2099         }
2100         if (macupdate) {
2101             LOG.info("Removing Mac Fib entry rd {} mac{} nexthop {} ", rd, macaddress, nextHop);
2102             fibDSWriter.removeMacEntryFromDS(rd, macaddress);
2103             LOG.info("Removed Mac Fib entry rd {} prefix {} nexthop {} ", rd, macaddress, nextHop);
2104         } else {
2105             LOG.info("REMOVE: Removing Fib entry rd {} prefix {}", rd, prefix);
2106             fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nextHop);
2107             LOG.info("REMOVE: Removed Fib entry rd {} prefix {}", rd, prefix);
2108         }
2109     }
2110
2111     //TODO: below function is for testing purpose with cli
2112     public void onUpdateWithdrawRoute(String rd, String prefix, int plen, String nexthop) {
2113         LOG.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
2114         fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
2115         String vpnName = bgpUtil.getVpnNameFromRd(rd);
2116         if (vpnName != null) {
2117             vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, Uint32.ZERO /*INVALID_LABEL*/,
2118                                              RouteOrigin.BGP, NwConstants.DEL_FLOW);
2119         }
2120     }
2121
2122     public void peerDown(String ipAddress, long asNumber) {
2123         PeerDownEvent peerDownEvent = new PeerDownEvent(ipAddress,asNumber);
2124         bgpUpdatesHistory.addToHistory(TransactionType.ADD, peerDownEvent);
2125         List<String> tepIpList = bgpUtil.getDcgwTepConfig(ipAddress);
2126         if (tepIpList == null) {
2127             LOG.error("No Tep IP configured for DCGW {} on a peerDown", ipAddress);
2128             return;
2129         }
2130         tepIpList.forEach(tepIp -> {
2131             bgpUtil.removeOrUpdateLBGroups(tepIp, NwConstants.MOD_FLOW);
2132         });
2133     }
2134
2135     public void peerUp(String ipAddress, long asNumber) {
2136         PeerUpEvent peerUpEvent = new PeerUpEvent(ipAddress,asNumber);
2137         bgpUpdatesHistory.addToHistory(TransactionType.ADD, peerUpEvent);
2138         List<String> tepIpList = bgpUtil.getDcgwTepConfig(ipAddress);
2139         if (tepIpList == null) {
2140             LOG.error("No Tep IP configured for DCGW {} on a peerUp", ipAddress);
2141             return;
2142         }
2143         tepIpList.forEach(tepIp -> {
2144             bgpUtil.removeOrUpdateLBGroups(tepIp, NwConstants.MOD_FLOW);
2145         });
2146     }
2147
2148     private static boolean isRouteModified(Uint32 label, Uint32 labelInStaleMap) {
2149         return labelInStaleMap != null && !labelInStaleMap.equals(label);
2150     }
2151
2152     static class ReplayNbr {
2153         Neighbors nbr;
2154         boolean shouldRetry = false;
2155
2156         public Neighbors getNbr() {
2157             return nbr;
2158         }
2159
2160         public boolean isShouldRetry() {
2161             return shouldRetry;
2162         }
2163
2164         public void setShouldRetry(boolean retryNbr) {
2165             this.shouldRetry = retryNbr;
2166         }
2167
2168         ReplayNbr(Neighbors nbr, boolean shouldRetry) {
2169             this.nbr = nbr;
2170             this.shouldRetry = shouldRetry;
2171         }
2172     }
2173
2174     private static boolean replayNbrConfig(List<Neighbors> neighbors, BgpRouter br) {
2175         if (neighbors == null || neighbors.isEmpty()) {
2176             LOG.error("Replaying nbr configuration, received NULL list ");
2177             return true;
2178         }
2179
2180         List<ReplayNbr> replayNbrList = new ArrayList<>();
2181         for (Neighbors nbr : neighbors) {
2182             if (nbr != null) {
2183                 replayNbrList.add(new ReplayNbr(nbr, true));
2184             }
2185         }
2186         final int numberOfNbrRetries = 3;
2187         RetryOnException nbrRetry = new RetryOnException(numberOfNbrRetries);
2188         do {
2189             for (ReplayNbr replayNbr : replayNbrList) {
2190                 if (!replayNbr.isShouldRetry()) {
2191                     continue;
2192                 }
2193                 boolean replayDone = false;
2194                 LOG.debug("Replaying addNbr {}", replayNbr.getNbr().getAddress().getValue());
2195                 replayDone = false;
2196                 try {
2197                     final String md5password = extractMd5Secret(replayNbr.getNbr());
2198                     br.addNeighbor(replayNbr.getNbr().getAddress().getValue(),
2199                             replayNbr.getNbr().getRemoteAs().longValue(), md5password);
2200                     replayDone = true;
2201                 } catch (TApplicationException tae) {
2202                     LOG.debug("Replaying addNbr {}, tapplicationexception: ",
2203                             replayNbr.getNbr().getAddress().getValue(), tae);
2204                     if (tae.getType() == BgpRouterException.BGP_ERR_PEER_EXISTS) {
2205                         LOG.debug("Replaying addNbr Neighbor already present");
2206                         replayDone = true;
2207                     } else {
2208                         LOG.error("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), tae);
2209                     }
2210                 } catch (TException | BgpRouterException eNbr) {
2211                     LOG.debug("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), eNbr);
2212                 }
2213
2214                 LOG.debug("Replay addNbr {} successful", replayNbr.getNbr().getAddress().getValue());
2215
2216                 //Update Source handling
2217                 UpdateSource us = replayNbr.getNbr().getUpdateSource();
2218                 if (us != null) {
2219                     LOG.debug("Replaying updatesource {} to peer {}", us.getSourceIp().getValue(),
2220                             us.getPeerIp().getValue());
2221                     try {
2222                         br.addUpdateSource(us.getPeerIp().getValue(),
2223                                 us.getSourceIp().getValue());
2224                     } catch (TException | BgpRouterException eUs) {
2225                         LOG.debug("Replaying UpdateSource for Nbr {}, exception:",
2226                                 replayNbr.getNbr().getAddress().getValue(), eUs);
2227                     }
2228                     LOG.debug("Replay updatesource {} successful", us.getSourceIp().getValue());
2229                 }
2230                 //Ebgp Multihope
2231                 EbgpMultihop en = replayNbr.getNbr().getEbgpMultihop();
2232                 if (en != null) {
2233                     try {
2234                         br.addEbgpMultihop(en.getPeerIp().getValue(),
2235                                 en.getNhops().intValue());
2236                     } catch (TException | BgpRouterException eEbgpMhop) {
2237                         LOG.debug("Replaying EbgpMultihop for Nbr {}, exception: ",
2238                                 replayNbr.getNbr().getAddress().getValue(), eEbgpMhop);
2239                     }
2240                 }
2241
2242                 //afs
2243                 List<AddressFamilies> afs = replayNbr.getNbr().getAddressFamilies();
2244                 if (afs != null) {
2245                     for (AddressFamilies af : afs) {
2246                         af_afi afi = af_afi.findByValue(af.getAfi().intValue());
2247                         af_safi safi = af_safi.findByValue(af.getSafi().intValue());
2248                         try {
2249                             br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
2250                         } catch (TException | BgpRouterException eAFs) {
2251                             LOG.debug("Replaying AddressFamily for Nbr {}, exception:",
2252                                     replayNbr.getNbr().getAddress().getValue(), eAFs);
2253                         }
2254                     }
2255                 }
2256                 //replay is success --> no need to replay this nbr in next iteration.
2257                 replayNbr.setShouldRetry(replayDone ? false : true);
2258             }
2259         } while (nbrRetry.decrementAndRetry());
2260         boolean replaySuccess = true;
2261         for (ReplayNbr replayNbr : replayNbrList) {
2262             replaySuccess = replaySuccess && !replayNbr.isShouldRetry();
2263             if (replaySuccess == false) {
2264                 LOG.error("replayNbrConfig: will be cancelling stale cleanup, cfg nbr: {} Failed:",
2265                         replayNbr.getNbr().getAddress().getValue());
2266             }
2267         }
2268         return replaySuccess;
2269     }
2270
2271     public String getConfigHost() {
2272         if (config == null) {
2273             return hostStartup;
2274         }
2275         ConfigServer ts = config.getConfigServer();
2276         return ts == null ? hostStartup : ts.getHost().getValue();
2277     }
2278
2279     public int getConfigPort() {
2280         if (config == null) {
2281             return Integer.parseInt(portStartup);
2282         }
2283         ConfigServer ts = config.getConfigServer();
2284         return ts == null ? Integer.parseInt(portStartup) :
2285                 ts.getPort().intValue();
2286     }
2287
2288     public Bgp getConfig() {
2289         AtomicInteger bgpDSretryCount = new AtomicInteger(DS_RETRY_COUNT);
2290         while (0 != bgpDSretryCount.decrementAndGet()) {
2291             try {
2292                 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
2293                         InstanceIdentifier.create(Bgp.class)).orNull();
2294             } catch (ReadFailedException e) {
2295                 //Config DS may not be up, so sleep for 1 second and retry
2296                 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
2297                 try {
2298                     Thread.sleep(WAIT_TIME_BETWEEN_EACH_TRY_MILLIS);
2299                 } catch (InterruptedException timerEx) {
2300                     LOG.debug("WAIT_TIME_BETWEEN_EACH_TRY_MILLIS, Timer got interrupted while waiting for"
2301                             + "config DS availability", timerEx);
2302                 }
2303             }
2304         }
2305         LOG.error("failed to get bgp config");
2306         return null;
2307     }
2308
2309     @SuppressWarnings("checkstyle:IllegalCatch")
2310     public synchronized boolean replay() throws InterruptedException, TimeoutException, ExecutionException {
2311         boolean replaySucceded = true;
2312         boolean doRouteSync = false;
2313         String host = getConfigHost();
2314         int port = getConfigPort();
2315         LOG.error("connecting  to bgp host {} ", host);
2316         boolean res = bgpRouter.connect(host, port);
2317         if (!res) {
2318             LOG.error("Cannot connect to BGP config server at {} {}", host, port);
2319             return replaySucceded;
2320         }
2321         config = getConfig();
2322         if (config == null) {
2323             LOG.error("bgp config is empty nothing to push to bgp");
2324             return replaySucceded;
2325         }
2326         BgpRouter br = bgpRouter;
2327         AsId asId = config.getAsId();
2328         if (asId == null) {
2329             LOG.error("bgp as-id is null");
2330             return replaySucceded;
2331         }
2332         long asNum = asId.getLocalAs().toJava();
2333         IpAddress routerId = asId.getRouterId();
2334         String rid = routerId == null ? "" : routerId.stringValue();
2335         int stalepathTime = (int) getStalePathtime(bgpGrRestartTime, config.getAsId());
2336         boolean announceFbit = true;
2337         boolean replayDone = false;
2338         final int numberOfStartBgpRetries = 3;
2339         RetryOnException startBgpRetry = new RetryOnException(numberOfStartBgpRetries);
2340         do {
2341             try {
2342                 LOG.debug("Replaying BGPConfig ");
2343                 br.startBgp(asNum, rid, bgpKaTime, bgpHoldTime, stalepathTime, announceFbit);
2344                 LOG.debug("Replay BGPConfig successful");
2345                 replayDone = true;
2346                 break;
2347             } catch (BgpRouterException bre) {
2348                 if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
2349                     LOG.debug("Starting the routesync for exception", bre);
2350                     startBgpRetry.errorOccured();
2351                     if (!startBgpRetry.shouldRetry()) {
2352                         doRouteSync = true;
2353                         replayDone = true;
2354                     }
2355                 } else {
2356                     LOG.error("Replay: startBgp() received exception error {} : ",
2357                             bre.getErrorCode(), bre);
2358                     startBgpRetry.errorOccured();
2359                 }
2360             } catch (TApplicationException tae) {
2361                 if (tae.getType() == BgpRouterException.BGP_ERR_ACTIVE) {
2362                     LOG.debug("Starting the routesync for exception", tae);
2363                     startBgpRetry.errorOccured();
2364                     if (!startBgpRetry.shouldRetry()) {
2365                         doRouteSync = true;
2366                         replayDone = true;
2367                     }
2368                 } else if (tae.getType() == BgpRouterException.BGP_ERR_COMMON_FAILURE) {
2369                     LOG.debug("Starting the routesync for AS-ID started exception", tae);
2370                     startBgpRetry.errorOccured();
2371                     if (!startBgpRetry.shouldRetry()) {
2372                         doRouteSync = true;
2373                         replayDone = true;
2374                     }
2375                 } else {
2376                     LOG.error("Replay: startBgp() received exception type {}: ",
2377                             tae.getType(), tae);
2378                     startBgpRetry.errorOccured();
2379                 }
2380             } catch (Exception e) {
2381                 //not unusual. We may have restarted & BGP is already on
2382                 LOG.error("Replay:startBgp() received exception: ", e);
2383                 startBgpRetry.errorOccured();
2384             }
2385         } while (startBgpRetry.shouldRetry());
2386
2387         replaySucceded = replayDone;
2388
2389         startBgpCountersTask();
2390         startBgpAlarmsTask();
2391
2392         /*
2393          * commenting this due to a bug with QBGP. Will uncomment once QBGP fix is done.
2394          * This wont have any functional impacts
2395          */
2396         //try {
2397         //    br.delayEOR(delayEorSeconds);
2398         //} catch (TException | BgpRouterException e) {
2399         //    LOG.error("Replay: delayEOR() number of seconds to wait for EOR from ODL:", e);
2400         //}
2401
2402         BfdConfig bfdConfig = bgpUtil.getBfdConfig();
2403         if (bfdConfig != null) {
2404             if (bfdConfig.isBfdEnabled()) {
2405                 LOG.debug("Replaying bfd config min-rx {} min-tx {} detect-mul {} mhop {}",
2406                         bfdConfig.getMinRx(), bfdConfig.getMinTx(),
2407                         bfdConfig.getDetectMult(), bfdConfig.isMultihop());
2408                 try {
2409                     br.addBfd(bfdConfig.getDetectMult().intValue(), bfdConfig.getMinRx().intValue(),
2410                             bfdConfig.getMinTx().intValue(), bfdConfig.isMultihop());
2411                 } catch (TApplicationException tae) {
2412                     if (tae.getType() == BgpRouterException.BGP_ERR_PEER_EXISTS) {
2413                         LOG.debug("Replay:addBfd() received exception", tae);
2414                     } else {
2415                         LOG.error("Replay:addBfd() received exception", tae);
2416                     }
2417                 } catch (TException | BgpRouterException e) {
2418                     LOG.error("Replay:addBfd() received exception", e);
2419                 }
2420             }
2421         }
2422
2423         List<Neighbors> neighbors = config.getNeighborsContainer().getNeighbors();
2424         if (neighbors != null) {
2425             LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
2426             boolean neighborConfigReplayResult = replayNbrConfig(neighbors, br);
2427             if (neighborConfigReplayResult == false) {
2428                 replaySucceded = false;
2429             }
2430         } else {
2431             LOG.error("no Neighbors present for replay config ");
2432         }
2433
2434         Logging logging = config.getLogging();
2435         if (logging != null) {
2436             try {
2437                 br.setLogging(logging.getFile(), logging.getLevel());
2438             } catch (TException | BgpRouterException e) {
2439                 LOG.error("Replay:setLogging() received exception", e);
2440             }
2441         }
2442
2443         GracefulRestart gracefulRestart = config.getGracefulRestart();
2444         bgpGrRestartTime = ((gracefulRestart != null)
2445                 ? gracefulRestart.getStalepathTime().intValue() : bgpGrRestartTime);
2446         try {
2447             br.addGracefulRestart(bgpGrRestartTime);
2448         } catch (Exception e) {
2449             LOG.error("Replay:addGr() received exception: ", e);
2450         }
2451         List<Vrfs> vrfs = config.getVrfsContainer().getVrfs();
2452         if (vrfs == null) {
2453             vrfs = new ArrayList<>();
2454         }
2455         for (Vrfs vrf : vrfs) {
2456             for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf()) {
2457                 try {
2458                     br.addVrf(BgpUtil.getLayerType(adf), vrf.getRd(), vrf.getImportRts(),
2459                             vrf.getExportRts(), adf.getAfi().toJava(), adf.getSafi().toJava());
2460                 } catch (TException | BgpRouterException e) {
2461                     LOG.error("Replay:addVrf() received exception", e);
2462                 }
2463             }
2464         }
2465
2466         List<Networks> ln = config.getNetworksContainer().getNetworks();
2467         if (ln != null) {
2468             for (Networks net : ln) {
2469                 String rd = net.getRd();
2470                 String pfxlen = net.getPrefixLen();
2471                 String nh = net.getNexthop().getValue();
2472                 Long label = net.getLabel().toJava();
2473                 int lbl = label == null ? 0 : label.intValue();
2474                 int l3vni = net.getL3vni() == null ? 0 : net.getL3vni().intValue();
2475                 int l2vni = net.getL2vni() == null ? 0 : net.getL2vni().intValue();
2476                 if (rd == null && lbl > 0) {
2477                     //LU prefix is being deleted.
2478                     rd = Integer.toString(lbl);
2479                 }
2480
2481                 BgpControlPlaneType protocolType = net.getBgpControlPlaneType();
2482                 int ethernetTag = net.getEthtag().intValue();
2483                 String esi = net.getEsi();
2484                 String macaddress = net.getMacaddress();
2485                 EncapType encapType = net.getEncapType();
2486                 String routerMac = net.getRoutermac();
2487
2488                 try {
2489                     br.addPrefix(rd, pfxlen, nh, lbl, l3vni, l2vni,
2490                             BgpUtil.convertToThriftProtocolType(protocolType),
2491                             ethernetTag, esi, macaddress, BgpUtil.convertToThriftEncapType(encapType), routerMac);
2492                 } catch (TException | BgpRouterException e) {
2493                     LOG.error("Replay:addPfx() received exception", e);
2494                 }
2495             }
2496         }
2497
2498
2499         List<Multipath> multipaths = config.getMultipathContainer().getMultipath();
2500
2501         if (multipaths != null) {
2502             for (Multipath multipath : multipaths) {
2503                 if (multipath != null) {
2504                     af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
2505                     af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
2506
2507                     try {
2508                         if (multipath.isMultipathEnabled()) {
2509                             br.enableMultipath(afi, safi);
2510                         } else {
2511                             br.disableMultipath(afi, safi);
2512                         }
2513                     } catch (TException | BgpRouterException e) {
2514                         LOG.info("Replay:multipaths() received exception", e);
2515                     }
2516                 }
2517             }
2518         }
2519         List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpathContainer().getVrfMaxpath();
2520         if (vrfMaxpaths != null) {
2521             for (VrfMaxpath vrfMaxpath : vrfMaxpaths) {
2522                 try {
2523                     br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths().toJava());
2524                 } catch (TException | BgpRouterException e) {
2525                     LOG.info("Replay:vrfMaxPath() received exception", e);
2526                 }
2527             }
2528         }
2529
2530         //send End of Rib Marker to Qthriftd.
2531         final int numberOfEORRetries = 3;
2532         RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
2533         do {
2534             try {
2535                 br.sendEOR();
2536                 LOG.debug("Replay sendEOR() successful");
2537                 break;
2538             } catch (Exception e) {
2539                 eorRetry.errorOccured();
2540                 LOG.error("Replay:sedEOR() received exception:", e);
2541             }
2542         } while (eorRetry.shouldRetry());
2543
2544         if (doRouteSync) {
2545             LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception "
2546                       + "happened earlier");
2547             doRouteSync();
2548         }
2549
2550         return replaySucceded;
2551     }
2552
2553     private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
2554         bgpUtil.update(iid, dto);
2555     }
2556
2557     private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
2558         bgpUtil.delete(iid);
2559     }
2560
2561     public void startConfig(String bgpHost, int thriftPort) {
2562         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2563                 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2564         InstanceIdentifier<ConfigServer> iid = iib.build();
2565         Ipv4Address ipAddr = new Ipv4Address(bgpHost);
2566         ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
2567                 .setPort((long) thriftPort).build();
2568         update(iid, dto);
2569     }
2570
2571     public void startBgp(long as, String routerId, int spt, boolean fbit) {
2572         IpAddress rid = routerId == null ? null : IpAddressBuilder.getDefaultInstance(routerId);
2573         Long staleTime = (long) spt;
2574         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2575                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2576         InstanceIdentifier<AsId> iid = iib.build();
2577         AsId dto = new AsIdBuilder().setLocalAs(as)
2578                 .setRouterId(rid)
2579                 .setStalepathTime(staleTime)
2580                 .setAnnounceFbit(fbit).build();
2581         update(iid, dto);
2582     }
2583
2584     public void startBfd(long detectMult, long minRx, long minTx, boolean multiHop) {
2585         InstanceIdentifier.InstanceIdentifierBuilder<BfdConfig> iib =
2586                 InstanceIdentifier.builder(BfdConfig.class);
2587         InstanceIdentifier<BfdConfig> iid = iib.build();
2588         BfdConfig dto = new BfdConfigBuilder()
2589                 .setBfdEnabled(true)
2590                 .setMultihop(multiHop)
2591                 .setMinRx(minRx)
2592                 .setMinTx(minTx)
2593                 .setDetectMult(detectMult)
2594                 .build();
2595         update(iid, dto);
2596     }
2597
2598     public void addDcgwTep(String dcgwIp, String tepIp) {
2599         InstanceIdentifier.InstanceIdentifierBuilder<DcgwTep> iib =
2600                 InstanceIdentifier.builder(Bgp.class)
2601                         .child(DcgwTepList.class)
2602                         .child(DcgwTep.class, new DcgwTepKey(dcgwIp));
2603         InstanceIdentifier<DcgwTep> iid = iib.build();
2604         ArrayList<String> tepList = new ArrayList<String>();
2605         tepList.add(tepIp);
2606         DcgwTep dto = new DcgwTepBuilder().setDcGwIp(dcgwIp).setTepIps(tepList)
2607                 .build();
2608         update(iid, dto);
2609         bgpUtil.removeOrUpdateLBGroups(tepIp,NwConstants.MOD_FLOW);
2610     }
2611
2612     public void addLogging(String fileName, String logLevel) {
2613         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2614                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2615         InstanceIdentifier<Logging> iid = iib.build();
2616         Logging dto = new LoggingBuilder().setFile(fileName)
2617                 .setLevel(logLevel).build();
2618         update(iid, dto);
2619     }
2620
2621     public void addGracefulRestart(int staleTime) {
2622         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2623                 InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
2624         InstanceIdentifier<GracefulRestart> iid = iib.build();
2625         GracefulRestart dto = new GracefulRestartBuilder()
2626                 .setStalepathTime((long) staleTime).build();
2627         update(iid, dto);
2628     }
2629
2630     public void addNeighbor(
2631             String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
2632         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2633         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2634                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2635                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
2636         InstanceIdentifier<Neighbors> iid = iib.build();
2637         TcpSecurityOption tcpSecOption = null;
2638         if (md5Secret != null) {
2639             tcpSecOption = new TcpMd5SignatureOptionBuilder().setTcpMd5SignaturePassword(md5Secret).build();
2640         } // else let tcpSecOption be null
2641         Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
2642                 .setRemoteAs(remoteAs).setTcpSecurityOption(tcpSecOption).build();
2643         update(iid, dto);
2644     } // public addNeighbor(nbrIp, remoteAs, md5Secret)
2645
2646     public void addUpdateSource(String nbrIp, String srcIp) {
2647         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2648         Ipv4Address srcAddr = new Ipv4Address(srcIp);
2649         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2650                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2651                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2652                         .child(UpdateSource.class);
2653         InstanceIdentifier<UpdateSource> iid = iib.build();
2654         UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
2655                 .setSourceIp(srcAddr).build();
2656         update(iid, dto);
2657     }
2658
2659     public void addEbgpMultihop(String nbrIp, int hops) {
2660         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2661         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2662                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2663                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2664                         .child(EbgpMultihop.class);
2665         InstanceIdentifier<EbgpMultihop> iid = iib.build();
2666         EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
2667                 .setNhops((long) hops).build();
2668         update(iid, dto);
2669     }
2670
2671     public void addAddressFamily(String nbrIp, int afi, int safi) {
2672         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2673         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2674                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2675                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2676                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2677         InstanceIdentifier<AddressFamilies> iid = iib.build();
2678         AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
2679                 .setAfi((long) afi).setSafi((long) safi).build();
2680         update(iid, dto);
2681     }
2682
2683     public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
2684               VrfEntry.EncapType encapType, Uint32 lbl, Uint32 l3vni, Uint32 l2vni, String gatewayMac) {
2685         for (String nh : nhList) {
2686             Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
2687             Uint32 label = lbl;
2688             InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
2689                     .child(NetworksContainer.class)
2690                     .child(Networks.class, new NetworksKey(pfx, rd)).build();
2691             NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
2692                                                 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
2693             buildVpnEncapSpecificInfo(networksBuilder, encapType, label, l3vni, l2vni, macAddress, gatewayMac);
2694             update(iid, networksBuilder.build());
2695         }
2696     }
2697
2698     private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, Uint32 label,
2699                                                   Uint32 l3vni, Uint32 l2vni, String macAddress, String gatewayMac) {
2700         if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
2701             builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
2702                     .setEncapType(EncapType.GRE);
2703         } else {
2704             builder.setL3vni(l3vni).setL2vni(l2vni).setMacaddress(macAddress).setRoutermac(gatewayMac)
2705                     .setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLEVPN).setEncapType(EncapType.VXLAN);
2706         }
2707     }
2708
2709     // TODO: add LayerType as arg - supports command
2710     public void addVrf(String rd, List<String> irts, List<String> erts, AddressFamily addressFamily) {
2711         Vrfs vrf = bgpUtil.getVrfFromRd(rd);
2712         List<AddressFamiliesVrf> adfList = new ArrayList<>(1);
2713         if (vrf != null) {
2714             adfList = vrf.getAddressFamiliesVrf();
2715         }
2716         AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2717         if (addressFamily.equals(AddressFamily.IPV4)) {
2718             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2719             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2720         } else if (addressFamily.equals(AddressFamily.IPV6)) {
2721             adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2722             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2723         } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2724             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2725             adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2726         }
2727         AddressFamiliesVrf adf = adfBuilder.build();
2728         adfList.add(adf);
2729         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = InstanceIdentifier.builder(Bgp.class)
2730                 .child(VrfsContainer.class)
2731                 .child(Vrfs.class, new VrfsKey(rd));
2732         InstanceIdentifier<Vrfs> iid = iib.build();
2733         Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
2734             .setExportRts(erts).setAddressFamiliesVrf(adfList).build();
2735
2736         List<AddressFamiliesVrf> listAdFamilies = mapNewAdFamily.get(rd);
2737         if (listAdFamilies != null) {
2738             listAdFamilies.add(adf);
2739         } else {
2740             mapNewAdFamily.put(rd, adfList);
2741         }
2742
2743         try {
2744             SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, iid, dto);
2745         } catch (TransactionCommitFailedException e) {
2746             LOG.error("Error adding VRF to datastore", e);
2747             throw new RuntimeException(e);
2748         }
2749
2750         // enable multipath by default in all VRFs
2751         setMultipaths(rd, BgpConstants.BGP_DEFAULT_MULTIPATH);
2752     }
2753
2754     public void stopConfig() {
2755         InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
2756                 InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
2757         InstanceIdentifier<ConfigServer> iid = iib.build();
2758         delete(iid);
2759     }
2760
2761     public void stopBgp() {
2762         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
2763                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
2764         InstanceIdentifier<AsId> iid = iib.build();
2765         delete(iid);
2766     }
2767
2768     public void stopBfd() {
2769         InstanceIdentifier.InstanceIdentifierBuilder<BfdConfig> iib =
2770                 InstanceIdentifier.builder(BfdConfig.class);
2771         InstanceIdentifier<BfdConfig> iid = iib.build();
2772         delete(iid);
2773     }
2774
2775     public void delDcgwTep(String dcgwIp, String tepIp) {
2776         if (tepIp == null) {
2777             InstanceIdentifier.InstanceIdentifierBuilder<DcgwTep> iib =
2778                     InstanceIdentifier.builder(Bgp.class)
2779                             .child(DcgwTepList.class)
2780                             .child(DcgwTep.class, new DcgwTepKey(dcgwIp));
2781             InstanceIdentifier<DcgwTep> iid = iib.build();
2782             delete(iid);
2783         } else {
2784             InstanceIdentifier.InstanceIdentifierBuilder<DcgwTep> iib =
2785                     InstanceIdentifier.builder(Bgp.class)
2786                             .child(DcgwTepList.class)
2787                             .child(DcgwTep.class, new DcgwTepKey(dcgwIp));
2788             InstanceIdentifier<DcgwTep> iid = iib.build();
2789             List<String> tepIpList = bgpUtil.getDcgwTepConfig(dcgwIp);
2790             if (tepIpList == null) {
2791                 LOG.error("No Tep IP configured for DCGW {} on deleting the dcgwtep", dcgwIp);
2792                 return;
2793             }
2794             List<String> newTepIpList = new ArrayList<String>();
2795             tepIpList.forEach(tep -> {
2796                 if (!tep.equals(tepIp)) {
2797                     newTepIpList.add(tep);
2798                 }
2799             });
2800             DcgwTep dto = new DcgwTepBuilder().setDcGwIp(dcgwIp).setTepIps(newTepIpList)
2801                     .build();
2802             try {
2803                 SingleTransactionDataBroker.syncWrite(dataBroker,
2804                         LogicalDatastoreType.CONFIGURATION, iid, dto);
2805             } catch (TransactionCommitFailedException e) {
2806                 LOG.error("delDcgwTep: Error deleting DCGW Tep", e);
2807                 throw new RuntimeException(e);
2808             }
2809         }
2810     }
2811
2812     public void delLogging() {
2813         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
2814                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
2815         InstanceIdentifier<Logging> iid = iib.build();
2816         delete(iid);
2817     }
2818
2819     public void delGracefulRestart() {
2820         InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
2821                 InstanceIdentifier.builder(Bgp.class)
2822                         .child(GracefulRestart.class);
2823         InstanceIdentifier<GracefulRestart> iid = iib.build();
2824         delete(iid);
2825     }
2826
2827     public void delNeighbor(String nbrIp) {
2828         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2829         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
2830                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2831                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
2832         InstanceIdentifier<Neighbors> iid = iib.build();
2833         delete(iid);
2834     }
2835
2836     public void delUpdateSource(String nbrIp) {
2837         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2838         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
2839                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2840                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2841                         .child(UpdateSource.class);
2842         InstanceIdentifier<UpdateSource> iid = iib.build();
2843         delete(iid);
2844     }
2845
2846     public void delEbgpMultihop(String nbrIp) {
2847         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2848         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
2849                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2850                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2851                         .child(EbgpMultihop.class);
2852         InstanceIdentifier<EbgpMultihop> iid = iib.build();
2853         delete(iid);
2854     }
2855
2856     public void delAddressFamily(String nbrIp, int afi, int safi) {
2857         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
2858         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
2859                 InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
2860                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
2861                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
2862         InstanceIdentifier<AddressFamilies> iid = iib.build();
2863         delete(iid);
2864     }
2865
2866     public void delPrefix(String rd, String pfx) {
2867         InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
2868                 InstanceIdentifier.builder(Bgp.class).child(NetworksContainer.class)
2869                         .child(Networks.class, new NetworksKey(pfx, rd));
2870         InstanceIdentifier<Networks> iid = iib.build();
2871         delete(iid);
2872     }
2873
2874     public boolean delVrf(String rd, AddressFamily addressFamily) {
2875         if (addressFamily == null) {
2876             LOG.error("delVrf: vrf {}, addressFamily invalid", rd);
2877             return false;
2878         }
2879         delMultipaths(rd);
2880         AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
2881         if (addressFamily.equals(AddressFamily.IPV4)) {
2882             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2883             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2884         } else if (addressFamily.equals(AddressFamily.IPV6)) {
2885             adfBuilder.setAfi((long) af_afi.AFI_IPV6.getValue());
2886             adfBuilder.setSafi((long) af_safi.SAFI_MPLS_VPN.getValue());
2887         } else if (addressFamily.equals(AddressFamily.L2VPN)) {
2888             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
2889             adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
2890         }
2891         LOG.debug("delVrf: Received Delete VRF : rd:{}, address family: {} {}", rd,
2892                 adfBuilder.getAfi(), adfBuilder.getSafi());
2893
2894         Vrfs vrfOriginal = bgpUtil.getVrfFromRd(rd);
2895         if (vrfOriginal == null) {
2896             LOG.error("delVrf: no vrf with existing rd {}. step aborted", rd);
2897             return false;
2898         }
2899
2900         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
2901                 InstanceIdentifier.builder(Bgp.class).child(VrfsContainer.class)
2902                         .child(Vrfs.class, new VrfsKey(rd));
2903
2904         InstanceIdentifier<Vrfs> iid = iib.build();
2905
2906         @SuppressWarnings("static-access")
2907         InstanceIdentifier<Bgp> iid6 =  iid.builder(Bgp.class).build()
2908                 .child(MultipathContainer.class)
2909                 .child(Multipath.class, new MultipathKey(adfBuilder.getAfi(), adfBuilder.getSafi())).create(Bgp.class);
2910         InstanceIdentifierBuilder<Vrfs> iib3 =
2911                 iid6.child(VrfsContainer.class).child(Vrfs.class, new VrfsKey(rd)).builder();
2912         InstanceIdentifier<Vrfs> iidFinal = iib3.build();
2913
2914         //** update or delete the vrfs with the rest of AddressFamilies already present in the last list
2915         AddressFamiliesVrf adfToDel = adfBuilder.build();
2916         List<AddressFamiliesVrf> adfListOriginal = new ArrayList<>(vrfOriginal.nonnullAddressFamiliesVrf());
2917         List<AddressFamiliesVrf> adfListToRemoveFromOriginal = new ArrayList<>();
2918         adfListOriginal.forEach(adf -> {
2919             if (adf.equals(adfToDel)) {
2920                 adfListToRemoveFromOriginal.add(adfToDel);
2921                 return;
2922             }
2923         });
2924         for (AddressFamiliesVrf adfToRemove : adfListToRemoveFromOriginal) {
2925             adfListOriginal.remove(adfToRemove);
2926             try {
2927                 SingleTransactionDataBroker.syncWrite(dataBroker,
2928                         LogicalDatastoreType.CONFIGURATION, iid, vrfOriginal);
2929             } catch (TransactionCommitFailedException e) {
2930                 LOG.error("delVrf: Error updating VRF to datastore", e);
2931                 throw new RuntimeException(e);
2932             }
2933         }
2934         if (adfListOriginal.isEmpty()) {
2935             LOG.debug("delVrf: delete iid: {}", iidFinal);
2936             delete(iidFinal);
2937             return true;
2938         }
2939         // not all is removed
2940         return false;
2941     }
2942
2943     public void setMultipathStatus(af_afi afi, af_safi safi, boolean enable) {
2944         long lafi = afi.getValue();
2945         long lsafi = safi.getValue();
2946
2947         InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
2948                 InstanceIdentifier
2949                         .builder(Bgp.class).child(MultipathContainer.class)
2950                         .child(Multipath.class,
2951                                 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
2952
2953         Multipath dto = new MultipathBuilder().setAfi(lafi).setSafi(lsafi).setMultipathEnabled(enable).build();
2954         update(iib.build(), dto);
2955     }
2956
2957     public void setMultipaths(String rd, int maxpath) {
2958         InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2959                 InstanceIdentifier
2960                         .builder(Bgp.class).child(VrfMaxpathContainer.class)
2961                         .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2962
2963         VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
2964         update(iib.build(), dto);
2965     }
2966
2967     public void delMultipaths(String rd) {
2968         InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
2969                 InstanceIdentifier.builder(Bgp.class).child(VrfMaxpathContainer.class)
2970                         .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
2971         InstanceIdentifier<VrfMaxpath> iid = iib.build();
2972         delete(iid);
2973     }
2974
2975     /*
2976     * Remove Stale Marked Routes after timer expiry.
2977     */
2978     private class RouteCleanup implements Callable<Integer> {
2979
2980         @Override
2981         public Integer call() {
2982             totalCleared = 0;
2983             try {
2984                 if (staledFibEntriesMap.isEmpty()) {
2985                     LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
2986                 } else {
2987                     for (String rd : staledFibEntriesMap.keySet()) {
2988                         if (Thread.interrupted()) {
2989                             return 0;
2990                         }
2991                         Map<String, Uint32> map = staledFibEntriesMap.get(rd);
2992                         if (map != null) {
2993                             for (String key : map.keySet()) {
2994                                 if (Thread.interrupted()) {
2995                                     return 0;
2996                                 }
2997                                 String prefix = extractPrefix(key);
2998                                 String nextHop = extractNextHop(key);
2999                                 totalCleared++;
3000                                 LOG.debug("BGP: RouteCleanup deletePrefix called for : rd:{}, prefix{}, nextHop:{}",
3001                                         rd, prefix, nextHop);
3002                                 fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix, nextHop);
3003                             }
3004                         }
3005                     }
3006                 }
3007             } finally {
3008                 staledFibEntriesMap.clear();
3009             }
3010             LOG.error("cleared {} stale routes after bgp restart", totalCleared);
3011             return 0;
3012         }
3013     }
3014
3015     /*
3016      * BGP restart scenario, ODL-BGP manager was/is running.
3017      * On re-sync notification, Get a copy of FIB database.
3018      */
3019     public void createStaleFibMap() {
3020         totalStaledCount = 0;
3021         try {
3022             staledFibEntriesMap.clear();
3023             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
3024
3025             Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
3026                     LogicalDatastoreType.CONFIGURATION, id);
3027             if (fibEntries.isPresent()) {
3028                 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
3029                 for (VrfTables vrfTable : staleVrfTables) {
3030                     Map<String, Uint32> staleFibEntMap = new HashMap<>();
3031                     for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
3032                         if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
3033                             //Stale marking and cleanup is only meant for the routes learned through BGP.
3034                             continue;
3035                         }
3036                         if (Thread.interrupted()) {
3037                             break;
3038                         }
3039                         totalStaledCount++;
3040                         //Create MAP from staleVrfTables.
3041                         vrfEntry.getRoutePaths()
3042                                 .forEach(
3043                                     routePath -> staleFibEntMap.put(
3044                                             appendNextHopToPrefix(vrfEntry.getDestPrefix(),
3045                                                     routePath.getNexthopAddress()), routePath.getLabel()));
3046                     }
3047                     staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
3048                 }
3049             } else {
3050                 LOG.error("createStaleFibMap:: FIBentries.class is not present");
3051             }
3052         } catch (ReadFailedException e) {
3053             LOG.error("createStaleFibMap:: error ", e);
3054         }
3055         LOG.error("created {} staled entries ", totalStaledCount);
3056     }
3057
3058     /*
3059      * BGP config remove scenario, Need to remove all the
3060      * external routes from FIB.
3061      */
3062     public void deleteExternalFibRoutes() {
3063         totalExternalRoutes = 0;
3064         totalExternalMacRoutes = 0;
3065         try {
3066             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
3067
3068             Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
3069                     LogicalDatastoreType.CONFIGURATION, id);
3070             if (fibEntries.isPresent()) {
3071                 if (fibEntries.get().getVrfTables() == null) {
3072                     LOG.error("deleteExternalFibRoutes::getVrfTables is null");
3073                     return;
3074                 }
3075                 List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
3076                 for (VrfTables vrfTable : staleVrfTables) {
3077                     String rd = vrfTable.getRouteDistinguisher();
3078                     if (vrfTable.getVrfEntry() != null) {
3079                         for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
3080                             if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
3081                                 //route cleanup is only meant for the routes learned through BGP.
3082                                 continue;
3083                             }
3084                             totalExternalRoutes++;
3085                             fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
3086                         }
3087                     } else if (vrfTable.getMacVrfEntry() != null) {
3088                         for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
3089                             if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
3090                                 //route cleanup is only meant for the routes learned through BGP.
3091                                 continue;
3092                             }
3093                             totalExternalMacRoutes++;
3094                             fibDSWriter.removeMacEntryFromDS(rd, macEntry.getMac());
3095                         }
3096                     }
3097                 }
3098             } else {
3099                 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
3100             }
3101         } catch (ReadFailedException e) {
3102             LOG.error("deleteExternalFibRoutes:: error ", e);
3103         }
3104         LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
3105     }
3106
3107     public boolean addToRt2TepMap(String rd, String tepIp, String mac, Uint32 l2vni) {
3108         boolean isFirstMacUpdateFromTep = false;
3109         if (rt2TepMap.containsKey(rd)) {
3110             if (rt2TepMap.get(rd).containsKey(tepIp)) {
3111                 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and tep-ip {}. No Elan DS write required",
3112                         mac, l2vni, rd, tepIp);
3113                 rt2TepMap.get(rd).get(tepIp).put(mac, l2vni);
3114             } else {
3115                 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
3116                         mac, l2vni, rd, tepIp);
3117                 isFirstMacUpdateFromTep = true;
3118                 Map<String, Uint32> macList = new HashMap<>();
3119                 macList.put(mac, l2vni);
3120                 rt2TepMap.get(rd).put(tepIp, macList);
3121             }
3122         } else {
3123             LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
3124                     mac, l2vni, rd, tepIp);
3125             isFirstMacUpdateFromTep = true;
3126             Map<String, Uint32> macList = new HashMap<>();
3127             macList.put(mac, l2vni);
3128             Map<String, Map<String, Uint32>> tepIpMacMap = new HashMap<>();
3129             tepIpMacMap.put(tepIp, macList);
3130             rt2TepMap.put(rd, tepIpMacMap);
3131         }
3132         return isFirstMacUpdateFromTep;
3133     }
3134
3135     public boolean deleteFromRt2TepMap(String rd, String tepIp, String mac) {
3136         boolean isLastMacUpdateFromTep = false;
3137         LOG.debug("RT2 withdraw with rd {} mac {} tep-ip {} ", rd, mac, tepIp);
3138         if (rt2TepMap.containsKey(rd)) {
3139             if (rt2TepMap.get(rd).containsKey(tepIp)) {
3140                 if (rt2TepMap.get(rd).get(tepIp).containsKey(mac)) {
3141                     LOG.debug("RT2 Withdraw : Removing the mac {} from Map", mac);
3142                     rt2TepMap.get(rd).get(tepIp).remove(mac);
3143                     if (rt2TepMap.get(rd).get(tepIp).isEmpty()) {
3144                         isLastMacUpdateFromTep = true;
3145                         LOG.debug("RT2 Withdraw : Removing the tep-ip {} from Map", tepIp);
3146                         rt2TepMap.get(rd).remove(tepIp);
3147                         if (rt2TepMap.get(rd).isEmpty()) {
3148                             LOG.debug("RT2 Withdraw : Removing the rd {} from Map", rd);
3149                             rt2TepMap.remove(rd);
3150                         }
3151                     }
3152                 }
3153             }
3154         }
3155         return isLastMacUpdateFromTep;
3156     }
3157
3158     public Collection<String> getTepIPs(String rd) {
3159         final Map<String, Map<String, Uint32>> tepIpMap = rt2TepMap.get(rd);
3160         return tepIpMap != null ? tepIpMap.keySet() : Collections.emptyList();
3161     }
3162
3163     public boolean isBgpConnected() {
3164         return (bgpRouter == null) ? false : bgpRouter.isBgpConnected();
3165     }
3166
3167     public long getLastConnectedTS() {
3168         return (bgpRouter == null) ? 0 : bgpRouter.getLastConnectedTS();
3169     }
3170
3171     public long getConnectTS() {
3172         return (bgpRouter == null) ? 0 : bgpRouter.getConnectTS();
3173     }
3174
3175     public long getStartTS() {
3176         return (bgpRouter == null) ? 0 : bgpRouter.getStartTS();
3177     }
3178
3179     public TTransport getTransport() {
3180         return bgpRouter.getTransport();
3181     }
3182
3183     public int getTotalStaledCount() {
3184         return totalStaledCount;
3185     }
3186
3187     public int getTotalCleared() {
3188         return totalCleared;
3189     }
3190
3191     public BgpCounters getBgpCounters() {
3192         return bgpCountersReference.get();
3193     }
3194
3195     private void startBgpCountersTask() {
3196         if (getBgpCounters() == null && bgpCountersReference.compareAndSet(null,
3197                 new BgpCounters(getBgpSdncMipIp(), metricProvider))) {
3198             bgpCountersTask = executor.scheduleAtFixedRate(bgpCountersReference.get(), 0, 120 * 1000,
3199                     TimeUnit.MILLISECONDS);
3200             LOG.info("Bgp Counters task scheduled for every two minutes.");
3201
3202             bgpManager.setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
3203         }
3204     }
3205
3206     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
3207             justification = "https://github.com/spotbugs/spotbugs/issues/811")
3208     private void stopBgpCountersTask() {
3209         final BgpCounters bgpCounters = bgpCountersReference.getAndSet(null);
3210         if (bgpCounters != null) {
3211             bgpCountersTask.cancel(true);
3212             bgpCounters.close();
3213         }
3214     }
3215
3216     private void startBgpAlarmsTask() {
3217         if (getBgpAlarms() == null && bgpAlarmsReference.compareAndSet(null, new BgpAlarms(this))) {
3218             bgpAlarmsReference.get().init();
3219             bgpAlarmsTask = executor.scheduleAtFixedRate(bgpAlarmsReference.get(), 0, 60 * 1000, TimeUnit.MILLISECONDS);
3220             LOG.info("Bgp Alarms task scheduled for every minute.");
3221         } else {
3222             LOG.trace("Bgp Alarms task already scheduled for every minute.");
3223         }
3224     }
3225
3226     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
3227             justification = "https://github.com/spotbugs/spotbugs/issues/811")
3228     private void stopBgpAlarmsTask() {
3229         final BgpAlarms bgpAlarms = bgpAlarmsReference.getAndSet(null);
3230         if (bgpAlarms != null) {
3231             bgpAlarmsTask.cancel(true);
3232             bgpAlarms.close();
3233         }
3234     }
3235
3236     public BgpAlarms getBgpAlarms() {
3237         return bgpAlarmsReference.get();
3238     }
3239
3240     public void getPeerStatus(String nbrIp, long nbrAsNum) throws
3241             BgpRouterException, TException {
3242         bgpRouter.getPeerStatus(nbrIp, nbrAsNum);
3243     }
3244
3245     private static String appendNextHopToPrefix(String prefix, String nextHop) {
3246         return prefix + ":" + nextHop;
3247     }
3248
3249     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
3250             justification = "https://github.com/spotbugs/spotbugs/issues/811")
3251     private static String extractPrefix(String prefixNextHop) {
3252         return prefixNextHop.split(":")[0];
3253     }
3254
3255     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
3256             justification = "https://github.com/spotbugs/spotbugs/issues/811")
3257     private static String extractNextHop(String prefixNextHop) {
3258         return prefixNextHop.split(":")[1];
3259     }
3260
3261     private static String extractMd5Secret(final Neighbors val) {
3262         String md5Secret = null;
3263         TcpSecurityOption tcpSecOpt = val.getTcpSecurityOption();
3264         if (tcpSecOpt != null) {
3265             if (tcpSecOpt instanceof TcpMd5SignatureOption) {
3266                 md5Secret = ((TcpMd5SignatureOption) tcpSecOpt).getTcpMd5SignaturePassword().getValue();
3267             } else { // unknown TcpSecurityOption
3268                 LOG.debug("neighbors  Ignored unknown tcp-security-option of peer {}", val.getAddress().getValue());
3269             }
3270         }
3271         return md5Secret;
3272     } // private method extractMd5Secret
3273
3274     @SuppressWarnings("checkstyle:IllegalCatch")
3275     @Override
3276     public ListenableFuture<RpcResult<InitiateEorOutput>> initiateEor(InitiateEorInput input) {
3277         boolean returnError = false;
3278         String msg = null;
3279         String neighborIp = null;
3280         if (!isBGPEntityOwner()) {
3281             msg = String.format("RPC triggered in Non-EoS Owner");
3282             return Futures.immediateFuture(
3283                     RpcResultBuilder.<InitiateEorOutput>failed().withError(RpcError.ErrorType.APPLICATION,
3284                             msg).build());
3285         }
3286         if (input == null) {
3287             msg = String.format("BGP invalid input for EoR");
3288             LOG.error("Error : {}", msg);
3289             returnError = true;
3290         } else {
3291             neighborIp = input.getNeighborIp();
3292         }
3293         if (eorSupressedDuetoUpgradeFlag.get() == false) {
3294             msg = String.format("EoR triggerd by RBU-RPC call before replay"
3295                     + "of BGP configuration (or) BGP not restarted");
3296             LOG.error("Error : {}", msg);
3297         }
3298         if ("ALL".compareToIgnoreCase(neighborIp) == 0) {
3299             //send EoR for all the neighbor
3300             LOG.error("EoR trigger received to ALL neighbors");
3301             final int numberOfEORRetries = 3;
3302             RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
3303             do {
3304                 try {
3305                     BgpRouter br = bgpRouter;
3306                     br.sendEOR();
3307                     LOG.debug("RPC: sendEOR {} successful", br);
3308                     break;
3309                 } catch (Exception e) {
3310                     eorRetry.errorOccured();
3311                     LOG.error("Replay:sedEOR() received exception:", e);
3312                 }
3313             } while (eorRetry.shouldRetry());
3314             eorSupressedDuetoUpgradeFlag.set(false);
3315         } else if (InetAddresses.isInetAddress(neighborIp)) {
3316             //send EoR for only one neighbor
3317             msg = String.format("Inidividual neighbors EoR is not supported");
3318             LOG.warn("Error : {}", msg);
3319             returnError = true;
3320         } else {
3321             //error
3322             msg = String.format("RPC: initiateEor: Invalid input ");
3323             LOG.warn("Error : {}", msg);
3324             returnError = true;
3325         }
3326         if (returnError) {
3327             return Futures.immediateFuture(
3328                     RpcResultBuilder.<InitiateEorOutput>failed().withError(RpcError.ErrorType.APPLICATION,
3329                             msg).build());
3330         }
3331         InitiateEorOutput initiateEorOutput =
3332                 new InitiateEorOutputBuilder().setRetVal(0L).build();
3333         return Futures.immediateFuture(RpcResultBuilder.<InitiateEorOutput>success()
3334                 .withResult(initiateEorOutput).build());
3335     }
3336 }