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