MRI version bumpup for Aluminium
[netvirt.git] / bgpmanager / impl / src / main / java / org / opendaylight / netvirt / bgpmanager / BgpConfigurationManager.java
index b03a46b4bd9fe0f8954b80548af1a6dd16216320..280f662204c2184c55228c42917e507288699f4c 100755 (executable)
@@ -7,13 +7,20 @@
  */
 package org.opendaylight.netvirt.bgpmanager;
 
-import com.google.common.base.Optional;
+import static org.opendaylight.netvirt.bgpmanager.oam.BgpConstants.HISTORY_LIMIT;
+import static org.opendaylight.netvirt.bgpmanager.oam.BgpConstants.HISTORY_THRESHOLD;
+
+import com.google.common.base.Preconditions;
+import com.google.common.net.InetAddresses;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import io.netty.util.concurrent.GlobalEventExecutor;
-import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
@@ -25,6 +32,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Timer;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
@@ -36,26 +44,24 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
-import javax.annotation.Nullable;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.apache.thrift.TApplicationException;
 import org.apache.thrift.TException;
 import org.apache.thrift.transport.TTransport;
-import org.opendaylight.controller.config.api.osgi.WaitingServiceTracker;
-import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
 import org.opendaylight.infrautils.metrics.MetricProvider;
+import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
 import org.opendaylight.mdsal.eos.binding.api.Entity;
 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipCandidateRegistration;
 import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipListenerRegistration;
@@ -79,86 +85,126 @@ import org.opendaylight.netvirt.bgpmanager.thrift.gen.qbgpConstants;
 import org.opendaylight.netvirt.bgpmanager.thrift.server.BgpThriftService;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.IVpnLinkService;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionHistory;
+import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebfd.rev190219.BfdConfig;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebfd.rev190219.BfdConfigBuilder;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.AddressFamily;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.BgpControlPlaneType;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EbgpService;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.EncapType;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.InitiateEorInput;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.InitiateEorOutput;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.InitiateEorOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.TcpMd5SignaturePasswordType;
+//import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsId;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.AsIdBuilder;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServer;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.ConfigServerBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.DcgwTepList;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestart;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.GracefulRestartBuilder;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Logging;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.LoggingBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Multipath;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathKey;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsKey;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpath;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathKey;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Vrfs;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsKey;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamilies;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.AddressFamiliesKey;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihop;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.EbgpMultihopBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSource;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.UpdateSourceBuilder;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrf;
-import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfs.AddressFamiliesVrfBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.MultipathContainer;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NeighborsContainer;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksContainer;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfMaxpathContainer;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.VrfsContainer;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.dcgw.tep.list.DcgwTep;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.dcgw.tep.list.DcgwTepBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.dcgw.tep.list.DcgwTepKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.multipathcontainer.Multipath;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.multipathcontainer.MultipathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.multipathcontainer.MultipathKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.Neighbors;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.NeighborsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.NeighborsKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.AddressFamilies;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.AddressFamiliesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.AddressFamiliesKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.EbgpMultihop;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.EbgpMultihopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.UpdateSource;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighborscontainer.neighbors.UpdateSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.networkscontainer.Networks;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.networkscontainer.NetworksBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.networkscontainer.NetworksKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfmaxpathcontainer.VrfMaxpath;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfmaxpathcontainer.VrfMaxpathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfmaxpathcontainer.VrfMaxpathKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.Vrfs;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.VrfsBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.VrfsKey;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.vrfs.AddressFamiliesVrf;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.vrfs.AddressFamiliesVrfBuilder;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.vrfscontainer.vrfs.AddressFamiliesVrfKey;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.TcpSecurityOption;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOption;
 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.tcp.security.option.grouping.tcp.security.option.TcpMd5SignatureOptionBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.macvrfentries.MacVrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.Uint32;
 import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
-public class BgpConfigurationManager {
+public class BgpConfigurationManager implements EbgpService {
     private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
 
     // to have stale FIB map (RD, Prefix)
     //  number of seconds wait for route sync-up between ODL and BGP
     private static final int BGP_RESTART_ROUTE_SYNC_SEC = 600;
-    private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
-    private static final String DEF_LOGLEVEL = "errors";
     private static final String UPDATE_PORT = "bgp.thrift.service.port";
     private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
     private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
     private static final String DEF_UPORT = "6644";
     private static final String DEF_CHOST = "255.255.255.255"; // Invalid Host IP
-    private static final String DEF_CPORT = "0";               // Invalid Port
+    private static final String DEF_CPORT = "7644";
     private static final String DEF_BGP_SDNC_MIP = "127.0.0.1";
-    private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.sdnc.mip";
+    //vpnservice.bgp.thrift.bgp.mip is the MIP present with ODL. Here we open 6644 port
+    private static final String BGP_SDNC_MIP = "vpnservice.bgp.thrift.bgp.mip";
+    private static final String BGP_GR_RESTART_TIMER_PROPERTY = "vpnservice.bgp.gr.timer";
+    private static final String BGP_KA_TIMER_PROPERTY = "vpnservice.bgp.ka.timer";
+    private static final String BGP_HOLD_TIMER_PROPERTY = "vpnservice.bgp.hold.timer";
+    private static final String BGP_EOR_DELAY_PROPERTY = "vpnservice.bgp.eordelay";
+    private static final int DEF_BGP_KA_TIME = 60;
+    private static final int DEF_BGP_HOLD_TIME = 180;
+    private static final int DEF_BGP_GR_TIME = 4000;
     private static final int RESTART_DEFAULT_GR = 90;
     private static final int DS_RETRY_COUNT = 100; //100 retries, each after WAIT_TIME_BETWEEN_EACH_TRY_MILLIS seconds
     private static final long WAIT_TIME_BETWEEN_EACH_TRY_MILLIS = 1000L; //one second sleep after every retry
     private static final String BGP_ENTITY_TYPE_FOR_OWNERSHIP = "bgp";
+    private static final String BGP_EOR_DELAY = "vpnservice.bgp.eordelay";
+    private static final String DEF_BGP_EOR_DELAY = "1800";
     private static final String BGP_ENTITY_NAME = "bgp";
     private static final String ADD_WARN = "Config store updated; undo with Delete if needed.";
     private static final String DEL_WARN = "Config store updated; undo with Add if needed.";
     private static final String UPD_WARN = "Update operation not supported; Config store updated;"
             + " restore with another Update if needed.";
+    private static long bgp_as_num = 0;
+    private static List<Neighbors> nbrList = new ArrayList<>();
+    private int bgpKaTime = 0;
+    private int bgpHoldTime = 0;
+    private int bgpGrRestartTime = 0;
 
     private static final Class<?>[] REACTORS = {
         ConfigServerReactor.class, AsIdReactor.class,
@@ -166,7 +212,7 @@ public class BgpConfigurationManager {
         NeighborsReactor.class, UpdateSourceReactor.class,
         EbgpMultihopReactor.class, AddressFamiliesReactor.class,
         NetworksReactor.class, VrfsReactor.class, BgpReactor.class,
-        MultipathReactor.class, VrfMaxpathReactor.class
+        MultipathReactor.class, VrfMaxpathReactor.class, BfdConfigReactor.class
     };
 
     private IBgpManager bgpManager;
@@ -178,7 +224,8 @@ public class BgpConfigurationManager {
     private volatile Bgp config;
     private final BgpRouter bgpRouter;
     private final BgpSyncHandle bgpSyncHandle = new BgpSyncHandle();
-    private BgpThriftService updateServer;
+    private volatile BgpThriftService bgpThriftService = null;
+    private final int delayEorSeconds;
 
     private final CountDownLatch initer = new CountDownLatch(1);
 
@@ -205,7 +252,7 @@ public class BgpConfigurationManager {
     private int totalExternalMacRoutes;
 
     private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(
-            new ThreadFactoryBuilder().setNameFormat("BgpConfigurationManager-%d").setDaemon(true).build());
+            new ThreadFactoryBuilder().setNameFormat("bgp-config-%d").setDaemon(true).build());
 
     /**
      * this map store the new address families to send to quagga. When it is sended you must clear it.
@@ -214,10 +261,13 @@ public class BgpConfigurationManager {
     private final ConcurrentHashMap<String, List<AddressFamiliesVrf>> mapNewAdFamily = new ConcurrentHashMap<>();
 
     // map<rd, map<prefix/len:nexthop, label>>
-    private final Map<String, Map<String, Long>> staledFibEntriesMap = new ConcurrentHashMap<>();
+    private final Map<String, Map<String, Uint32>> staledFibEntriesMap = new ConcurrentHashMap<>();
 
     // map<rd, map<tep-ip, map<mac, l2vni>>>
-    private final Map<String, Map<String, Map<String, Long>>> rt2TepMap = new ConcurrentHashMap<>();
+    private final Map<String, Map<String, Map<String, Uint32>>> rt2TepMap = new ConcurrentHashMap<>();
+
+    //map<rd+prefix/plen, list (nexthop)>
+    private final Map<String,List> fibMap = new HashMap<>();
 
     private final List<AutoCloseable> listeners = new ArrayList<>();
 
@@ -225,6 +275,9 @@ public class BgpConfigurationManager {
     private final EntityOwnershipCandidateRegistration candidateRegistration;
     private final EntityOwnershipListenerRegistration entityListenerRegistration;
     private final MetricProvider metricProvider;
+    private final TransactionHistory bgpUpdatesHistory;
+
+    private volatile AtomicBoolean eorSupressedDuetoUpgradeFlag = new AtomicBoolean(false);
 
     @Inject
     public BgpConfigurationManager(final DataBroker dataBroker,
@@ -240,15 +293,23 @@ public class BgpConfigurationManager {
         this.bundleContext = bundleContext;
         this.bgpUtil = bgpUtil;
         this.metricProvider = metricProvider;
-        String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
         hostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
         portStartup = getProperty(CONFIG_PORT, DEF_CPORT);
-        LOG.info("UpdateServer at localhost:" + updatePort + " ConfigServer at "
-                + hostStartup + ":" + portStartup);
+        bgpKaTime =
+                Integer.parseInt(getProperty(BGP_KA_TIMER_PROPERTY,
+                        Integer.toString(DEF_BGP_KA_TIME)));
+        bgpHoldTime =
+                Integer.parseInt(getProperty(BGP_HOLD_TIMER_PROPERTY,
+                        Integer.toString(DEF_BGP_HOLD_TIME)));
+        bgpGrRestartTime =
+                Integer.parseInt(getProperty(BGP_GR_RESTART_TIMER_PROPERTY,
+                        Integer.toString(DEF_BGP_GR_TIME)));
+        LOG.info("ConfigServer at {}:{}", hostStartup, portStartup);
         VtyshCli.setHostAddr(hostStartup);
         ClearBgpCli.setHostAddr(hostStartup);
-        bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner);
-        registerCallbacks();
+        bgpUpdatesHistory = new TransactionHistory(HISTORY_LIMIT, HISTORY_THRESHOLD);
+        bgpRouter = BgpRouter.newInstance(this::getConfig, this::isBGPEntityOwner, bgpUpdatesHistory);
+        delayEorSeconds = Integer.parseInt(getProperty(BGP_EOR_DELAY, DEF_BGP_EOR_DELAY));
 
         entityOwnershipUtils = new EntityOwnershipUtils(entityOwnershipService);
 
@@ -259,13 +320,37 @@ public class BgpConfigurationManager {
         initer.countDown();
 
         GlobalEventExecutor.INSTANCE.execute(() -> {
-            final WaitingServiceTracker<IBgpManager> tracker = WaitingServiceTracker.create(
-                    IBgpManager.class, bundleContext);
-            bgpManager = tracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
-            updateServer = new BgpThriftService(Integer.parseInt(updatePort), bgpManager, this);
-            updateServer.start();
-            LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
+            ServiceTracker<IBgpManager, ?> tracker = null;
+            try {
+                tracker = new ServiceTracker<>(bundleContext, IBgpManager.class, null);
+                tracker.open();
+                bgpManager = (IBgpManager) tracker.waitForService(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
+                Preconditions.checkState(bgpManager != null, "IBgpManager service not found");
+            } catch (InterruptedException e) {
+                throw new IllegalStateException("Error retrieving IBgpManager service", e);
+            } finally {
+                if (tracker != null) {
+                    tracker.close();
+                }
+            }
+
+            String updatePort = getProperty(UPDATE_PORT, DEF_UPORT);
+            if (InetAddresses.isInetAddress(getBgpSdncMipIp())) {
+                InetSocketAddress bgpThriftServerSocketAddr = new InetSocketAddress(getBgpSdncMipIp(),
+                        Integer.parseInt(updatePort));
+                bgpThriftService = new BgpThriftService(bgpThriftServerSocketAddr, bgpManager, this);
+                if (isBGPEntityOwner()) {
+                    //I am EoS owner of BGP, opening bgp thrift UPDATE-SERVER port.
+                    LOG.info("BGP Configuration manager initialized: UPDATE-SERVER started");
+                    bgpThriftService.start();
+                }
+                LOG.info("UPDATE server started :ip:port={}:{}", getBgpSdncMipIp(), updatePort);
+            } else {
+                LOG.error("Failed to init UPDATE server invalid ip:port={}:{}", getBgpSdncMipIp(), updatePort);
+            }
         });
+        registerCallbacks();
+        LOG.info("BgpConfigurationManager initialized. IBgpManager={}", bgpManager);
     }
 
     public String getBgpSdncMipIp() {
@@ -288,6 +373,10 @@ public class BgpConfigurationManager {
         this.cfgReplayEndTime = cfgReplayEndTime;
     }
 
+    public TransactionHistory getBgpUpdatesHistory() {
+        return bgpUpdatesHistory;
+    }
+
     public long getCfgReplayStartTime() {
         return cfgReplayStartTime;
     }
@@ -327,8 +416,8 @@ public class BgpConfigurationManager {
         for (Class<?> reactor : REACTORS) {
             Object obj = createListener(reactor);
             if (obj != null) {
-                AsyncDataTreeChangeListenerBase dcl = (AsyncDataTreeChangeListenerBase) obj;
-                dcl.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+                AbstractAsyncDataTreeChangeListener dcl = (AbstractAsyncDataTreeChangeListener) obj;
+                dcl.register();
                 listeners.add(dcl);
             }
         }
@@ -339,8 +428,14 @@ public class BgpConfigurationManager {
     public void close() {
         executor.shutdown();
 
-        if (updateServer != null) {
-            updateServer.stop();
+        if (bgpThriftService != null) {
+            bgpThriftService.stop();
+            bgpThriftService = null;
+        }
+
+        if (isBgpConnected()) {
+            //disconnect the CONFIG SERVER port (which was )opened during I was Owner
+            bgpRouter.disconnect();
         }
 
         if (candidateRegistration != null) {
@@ -379,20 +474,39 @@ public class BgpConfigurationManager {
     private EntityOwnershipListenerRegistration registerEntityListener(
             final EntityOwnershipService entityOwnershipService) {
         return entityOwnershipService.registerListener(BGP_ENTITY_TYPE_FOR_OWNERSHIP, ownershipChange -> {
-            LOG.trace("entity owner change event fired: {}", ownershipChange);
+            LOG.info("entity owner change event fired: {}", ownershipChange);
 
             if (ownershipChange.getState() == EntityOwnershipChangeState.LOCAL_OWNERSHIP_GRANTED) {
-                LOG.trace("This PL is the Owner");
-                activateMIP();
+                LOG.info("This PL is the Owner");
+                if (bgpThriftService != null) {
+                    //opening UPDATE-SERVER port.
+                    bgpThriftService.start();
+                } else {
+                    LOG.error("I am the owner of BGP entity, but bgpThriftService is not initialized yet");
+                }
                 bgpRestarted();
             } else {
-                LOG.debug("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
+                LOG.info("Not owner: hasOwner: {}, isOwner: {}", ownershipChange.getState().hasOwner(),
                         ownershipChange.getState().isOwner());
+                if (bgpThriftService != null && bgpThriftService.isBgpThriftServiceStarted()) {
+                    //close the bgp Thrift Update-SERVER port opened on non-Entity Owner
+                    bgpThriftService.stop();
+                }
+                if (isBgpConnected()) {
+                    //disconnect the CONFIG SERVER port (which was )opened during I was Owner
+                    bgpRouter.disconnect();
+                }
+                stopBgpCountersTask();
+                stopBgpAlarmsTask();
             }
         });
     }
 
     public boolean isBGPEntityOwner() {
+        if (entityOwnershipUtils == null) {
+            LOG.error("entityOwnershipUtils is NULL when listener callbacks fired");
+            return false;
+        }
         return entityOwnershipUtils.isEntityOwner(new Entity(BGP_ENTITY_TYPE_FOR_OWNERSHIP, BGP_ENTITY_NAME), 0, 1);
     }
 
@@ -402,16 +516,19 @@ public class BgpConfigurationManager {
     }
 
     public class ConfigServerReactor
-            extends AsyncDataTreeChangeListenerBase<ConfigServer, ConfigServerReactor>
+            extends AbstractAsyncDataTreeChangeListener<ConfigServer>
             implements ClusteredDataTreeChangeListener<ConfigServer> {
         private static final String YANG_OBJ = "config-server ";
 
         public ConfigServerReactor() {
-            super(ConfigServer.class, ConfigServerReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(ConfigServer.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("ConfigServerReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
+        public void add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
             LOG.trace("received bgp connect config host {}", val.getHost().getValue());
             if (!isBGPEntityOwner()) {
                 return;
@@ -436,17 +553,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected ConfigServerReactor getDataTreeChangeListener() {
-            return ConfigServerReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<ConfigServer> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(ConfigServer.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
+        public void remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
             LOG.trace("received bgp disconnect");
             if (!isBGPEntityOwner()) {
                 return;
@@ -455,12 +562,23 @@ public class BgpConfigurationManager {
             bgpRouter.configServerUpdated();
 
             synchronized (BgpConfigurationManager.this) {
+                if (bgp_as_num != 0) {
+                    try {
+                        bgpRouter.stopBgp(bgp_as_num);
+                        stopBgpCountersTask();
+                        stopBgpAlarmsTask();
+                    } catch (TException | BgpRouterException e) {
+                        LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
+                    }
+                } else {
+                    LOG.debug("bgp as-id is null while removing config-server");
+                }
                 bgpRouter.disconnect();
             }
         }
 
         @Override
-        protected void update(InstanceIdentifier<ConfigServer> iid,
+        public void update(InstanceIdentifier<ConfigServer> iid,
                 ConfigServer oldval, ConfigServer newval) {
             LOG.trace("received bgp Connection update");
             if (!isBGPEntityOwner()) {
@@ -470,6 +588,8 @@ public class BgpConfigurationManager {
         }
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private BgpRouter getClient(String yangObj) {
         if (bgpRouter == null || !bgpRouter.isBgpConnected()) {
             LOG.warn("{}: configuration received when BGP is inactive", yangObj);
@@ -478,27 +598,31 @@ public class BgpConfigurationManager {
         return bgpRouter;
     }
 
-    public class AsIdReactor
-            extends AsyncDataTreeChangeListenerBase<AsId, AsIdReactor>
+    public class AsIdReactor extends AbstractAsyncDataTreeChangeListener<AsId>
             implements ClusteredDataTreeChangeListener<AsId> {
 
         private static final String YANG_OBJ = "as-id ";
 
         public AsIdReactor() {
-            super(AsId.class, AsIdReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(AsId.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("AsIdReactor", LOG));
         }
 
+        @SuppressFBWarnings(value  = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
         @Override
-        protected void add(InstanceIdentifier<AsId> iid, AsId val) {
+        public void add(InstanceIdentifier<AsId> iid, AsId val) {
             LOG.error("received bgp add asid {}", val);
             if (!isBGPEntityOwner()) {
                 return;
             }
             LOG.debug("received add router config asNum {}", val.getLocalAs());
+            bgp_as_num = val.getLocalAs().longValue();
             synchronized (BgpConfigurationManager.this) {
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for asNum {}; {}", YANG_OBJ, val.getLocalAs(),
+                    LOG.debug("{} Unable to process add for asNum {}; {} {}", YANG_OBJ, val.getLocalAs(),
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -510,26 +634,17 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected AsIdReactor getDataTreeChangeListener() {
-            return AsIdReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<AsId> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(AsId.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<AsId> iid, AsId val) {
+        public void remove(InstanceIdentifier<AsId> iid, AsId val) {
             LOG.error("received delete router config asNum {}", val.getLocalAs());
             if (!isBGPEntityOwner()) {
                 return;
             }
             synchronized (BgpConfigurationManager.this) {
-                long asNum = val.getLocalAs();
+                long asNum = val.getLocalAs().toJava();
                 BgpRouter br = getClient(YANG_OBJ);
+                bgp_as_num = 0;
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for asNum {}; {}", YANG_OBJ, asNum,
+                    LOG.debug("{} Unable to process remove for asNum {}; {} {}", YANG_OBJ, asNum,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
@@ -549,10 +664,11 @@ public class BgpConfigurationManager {
                 }
                 LOG.debug("Removing external routes from FIB");
                 deleteExternalFibRoutes();
-                List<Neighbors> nbrs = conf.getNeighbors();
-                if (nbrs != null && nbrs.size() > 0) {
+                Map<NeighborsKey, Neighbors> keyNeighborsMap = conf.getNeighborsContainer() == null ? null
+                        : conf.getNeighborsContainer().getNeighbors();
+                if (keyNeighborsMap != null && keyNeighborsMap.size() > 0) {
                     LOG.error("Tring to remove the as-id when neighbor config is already present");
-                    for (Neighbors nbr : nbrs) {
+                    for (Neighbors nbr : keyNeighborsMap.values()) {
                         LOG.debug("Removing Neighbor {} from Data store", nbr.getAddress().getValue());
                         delNeighbor(nbr.getAddress().getValue());
                     }
@@ -561,7 +677,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<AsId> iid,
+        public void update(InstanceIdentifier<AsId> iid,
                 AsId oldval, AsId newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -570,18 +686,20 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class GracefulRestartReactor
-            extends AsyncDataTreeChangeListenerBase<GracefulRestart, GracefulRestartReactor>
+    public class GracefulRestartReactor extends AbstractAsyncDataTreeChangeListener<GracefulRestart>
             implements ClusteredDataTreeChangeListener<GracefulRestart> {
 
         private static final String YANG_OBJ = "graceful-restart ";
 
         public GracefulRestartReactor() {
-            super(GracefulRestart.class, GracefulRestartReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("GracefulRestartReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
+        public void add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -589,7 +707,7 @@ public class BgpConfigurationManager {
                 int stalePathTime = val.getStalepathTime().intValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.error("{} Unable to add stale-path time {}; {}", YANG_OBJ, stalePathTime,
+                    LOG.error("{} Unable to add stale-path time {}; {} {}", YANG_OBJ, stalePathTime,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -602,17 +720,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected GracefulRestartReactor getDataTreeChangeListener() {
-            return GracefulRestartReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<GracefulRestart> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
+        public void remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -620,7 +728,7 @@ public class BgpConfigurationManager {
             synchronized (BgpConfigurationManager.this) {
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.error("{} Unable to delete stale-path time; {}", YANG_OBJ,
+                    LOG.error("{} Unable to delete stale-path time; {} {}", YANG_OBJ,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
@@ -633,7 +741,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<GracefulRestart> iid,
+        public void update(InstanceIdentifier<GracefulRestart> iid,
                 GracefulRestart oldval, GracefulRestart newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -643,7 +751,7 @@ public class BgpConfigurationManager {
                 int stalePathTime = newval.getStalepathTime().intValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.error("{} Unable to update stale-path time to {}; {}", YANG_OBJ, stalePathTime,
+                    LOG.error("{} Unable to update stale-path time to {}; {} {}", YANG_OBJ, stalePathTime,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -656,25 +764,27 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class LoggingReactor
-            extends AsyncDataTreeChangeListenerBase<Logging, LoggingReactor>
+    public class LoggingReactor extends AbstractAsyncDataTreeChangeListener<Logging>
             implements ClusteredDataTreeChangeListener<Logging> {
 
         private static final String YANG_OBJ = "logging ";
 
         public LoggingReactor() {
-            super(Logging.class, LoggingReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(Logging.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("LoggingReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<Logging> iid, Logging val) {
+        public void add(InstanceIdentifier<Logging> iid, Logging val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
             synchronized (BgpConfigurationManager.this) {
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.error("{} Unable to add logging for qbgp; {}", YANG_OBJ,
+                    LOG.error("{} Unable to add logging for qbgp; {} {}", YANG_OBJ,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -687,17 +797,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected LoggingReactor getDataTreeChangeListener() {
-            return LoggingReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<Logging> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Logging.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<Logging> iid, Logging val) {
+        public void remove(InstanceIdentifier<Logging> iid, Logging val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -705,12 +805,12 @@ public class BgpConfigurationManager {
             synchronized (BgpConfigurationManager.this) {
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.error("{} Unable to remove logging for qbgp; {}", YANG_OBJ,
+                    LOG.error("{} Unable to remove logging for qbgp; {} {}", YANG_OBJ,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
                 try {
-                    br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
+                    br.setLogging(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
                 } catch (TException | BgpRouterException e) {
                     LOG.error("{} Delete received exception; {}", YANG_OBJ, DEL_WARN, e);
                 }
@@ -718,7 +818,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<Logging> iid,
+        public void update(InstanceIdentifier<Logging> iid,
                 Logging oldval, Logging newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -726,7 +826,7 @@ public class BgpConfigurationManager {
             synchronized (BgpConfigurationManager.this) {
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.error("{} Unable to update logging for qbgp; {}", YANG_OBJ,
+                    LOG.error("{} Unable to update logging for qbgp; {} {}", YANG_OBJ,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -739,35 +839,59 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class NeighborsReactor
-            extends AsyncDataTreeChangeListenerBase<Neighbors, NeighborsReactor>
+    public class NeighborsReactor extends AbstractAsyncDataTreeChangeListener<Neighbors>
             implements ClusteredDataTreeChangeListener<Neighbors> {
 
         private static final String YANG_OBJ = "neighbors ";
 
         public NeighborsReactor() {
-            super(Neighbors.class, NeighborsReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("NeighborsReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
+        public void add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
+            if (nbrList != null && !nbrList.contains(val)) {
+                LOG.trace("Adding nbr {} to nbrlist", val.getAddress().getValue());
+                nbrList.add(val);
+            }
             if (!isBGPEntityOwner()) {
                 return;
             }
             LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
             synchronized (BgpConfigurationManager.this) {
                 String peerIp = val.getAddress().getValue();
-                long as = val.getRemoteAs();
+                String sourceIp = (val.getUpdateSource() == null) ? null :
+                                    val.getUpdateSource().getSourceIp().getValue();
+                int nhops = (val.getEbgpMultihop() == null) ? 0 :
+                                    val.getEbgpMultihop().getNhops().intValue();
+                Map<AddressFamiliesKey, AddressFamilies> keyAddressFamiliesMap = val.getAddressFamilies();
+                long as = val.getRemoteAs().toJava();
                 final String md5Secret = extractMd5Secret(val);
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for peer {} as {}; {}", YANG_OBJ, peerIp, as,
+                    LOG.debug("{} Unable to process add for peer {} as {}; {} {}", YANG_OBJ, peerIp, as,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
                 try {
                     //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
                     br.addNeighbor(peerIp, as, md5Secret);
+                    if (nhops != 0) {
+                        br.addEbgpMultihop(peerIp, nhops);
+                    }
+                    if (sourceIp != null) {
+                        br.addUpdateSource(peerIp, sourceIp);
+                    }
+                    if (keyAddressFamiliesMap != null) {
+                        for (AddressFamilies af : keyAddressFamiliesMap.values()) {
+                            af_afi afi = af_afi.findByValue(af.getAfi().intValue());
+                            af_safi safi = af_safi.findByValue(af.getSafi().intValue());
+                            br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
+                        }
+                    }
 
                 } catch (TException | BgpRouterException e) {
                     LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
@@ -776,17 +900,11 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected NeighborsReactor getDataTreeChangeListener() {
-            return NeighborsReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<Neighbors> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Neighbors.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
+        public void remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
+            if (nbrList != null && nbrList.contains(val)) {
+                LOG.trace("Removing nbr {} from nbr list", val.getAddress().getValue());
+                nbrList.remove(val);
+            }
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -795,7 +913,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getAddress().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
@@ -810,11 +928,18 @@ public class BgpConfigurationManager {
                 if (bgpAlarms != null) {
                     bgpAlarms.clearBgpNbrDownAlarm(peerIp);
                 }
+
+                if (bgpUtil.isBfdEnabled()) {
+                    final BgpCounters bgpCounters = getBgpCounters();
+                    if (bgpCounters != null) {
+                        bgpCounters.clearBfdNbrCounters(peerIp);
+                    }
+                }
             }
         }
 
         @Override
-        protected void update(InstanceIdentifier<Neighbors> iid,
+        public void update(InstanceIdentifier<Neighbors> iid,
                 Neighbors oldval, Neighbors newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -823,18 +948,20 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class EbgpMultihopReactor
-            extends AsyncDataTreeChangeListenerBase<EbgpMultihop, EbgpMultihopReactor>
+    public class EbgpMultihopReactor extends AbstractAsyncDataTreeChangeListener<EbgpMultihop>
             implements ClusteredDataTreeChangeListener<EbgpMultihop> {
 
         private static final String YANG_OBJ = "ebgp-multihop ";
 
         public EbgpMultihopReactor() {
-            super(EbgpMultihop.class, EbgpMultihopReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class)
+                    .child(EbgpMultihop.class), org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("EbgpMultihopReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
+        public void add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -843,7 +970,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getPeerIp().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -856,17 +983,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected EbgpMultihopReactor getDataTreeChangeListener() {
-            return EbgpMultihopReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<EbgpMultihop> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(EbgpMultihop.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
+        public void remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -875,7 +992,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getPeerIp().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
@@ -888,7 +1005,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<EbgpMultihop> iid,
+        public void update(InstanceIdentifier<EbgpMultihop> iid,
                 EbgpMultihop oldval, EbgpMultihop newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -897,18 +1014,20 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class UpdateSourceReactor
-            extends AsyncDataTreeChangeListenerBase<UpdateSource, UpdateSourceReactor>
+    public class UpdateSourceReactor extends AbstractAsyncDataTreeChangeListener<UpdateSource>
             implements ClusteredDataTreeChangeListener<UpdateSource> {
 
         private static final String YANG_OBJ = "update-source ";
 
         public UpdateSourceReactor() {
-            super(UpdateSource.class, UpdateSourceReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class)
+                    .child(UpdateSource.class), org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("UpdateSourceReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
+        public void add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -917,7 +1036,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getPeerIp().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -930,17 +1049,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected UpdateSourceReactor getDataTreeChangeListener() {
-            return UpdateSourceReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<UpdateSource> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(UpdateSource.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
+        public void remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -949,7 +1058,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getPeerIp().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
@@ -962,7 +1071,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<UpdateSource> iid,
+        public void update(InstanceIdentifier<UpdateSource> iid,
                 UpdateSource oldval, UpdateSource newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -971,18 +1080,20 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class AddressFamiliesReactor
-            extends AsyncDataTreeChangeListenerBase<AddressFamilies, AddressFamiliesReactor>
+    public class AddressFamiliesReactor extends AbstractAsyncDataTreeChangeListener<AddressFamilies>
             implements ClusteredDataTreeChangeListener<AddressFamilies> {
 
         private static final String YANG_OBJ = "address-families ";
 
         public AddressFamiliesReactor() {
-            super(AddressFamilies.class, AddressFamiliesReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(NeighborsContainer.class).child(Neighbors.class)
+                    .child(AddressFamilies.class), org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("AddressFamiliesReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
+        public void add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -991,7 +1102,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getPeerIp().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process add for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -1006,17 +1117,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected AddressFamiliesReactor getDataTreeChangeListener() {
-            return AddressFamiliesReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<AddressFamilies> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Neighbors.class).child(AddressFamilies.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
+        public void remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -1025,7 +1126,7 @@ public class BgpConfigurationManager {
                 String peerIp = val.getPeerIp().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for peer {}; {}", YANG_OBJ, peerIp,
+                    LOG.debug("{} Unable to process remove for peer {}; {} {}", YANG_OBJ, peerIp,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
@@ -1040,7 +1141,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<AddressFamilies> iid,
+        public void update(InstanceIdentifier<AddressFamilies> iid,
                 AddressFamilies oldval, AddressFamilies newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -1049,23 +1150,19 @@ public class BgpConfigurationManager {
         }
     }
 
-    public class NetworksReactor
-            extends AsyncDataTreeChangeListenerBase<Networks, NetworksReactor>
+    public class NetworksReactor extends AbstractAsyncDataTreeChangeListener<Networks>
             implements ClusteredDataTreeChangeListener<Networks> {
 
         private static final String YANG_OBJ = "networks ";
 
         public NetworksReactor() {
-            super(Networks.class, NetworksReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(NetworksContainer.class).child(Networks.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("NetworksReactor", LOG));
         }
 
-        @Override
-        public NetworksReactor getDataTreeChangeListener() {
-            return NetworksReactor.this;
-        }
-
-        @Override
-        protected void add(InstanceIdentifier<Networks> iid, Networks val) {
+        public void add(InstanceIdentifier<Networks> iid, Networks val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -1076,11 +1173,11 @@ public class BgpConfigurationManager {
                 String nh = val.getNexthop().getValue();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {}", YANG_OBJ, rd, pfxlen, nh,
-                            BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
+                    LOG.debug("{} Unable to process add for rd {} prefix {} nexthop {}; {} {}", YANG_OBJ, rd, pfxlen,
+                            nh, BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
-                Long label = val.getLabel();
+                Long label = val.getLabel().toJava();
                 int lbl = label == null ? qbgpConstants.LBL_NO_LABEL
                         : label.intValue();
                 int l3vni = val.getL3vni() == null ? qbgpConstants.LBL_NO_LABEL
@@ -1105,12 +1202,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected InstanceIdentifier<Networks> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Networks.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<Networks> iid, Networks val) {
+        public void remove(InstanceIdentifier<Networks> iid, Networks val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -1120,11 +1212,11 @@ public class BgpConfigurationManager {
                 String pfxlen = val.getPrefixLen();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for rd {} prefix {}; {}", YANG_OBJ, rd, pfxlen,
+                    LOG.debug("{} Unable to process remove for rd {} prefix {}; {} {}", YANG_OBJ, rd, pfxlen,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
-                Long label = val.getLabel();
+                Long label = val.getLabel().toJava();
                 int lbl = label == null ? 0 : label.intValue();
                 if (rd == null && lbl > 0) {
                     //LU prefix is being deleted.
@@ -1157,7 +1249,7 @@ public class BgpConfigurationManager {
 
 
         @Override
-        protected void update(final InstanceIdentifier<Networks> iid,
+        public void update(final InstanceIdentifier<Networks> iid,
                 final Networks oldval, final Networks newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -1179,18 +1271,20 @@ public class BgpConfigurationManager {
 
     static Timer timer = new Timer();
 
-    public class VrfsReactor
-            extends AsyncDataTreeChangeListenerBase<Vrfs, VrfsReactor>
+    public class VrfsReactor extends AbstractAsyncDataTreeChangeListener<Vrfs>
             implements ClusteredDataTreeChangeListener<Vrfs> {
 
         private static final String YANG_OBJ = "vrfs ";
 
         public VrfsReactor() {
-            super(Vrfs.class, VrfsReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(VrfsContainer.class).child(Vrfs.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("VrfsReactor", LOG));
         }
 
         @Override
-        protected void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
+        public void add(InstanceIdentifier<Vrfs> iid, Vrfs vrfs) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -1199,16 +1293,17 @@ public class BgpConfigurationManager {
                 String rd = vrfs.getRd();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
+                    LOG.debug("{} Unable to process add for rd {}; {} {}", YANG_OBJ, rd,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
                 try {
-                    List<AddressFamiliesVrf> vrfAddrFamilyList = vrfs.getAddressFamiliesVrf();
-                    for (AddressFamiliesVrf vrfAddrFamily : vrfAddrFamilyList) {
+                    Map<AddressFamiliesVrfKey, AddressFamiliesVrf> keyAddressFamiliesVrfMap
+                            = vrfs.getAddressFamiliesVrf();
+                    for (AddressFamiliesVrf vrfAddrFamily : keyAddressFamiliesVrfMap.values()) {
                         /*add to br the new vrfs arguments*/
-                        br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(), vrfs.getExportRts(),
-                                vrfAddrFamily.getAfi(), vrfAddrFamily.getSafi());
+                        br.addVrf(BgpUtil.getLayerType(vrfAddrFamily), rd, vrfs.getImportRts(),
+                                vrfs.getExportRts(), vrfAddrFamily.getAfi().toJava(), vrfAddrFamily.getSafi().toJava());
                     }
                     /*add to br the vrfs contained in mapNewAdFamily*/
                     List<AddressFamiliesVrf> vrfAddrFamilyListFromMap = mapNewAdFamily.get(rd);
@@ -1217,12 +1312,12 @@ public class BgpConfigurationManager {
                     }
 
                     for (AddressFamiliesVrf adf : vrfAddrFamilyListFromMap) {
-                        if (vrfAddrFamilyList.contains(adf)) {
+                        if (keyAddressFamiliesVrfMap.values().contains(adf)) {
                             mapNewAdFamily.remove(rd);
                         } else  if (adf != null) {
 
-                            br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(), vrfs.getExportRts(),
-                                    adf.getAfi(), adf.getSafi());
+                            br.addVrf(BgpUtil.getLayerType(adf), rd, vrfs.getImportRts(),
+                                    vrfs.getExportRts(), adf.getAfi().toJava(), adf.getSafi().toJava());
                             // remove AddressFamiliesVrf which was already added to BGP
                             vrfAddrFamilyListFromMap.remove(adf);
                             if (vrfAddrFamilyListFromMap.isEmpty()) {
@@ -1233,23 +1328,13 @@ public class BgpConfigurationManager {
                         }
                     }
                 } catch (TException | BgpRouterException e) {
-                    LOG.error("{} get {}, Add received exception; {}", YANG_OBJ, ADD_WARN, e);
+                    LOG.error("{} get {}, Add received exception", YANG_OBJ, ADD_WARN, e);
                 }
             }
         }
 
         @Override
-        protected VrfsReactor getDataTreeChangeListener() {
-            return VrfsReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<Vrfs> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Vrfs.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
+        public void remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -1258,15 +1343,15 @@ public class BgpConfigurationManager {
                 String rd = val.getRd();
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process remove for rd {}; {}", YANG_OBJ, rd,
+                    LOG.debug("{} Unable to process remove for rd {}; {} {}", YANG_OBJ, rd,
                             BgpRouterException.BGP_ERR_NOT_INITED, DEL_WARN);
                     return;
                 }
                 try {
                     List<AddressFamiliesVrf> adf = mapNewAdFamily.get(rd);
                     adf = adf != null ? adf : new ArrayList<>();
-                    for (AddressFamiliesVrf s : val.getAddressFamiliesVrf()) {
-                        br.delVrf(rd, s.getAfi(), s.getSafi());
+                    for (AddressFamiliesVrf s : val.getAddressFamiliesVrf().values()) {
+                        br.delVrf(rd, s.getAfi().toJava(), s.getSafi().toJava());
                         adf.remove(s);// remove in the map the vrf in waiting for advertise quagga
                     }
                     if (adf.isEmpty()) {
@@ -1279,7 +1364,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<Vrfs> iid,
+        public void update(InstanceIdentifier<Vrfs> iid,
                 Vrfs oldval, Vrfs newval) {
             if (oldval != null && newval != null) {
                 LOG.debug("received update Vrfs config val {}, VRFS: Update getting triggered for VRFS rd {}",
@@ -1298,11 +1383,13 @@ public class BgpConfigurationManager {
             List<AddressFamiliesVrf> newlistAdFamilies = new ArrayList<>();
             if (oldval != null) {
                 oldlistAdFamilies = oldval.getAddressFamiliesVrf() == null
-                        ? new ArrayList<>() : oldval.getAddressFamiliesVrf();
+                        ? new ArrayList<>()
+                        : new ArrayList<AddressFamiliesVrf>(oldval.getAddressFamiliesVrf().values());
             }
             if (newval != null) {
                 newlistAdFamilies = newval.getAddressFamiliesVrf() == null
-                        ? new ArrayList<>() : newval.getAddressFamiliesVrf();
+                        ? new ArrayList<>()
+                        : new ArrayList<AddressFamiliesVrf>(newval.getAddressFamiliesVrf().values());
             }
             /*find old AddressFamily to remove from new configuration*/
             for (AddressFamiliesVrf adVrf : oldlistAdFamilies) {
@@ -1320,7 +1407,7 @@ public class BgpConfigurationManager {
             if (rd != null) {
                 BgpRouter br = getClient(YANG_OBJ);
                 if (br == null) {
-                    LOG.debug("{} Unable to process add for rd {}; {}", YANG_OBJ, rd,
+                    LOG.debug("{} Unable to process add for rd {}; {} {}", YANG_OBJ, rd,
                             BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
                     return;
                 }
@@ -1329,7 +1416,7 @@ public class BgpConfigurationManager {
                     try {
                         LOG.debug("call addVRf rd {} afi {} safi {}", rd, adfvrf.getAfi(), adfvrf.getSafi());
                         br.addVrf(BgpUtil.getLayerType(adfvrf), rd, newval.getImportRts(),
-                                newval.getExportRts(), adfvrf.getAfi(), adfvrf.getSafi());
+                                newval.getExportRts(),adfvrf.getAfi().toJava(), adfvrf.getSafi().toJava());
                     } catch (TException | BgpRouterException e) {
                         LOG.error("{} Add received exception; {}", YANG_OBJ, ADD_WARN, e);
                     }
@@ -1338,7 +1425,7 @@ public class BgpConfigurationManager {
                 for (AddressFamiliesVrf adfToDel : adFamilyVrfToDel) {
                     try {
                         LOG.debug("call delVRf rd {} afi {} safi {}", rd, adfToDel.getAfi(), adfToDel.getSafi());
-                        br.delVrf(rd, adfToDel.getAfi(), adfToDel.getSafi());
+                        br.delVrf(rd, adfToDel.getAfi().toJava(), adfToDel.getSafi().toJava());
                     } catch (TException | BgpRouterException e) {
                         LOG.error("{} delVrf received exception; {}", YANG_OBJ, ADD_WARN, e);
                     }
@@ -1347,31 +1434,19 @@ public class BgpConfigurationManager {
         }
     }
 
-    protected void activateMIP() {
-        try {
-            LOG.trace("BgpReactor: Executing MIP Activate command");
-            Runtime.getRuntime().exec("cluster ip -a sdnc_bgp_mip");
-            Runtime.getRuntime().exec("cluster ip -a sdnc_os_mip");
-            LOG.trace("bgpMIP Activated");
-
-        } catch (IOException io) {
-            LOG.error("IO Exception got while activating mip: {}", io.getMessage());
-        }
-    }
-
-    public class BgpReactor
-            extends AsyncDataTreeChangeListenerBase<Bgp, BgpReactor>
+    public class BgpReactor extends AbstractAsyncDataTreeChangeListener<Bgp>
             implements ClusteredDataTreeChangeListener<Bgp> {
 
         private static final String YANG_OBJ = "Bgp ";
 
         public BgpReactor() {
-            super(Bgp.class, BgpReactor.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Bgp.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("BgpReactor", LOG));
         }
 
-
         @Override
-        protected void add(InstanceIdentifier<Bgp> iid, Bgp val) {
+        public void add(InstanceIdentifier<Bgp> iid, Bgp val) {
             LOG.debug("received add Bgp config");
 
             try {
@@ -1384,22 +1459,11 @@ public class BgpConfigurationManager {
                 if (!isBGPEntityOwner()) {
                     return;
                 }
-                activateMIP();
             }
         }
 
         @Override
-        protected BgpReactor getDataTreeChangeListener() {
-            return BgpReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<Bgp> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
+        public void remove(InstanceIdentifier<Bgp> iid, Bgp val) {
             if (!isBGPEntityOwner()) {
                 return;
             }
@@ -1409,7 +1473,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void update(InstanceIdentifier<Bgp> iid,
+        public void update(InstanceIdentifier<Bgp> iid,
                 Bgp oldval, Bgp newval) {
             if (!isBGPEntityOwner()) {
                 return;
@@ -1420,39 +1484,30 @@ public class BgpConfigurationManager {
     }
 
     @SuppressWarnings("deprecation")
-    public class MultipathReactor
-            extends AsyncDataTreeChangeListenerBase<Multipath, MultipathReactor>
+    public class MultipathReactor extends AbstractAsyncDataTreeChangeListener<Multipath>
             implements ClusteredDataTreeChangeListener<Multipath> {
 
         private static final String YANG_OBJ = "multipath ";
 
         public MultipathReactor() {
-            super(Multipath.class, MultipathReactor.class);
-        }
-
-
-        @Override
-        protected MultipathReactor getDataTreeChangeListener() {
-            return MultipathReactor.this;
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Bgp.class)
+                    .child(MultipathContainer.class).child(Multipath.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("MultipathReactor", LOG));
         }
 
         @Override
-        protected InstanceIdentifier<Multipath> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(Multipath.class);
-        }
-
-        @Override
-        protected void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
+        public void remove(InstanceIdentifier<Multipath> iid, Multipath val) {
             executor.execute(new MultipathStatusChange(val));
         }
 
         @Override
-        protected void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
+        public void update(InstanceIdentifier<Multipath> iid, Multipath oldval, Multipath newval) {
             executor.execute(new MultipathStatusChange(newval));
         }
 
         @Override
-        protected void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
+        public void add(InstanceIdentifier<Multipath> key, Multipath dataObjectModification) {
             executor.execute(new MultipathStatusChange(dataObjectModification));
         }
 
@@ -1482,7 +1537,7 @@ public class BgpConfigurationManager {
                                     br.disableMultipath(afi, safi);
                                 }
                             } catch (TException | BgpRouterException e) {
-                                LOG.error(YANG_OBJ + " received exception: \"" + e + "\"");
+                                LOG.error("{} received exception", YANG_OBJ, e);
                             }
                         }
                     }
@@ -1498,25 +1553,16 @@ public class BgpConfigurationManager {
     }
 
     @SuppressWarnings("deprecation")
-    public class VrfMaxpathReactor
-            extends AsyncDataTreeChangeListenerBase<VrfMaxpath, VrfMaxpathReactor>
+    public class VrfMaxpathReactor extends AbstractAsyncDataTreeChangeListener<VrfMaxpath>
             implements ClusteredDataTreeChangeListener<VrfMaxpath> {
 
         private static final String YANG_OBJ = "vrfMaxpath ";
 
         public VrfMaxpathReactor() {
-            super(VrfMaxpath.class, VrfMaxpathReactor.class);
-        }
-
-
-        @Override
-        protected VrfMaxpathReactor getDataTreeChangeListener() {
-            return VrfMaxpathReactor.this;
-        }
-
-        @Override
-        protected InstanceIdentifier<VrfMaxpath> getWildCardPath() {
-            return InstanceIdentifier.create(Bgp.class).child(VrfMaxpath.class);
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    InstanceIdentifier.create(Bgp.class).child(VrfMaxpathContainer.class).child(VrfMaxpath.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("VrfMaxpathReactor", LOG));
         }
 
         class VrfMaxPathConfigurator implements Runnable {
@@ -1534,12 +1580,11 @@ public class BgpConfigurationManager {
                         BgpRouter br = getClient(YANG_OBJ);
                         if (br != null) {
                             try {
-                                br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths());
-                                LOG.debug("Maxpath for vrf: " + vrfMaxpathVal.getRd() + " : is "
-                                        vrfMaxpathVal.getMaxpaths());
+                                br.multipaths(vrfMaxpathVal.getRd(), vrfMaxpathVal.getMaxpaths().toJava());
+                                LOG.debug("Maxpath for vrf {} is {}", vrfMaxpathVal.getRd(),
+                                        vrfMaxpathVal.getMaxpaths());
                             } catch (TException | BgpRouterException e) {
-                                LOG.error(YANG_OBJ
-                                        + " received exception: \"" + e + "\"");
+                                LOG.error("{} received exception", YANG_OBJ, e);
                             }
                         }
                     }
@@ -1548,12 +1593,24 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
-            executor.execute(new VrfMaxPathConfigurator(vrfMaxPathVal));
+        public void remove(InstanceIdentifier<VrfMaxpath> iid, VrfMaxpath vrfMaxPathVal) {
+            if (isBGPEntityOwner()) {
+                synchronized (BgpConfigurationManager.this) {
+                    BgpRouter br = getClient(YANG_OBJ);
+                    if (br != null) {
+                        try {
+                            br.multipaths(vrfMaxPathVal.getRd(), BgpConstants.BGP_DEFAULT_MULTIPATH);
+                            LOG.debug("Del Maxpath for vrf: {} ", vrfMaxPathVal.getRd());
+                        } catch (TException | BgpRouterException e) {
+                            LOG.error(YANG_OBJ + " del received exception:", e);
+                        }
+                    }
+                }
+            }
         }
 
         @Override
-        protected void update(InstanceIdentifier<VrfMaxpath> iid,
+        public void update(InstanceIdentifier<VrfMaxpath> iid,
                               VrfMaxpath oldval, VrfMaxpath newval) {
             if (!Objects.equals(oldval.getMaxpaths(), newval.getMaxpaths())) {
                 executor.execute(new VrfMaxPathConfigurator(newval));
@@ -1561,7 +1618,7 @@ public class BgpConfigurationManager {
         }
 
         @Override
-        protected void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
+        public void add(InstanceIdentifier<VrfMaxpath> instanceIdentifier, VrfMaxpath vrfMaxpathVal) {
             executor.execute(new VrfMaxPathConfigurator(vrfMaxpathVal));
         }
 
@@ -1571,6 +1628,87 @@ public class BgpConfigurationManager {
         }
     }
 
+    public class BfdConfigReactor extends AbstractAsyncDataTreeChangeListener<BfdConfig>
+            implements ClusteredDataTreeChangeListener<BfdConfig> {
+
+        private static final String YANG_OBJ = "BfdConfig ";
+
+        public BfdConfigReactor() {
+            super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(BfdConfig.class),
+                    org.opendaylight.infrautils.utils.concurrent.Executors
+                            .newListeningSingleThreadExecutor("BfdConfigReactor", LOG));
+        }
+
+        @Override
+        public void add(InstanceIdentifier<BfdConfig> iid, BfdConfig val) {
+            if (!isBGPEntityOwner()) {
+                return;
+            }
+            BgpRouter br = getClient(YANG_OBJ);
+            LOG.debug("received bfd config: bfd enabled {} min-rx {} min-tx {} detect-mul {} mhop {}",
+                    val.isBfdEnabled(), val.getMinRx(), val.getMinTx(),
+                    val.getDetectMult(), val.isMultihop());
+            if (br == null) {
+                LOG.debug(YANG_OBJ + "{} Unable to process add  {}",
+                        BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
+                return;
+            }
+            if (val.isBfdEnabled() == false) {
+                LOG.debug("BFD not enabled. Ignoring the config add");
+                return;
+            }
+            int minRx = val.getMinRx().intValue();
+            int minTx = val.getMinTx().intValue();
+            int detectMult = val.getDetectMult().intValue();
+            boolean multiHop = val.isMultihop();
+            try {
+                br.addBfd(detectMult, minRx, minTx,multiHop);
+            } catch (TException | BgpRouterException e) {
+                LOG.error("{} get {}, Add received exception;", YANG_OBJ, ADD_WARN, e);
+            }
+        }
+
+        @Override
+        public void remove(InstanceIdentifier<BfdConfig> iid, BfdConfig val) {
+            if (!isBGPEntityOwner()) {
+                return;
+            }
+            LOG.debug("received bfd config removal");
+            BgpRouter br = getClient(YANG_OBJ);
+            if (br == null) {
+                LOG.debug("{} Unable to process del {}  {}", YANG_OBJ,
+                        BgpRouterException.BGP_ERR_NOT_INITED, ADD_WARN);
+                return;
+            }
+            try {
+                br.delBfd();
+            } catch (TException | BgpRouterException e) {
+                LOG.error("{} get {}, Del received exception;", YANG_OBJ, ADD_WARN, e);
+            }
+
+        }
+
+        @Override
+        public void update(InstanceIdentifier<BfdConfig> iid,
+                              BfdConfig oldval, BfdConfig newval) {
+            LOG.debug("received bfd config: updated oldval bfd enabled {}"
+                    + "min-rx {} min-tx {} detect-mul {} mhop {}",
+                    oldval.isBfdEnabled(), oldval.getMinRx(), oldval.getMinTx(),
+                    oldval.getDetectMult(), oldval.isMultihop());
+            LOG.debug("received bfd config: updated newval bfd enabled {}"
+                    + "min-rx {} min-tx {} detect-mul {} mhop {}",
+                    newval.isBfdEnabled(), newval.getMinRx(), newval.getMinTx(),
+                    newval.getDetectMult(), newval.isMultihop());
+            if (oldval.isBfdEnabled()) {
+                LOG.debug("deleting bfd config on an update");
+                remove(iid, oldval);
+            }
+            LOG.debug("adding bfd config on an update");
+            add(iid, newval);
+        }
+    }
+
+
     public boolean isIpAvailable(String odlip) {
 
         try {
@@ -1599,15 +1737,24 @@ public class BgpConfigurationManager {
     public long getStalePathtime(int defValue, AsId asId) {
         long spt = 0;
         try {
-            spt = getConfig().getGracefulRestart().getStalepathTime();
+            InstanceIdentifier<GracefulRestart> id =
+                    InstanceIdentifier.create(Bgp.class).child(GracefulRestart.class);
+            Optional<GracefulRestart> gracefulRestartOptional = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+                    LogicalDatastoreType.CONFIGURATION, id);
+            if (gracefulRestartOptional.isPresent()) {
+                spt = gracefulRestartOptional.get().getStalepathTime().toJava();
+            }
         } catch (NullPointerException e) {
             try {
-                spt = asId.getStalepathTime();
+                spt = asId.getStalepathTime().toJava();
                 LOG.trace("BGP config/Stale-path time is not set using graceful");
             } catch (NullPointerException ignore) {
                 LOG.trace("BGP AS id is not set using graceful");
                 spt = defValue;
             }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.trace("Exception while reading GracefulRestart DS for the As {}", asId.getStalepathTime());
+            spt = defValue;
         }
         if (spt == 0) {
             LOG.trace("BGP config/Stale-path time is not set using graceful/start-bgp");
@@ -1617,7 +1764,7 @@ public class BgpConfigurationManager {
     }
 
     public static boolean isValidConfigBgpHostPort(String bgpHost, int bgpPort) {
-        if (!bgpHost.equals(DEF_CHOST) && bgpPort != Integer.parseInt(DEF_CPORT)) {
+        if (!bgpHost.equals(DEF_CHOST)) {
             return true;
         } else {
             return false;
@@ -1654,11 +1801,12 @@ public class BgpConfigurationManager {
                 setCfgReplayEndTime(System.currentTimeMillis());
                 LOG.info("took {} msecs for bgp replay ", getCfgReplayEndTime() - getCfgReplayStartTime());
                 if (replaySucceded) {
-                    LOG.info("starting the stale cleanup timer");
                     long routeSyncTime = getStalePathtime(BGP_RESTART_ROUTE_SYNC_SEC, config.getAsId());
                     setStaleCleanupTime(routeSyncTime);
+                    LOG.error("starting the stale cleanup timer: {} seconds", routeSyncTime);
                     routeCleanupFuture = executor.schedule(new RouteCleanup(), routeSyncTime, TimeUnit.SECONDS);
                 } else {
+                    LOG.error("skipping stale cleanup, may be due to exception while replay");
                     staledFibEntriesMap.clear();
                 }
             } catch (InterruptedException | TimeoutException | ExecutionException eCancel) {
@@ -1669,7 +1817,8 @@ public class BgpConfigurationManager {
     }
 
     private boolean previousReplayJobInProgress() {
-        return lastReplayJobFt != null && !lastReplayJobFt.isDone();
+        return ((lastReplayJobFt != null && !lastReplayJobFt.isDone())
+                || (routeCleanupFuture != null && !routeCleanupFuture.isDone()));
     }
 
     private void cancelPreviousReplayJob() {
@@ -1692,16 +1841,17 @@ public class BgpConfigurationManager {
     }
 
     private void doRouteSync() {
-        LOG.error("Starting BGP route sync");
-        try {
-            bgpRouter.initRibSync(bgpSyncHandle);
-        } catch (BgpRouterException e) {
-            LOG.error("Route sync aborted, exception when initializing", e);
-            return;
-        }
-        while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
-            for (af_afi afi : af_afi.values()) {
+        for (af_afi afi : af_afi.values()) {
+            try {
+                bgpRouter.initRibSync(bgpSyncHandle);
+            } catch (BgpRouterException e) {
+                LOG.error("Route sync aborted, exception when initializing", e);
+                return;
+            }
+            LOG.error("Starting BGP route sync for afi {}", afi.getValue());
+            while (bgpSyncHandle.getState() != BgpSyncHandle.DONE) {
                 Routes routes = null;
+                int noUpdates = 0;
                 try {
                     routes = bgpRouter.doRibSync(bgpSyncHandle, afi);
                 } catch (TException | BgpRouterException e) {
@@ -1710,6 +1860,7 @@ public class BgpConfigurationManager {
                 }
                 Iterator<Update> updates = routes.getUpdatesIterator();
                 while (updates.hasNext()) {
+                    noUpdates++;
                     Update update = updates.next();
                     String rd = update.getRd();
                     String nexthop = update.getNexthop();
@@ -1726,30 +1877,29 @@ public class BgpConfigurationManager {
                     // use "rd" to query vrf table and obtain the protocol_type.
                     // Currently using PROTOCOL_EVPN as default.
                     onUpdatePushRoute(
-                           protocol_type.PROTOCOL_EVPN,
+                           protocol_type.PROTOCOL_L3VPN,
                            rd,
                            prefix,
                            plen,
                            nexthop,
-                           update.getEthtag(),
-                           update.getEsi(),
                            update.getMacaddress(),
-                           label,
-                           l2label,
+                           Uint32.valueOf(label),
+                           Uint32.valueOf(l2label),
                            update.getRoutermac(),
                            afi);
                 }
+                LOG.error("No of updates for afi {} is {}", afi.getValue(), noUpdates);
             }
         }
         try {
             LOG.error("Ending BGP route-sync");
             bgpRouter.endRibSync(bgpSyncHandle);
         } catch (BgpRouterException e) {
-            // Ignored?
+            LOG.error("Route sync aborted, exception when ending", e);
         }
     }
 
-    public void addTepToElanDS(String rd, String tepIp, String mac, Long l2vni) {
+    public void addTepToElanDS(String rd, String tepIp, String mac, Uint32 l2vni) {
         boolean needUpdate = addToRt2TepMap(rd, tepIp, mac, l2vni);
         if (needUpdate) {
             LOG.info("Adding tepIp {} with RD {} to ELan DS", tepIp, rd);
@@ -1780,10 +1930,13 @@ public class BgpConfigurationManager {
      */
 
     public void onUpdatePushRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
-            int ethtag, String esi, String macaddress, int label, int l2label, String routermac, af_afi afi) {
+                                  String macaddress, Uint32 label, Uint32 l2label, String routermac, af_afi afi) {
+        PrefixUpdateEvent prefixUpdateEvent = new PrefixUpdateEvent(protocolType,rd,prefix,plen,nextHop,
+                macaddress,label,l2label,routermac,afi);
+        bgpUpdatesHistory.addToHistory(TransactionType.ADD, prefixUpdateEvent);
         boolean addroute = false;
         boolean macupdate = false;
-        long l3vni = 0L;
+        Uint32 l3vni = Uint32.ZERO;
         VrfEntry.EncapType encapType = VrfEntry.EncapType.Mplsgre;
         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
             encapType = VrfEntry.EncapType.Vxlan;
@@ -1792,7 +1945,7 @@ public class BgpConfigurationManager {
                 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
                     LOG.info("Got RT2 route for RD {} l3label {} l2label {} from tep {} with mac {} remote RD {}",
                             vpnInstanceOpDataEntry.getVpnInstanceName(), label, l2label, nextHop, macaddress, rd);
-                    addTepToElanDS(rd, nextHop, macaddress, (long)l2label);
+                    addTepToElanDS(rd, nextHop, macaddress, l2label);
                     macupdate = true;
                 } else {
                     l3vni = vpnInstanceOpDataEntry.getL3vni();
@@ -1805,10 +1958,10 @@ public class BgpConfigurationManager {
 
         if (!staledFibEntriesMap.isEmpty()) {
             // restart Scenario, as MAP is not empty.
-            Map<String, Long> map = staledFibEntriesMap.get(rd);
+            Map<String, Uint32> map = staledFibEntriesMap.get(rd);
             if (map != null) {
                 String prefixNextHop = appendNextHopToPrefix(prefix + "/" + plen, nextHop);
-                Long labelInStaleMap = map.get(prefixNextHop);
+                Uint32 labelInStaleMap = map.get(prefixNextHop);
                 if (null == labelInStaleMap) {
                     // New Entry, which happened to be added during restart.
                     addroute = true;
@@ -1838,7 +1991,7 @@ public class BgpConfigurationManager {
                     rd, prefix, nextHop, label, afi);
             // TODO: modify addFibEntryToDS signature
             List<String> nextHopList = Collections.singletonList(nextHop);
-            fibDSWriter.addFibEntryToDS(rd, macaddress, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
+            fibDSWriter.addFibEntryToDS(rd, prefix + "/" + plen, nextHopList, encapType, label, l3vni,
                                         routermac, RouteOrigin.BGP);
             LOG.info("ADD: Added Fib entry rd {} prefix {} nexthop {} label {}", rd, prefix, nextHop, label);
             String vpnName = bgpUtil.getVpnNameFromRd(rd);
@@ -1851,17 +2004,19 @@ public class BgpConfigurationManager {
 
     public void onUpdateWithdrawRoute(protocol_type protocolType, String rd, String prefix, int plen, String nextHop,
             String macaddress) {
-        long vni = 0L;
+        PrefixWithdrawEvent prefixWithdrawEvent = new PrefixWithdrawEvent(protocolType,rd,prefix,plen,
+                nextHop,macaddress);
+        bgpUpdatesHistory.addToHistory(TransactionType.ADD, prefixWithdrawEvent);
         boolean macupdate = false;
         if (protocolType.equals(protocol_type.PROTOCOL_EVPN)) {
             VpnInstanceOpDataEntry vpnInstanceOpDataEntry = bgpUtil.getVpnInstanceOpData(rd);
             if (vpnInstanceOpDataEntry != null) {
-                vni = vpnInstanceOpDataEntry.getL3vni();
+                Uint32 vni = vpnInstanceOpDataEntry.getL3vni();
                 if (vpnInstanceOpDataEntry.getType() == VpnInstanceOpDataEntry.Type.L2) {
-                    LOG.debug("Got RT2 withdraw for RD %s from tep %s with mac %s remote RD %s",
+                    LOG.debug("Got RT2 withdraw for RD {} {} from tep {} with mac {} remote RD {}",
                             vpnInstanceOpDataEntry.getVpnInstanceName(), vni, nextHop, macaddress, rd);
                     deleteTepfromElanDS(rd, nextHop, macaddress);
-                    LOG.debug("For rd %s. skipping fib update", rd);
+                    LOG.debug("For rd {}. skipping fib update", rd);
                     macupdate = true;
                 }
             } else {
@@ -1886,13 +2041,39 @@ public class BgpConfigurationManager {
         fibDSWriter.removeOrUpdateFibEntryFromDS(rd, prefix + "/" + plen, nexthop);
         String vpnName = bgpUtil.getVpnNameFromRd(rd);
         if (vpnName != null) {
-            vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, 0 /*INVALID_LABEL*/,
+            vpnLinkService.leakRouteIfNeeded(vpnName, prefix, null /*nextHopList*/, Uint32.ZERO /*INVALID_LABEL*/,
                                              RouteOrigin.BGP, NwConstants.DEL_FLOW);
         }
     }
 
-    private static boolean isRouteModified(int label, Long labelInStaleMap) {
-        return labelInStaleMap != null && !labelInStaleMap.equals(Long.valueOf(label));
+    public void peerDown(String ipAddress, long asNumber) {
+        PeerDownEvent peerDownEvent = new PeerDownEvent(ipAddress,asNumber);
+        bgpUpdatesHistory.addToHistory(TransactionType.ADD, peerDownEvent);
+        List<String> tepIpList = bgpUtil.getDcgwTepConfig(ipAddress);
+        if (tepIpList == null) {
+            LOG.error("No Tep IP configured for DCGW {} on a peerDown", ipAddress);
+            return;
+        }
+        tepIpList.forEach(tepIp -> {
+            bgpUtil.removeOrUpdateLBGroups(tepIp, NwConstants.MOD_FLOW);
+        });
+    }
+
+    public void peerUp(String ipAddress, long asNumber) {
+        PeerUpEvent peerUpEvent = new PeerUpEvent(ipAddress,asNumber);
+        bgpUpdatesHistory.addToHistory(TransactionType.ADD, peerUpEvent);
+        List<String> tepIpList = bgpUtil.getDcgwTepConfig(ipAddress);
+        if (tepIpList == null) {
+            LOG.error("No Tep IP configured for DCGW {} on a peerUp", ipAddress);
+            return;
+        }
+        tepIpList.forEach(tepIp -> {
+            bgpUtil.removeOrUpdateLBGroups(tepIp, NwConstants.MOD_FLOW);
+        });
+    }
+
+    private static boolean isRouteModified(Uint32 label, Uint32 labelInStaleMap) {
+        return labelInStaleMap != null && !labelInStaleMap.equals(label);
     }
 
     static class ReplayNbr {
@@ -1943,79 +2124,74 @@ public class BgpConfigurationManager {
                     final String md5password = extractMd5Secret(replayNbr.getNbr());
                     br.addNeighbor(replayNbr.getNbr().getAddress().getValue(),
                             replayNbr.getNbr().getRemoteAs().longValue(), md5password);
-                    UpdateSource us = replayNbr.getNbr().getUpdateSource();
-                    if (us != null) {
-                        LOG.debug("Replaying updatesource along with nbr: {} US-ip: {} to peer {}",
-                                replayNbr.getNbr().getAddress().getValue(),
-                                us.getSourceIp().getValue(),
-                                us.getPeerIp().getValue());
-                        br.addUpdateSource(us.getPeerIp().getValue(),
-                                us.getSourceIp().getValue());
-                    }
                     replayDone = true;
+                } catch (TApplicationException tae) {
+                    LOG.debug("Replaying addNbr {}, tapplicationexception: ",
+                            replayNbr.getNbr().getAddress().getValue(), tae);
+                    if (tae.getType() == BgpRouterException.BGP_ERR_PEER_EXISTS) {
+                        LOG.debug("Replaying addNbr Neighbor already present");
+                        replayDone = true;
+                    } else {
+                        LOG.error("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), tae);
+                    }
                 } catch (TException | BgpRouterException eNbr) {
                     LOG.debug("Replaying addNbr {}, exception: ", replayNbr.getNbr().getAddress().getValue(), eNbr);
                 }
-                boolean replaySuccess = true;
-                replaySuccess = replaySuccess && replayDone;
+
                 LOG.debug("Replay addNbr {} successful", replayNbr.getNbr().getAddress().getValue());
 
                 //Update Source handling
                 UpdateSource us = replayNbr.getNbr().getUpdateSource();
-                if (replayDone == false && us != null) {
+                if (us != null) {
                     LOG.debug("Replaying updatesource {} to peer {}", us.getSourceIp().getValue(),
                             us.getPeerIp().getValue());
-                    replayDone = false;
                     try {
                         br.addUpdateSource(us.getPeerIp().getValue(),
                                 us.getSourceIp().getValue());
-                        replayDone = true;
                     } catch (TException | BgpRouterException eUs) {
                         LOG.debug("Replaying UpdateSource for Nbr {}, exception:",
                                 replayNbr.getNbr().getAddress().getValue(), eUs);
                     }
                     LOG.debug("Replay updatesource {} successful", us.getSourceIp().getValue());
-                    replaySuccess = replaySuccess && replayDone;
                 }
                 //Ebgp Multihope
                 EbgpMultihop en = replayNbr.getNbr().getEbgpMultihop();
                 if (en != null) {
-                    replayDone = false;
                     try {
                         br.addEbgpMultihop(en.getPeerIp().getValue(),
                                 en.getNhops().intValue());
-                        replayDone = true;
                     } catch (TException | BgpRouterException eEbgpMhop) {
                         LOG.debug("Replaying EbgpMultihop for Nbr {}, exception: ",
                                 replayNbr.getNbr().getAddress().getValue(), eEbgpMhop);
                     }
-                    replaySuccess = replaySuccess && replayDone;
                 }
 
-                //afs
-                List<AddressFamilies> afs = replayNbr.getNbr().getAddressFamilies();
-                if (afs != null) {
-                    for (AddressFamilies af : afs) {
+                //keyAddressFamiliesMap
+                Map<AddressFamiliesKey, AddressFamilies> keyAddressFamiliesMap
+                        = replayNbr.getNbr().getAddressFamilies();
+                if (keyAddressFamiliesMap != null) {
+                    for (AddressFamilies af : keyAddressFamiliesMap.values()) {
                         af_afi afi = af_afi.findByValue(af.getAfi().intValue());
                         af_safi safi = af_safi.findByValue(af.getSafi().intValue());
-                        replayDone = false;
                         try {
                             br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
-                            replayDone = true;
                         } catch (TException | BgpRouterException eAFs) {
                             LOG.debug("Replaying AddressFamily for Nbr {}, exception:",
                                     replayNbr.getNbr().getAddress().getValue(), eAFs);
                         }
-                        replaySuccess = replaySuccess && replayDone;
                     }
                 }
                 //replay is success --> no need to replay this nbr in next iteration.
-                replayNbr.setShouldRetry(replaySuccess ? false : true);
+                replayNbr.setShouldRetry(replayDone ? false : true);
             }
         } while (nbrRetry.decrementAndRetry());
         boolean replaySuccess = true;
         for (ReplayNbr replayNbr : replayNbrList) {
             replaySuccess = replaySuccess && !replayNbr.isShouldRetry();
+            if (replaySuccess == false) {
+                LOG.error("replayNbrConfig: will be cancelling stale cleanup, cfg nbr: {} Failed:",
+                        replayNbr.getNbr().getAddress().getValue());
+            }
         }
         return replaySuccess;
     }
@@ -2042,8 +2218,8 @@ public class BgpConfigurationManager {
         while (0 != bgpDSretryCount.decrementAndGet()) {
             try {
                 return SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                        InstanceIdentifier.create(Bgp.class)).orNull();
-            } catch (ReadFailedException e) {
+                        InstanceIdentifier.create(Bgp.class)).orElse(null);
+            } catch (InterruptedException | ExecutionException e) {
                 //Config DS may not be up, so sleep for 1 second and retry
                 LOG.debug("failed to get bgp config, may be DS is yet in consistent state(?)", e);
                 try {
@@ -2061,16 +2237,13 @@ public class BgpConfigurationManager {
     @SuppressWarnings("checkstyle:IllegalCatch")
     public synchronized boolean replay() throws InterruptedException, TimeoutException, ExecutionException {
         boolean replaySucceded = true;
+        boolean doRouteSync = false;
         String host = getConfigHost();
         int port = getConfigPort();
         LOG.error("connecting  to bgp host {} ", host);
         boolean res = bgpRouter.connect(host, port);
         if (!res) {
-            String msg = "Cannot connect to BGP config server at " + host + ":" + port;
-            if (config != null) {
-                msg += "; Configuration Replay aborted";
-            }
-            LOG.error(msg);
+            LOG.error("Cannot connect to BGP config server at {} {}", host, port);
             return replaySucceded;
         }
         config = getConfig();
@@ -2084,10 +2257,10 @@ public class BgpConfigurationManager {
             LOG.error("bgp as-id is null");
             return replaySucceded;
         }
-        long asNum = asId.getLocalAs();
+        long asNum = asId.getLocalAs().toJava();
         IpAddress routerId = asId.getRouterId();
-        String rid = routerId == null ? "" : new String(routerId.getValue());
-        int stalepathTime = (int) getStalePathtime(RESTART_DEFAULT_GR, config.getAsId());
+        String rid = routerId == null ? "" : routerId.stringValue();
+        int stalepathTime = (int) getStalePathtime(bgpGrRestartTime, config.getAsId());
         boolean announceFbit = true;
         boolean replayDone = false;
         final int numberOfStartBgpRetries = 3;
@@ -2095,7 +2268,7 @@ public class BgpConfigurationManager {
         do {
             try {
                 LOG.debug("Replaying BGPConfig ");
-                br.startBgp(asNum, rid, stalepathTime, announceFbit);
+                br.startBgp(asNum, rid, bgpKaTime, bgpHoldTime, stalepathTime, announceFbit);
                 LOG.debug("Replay BGPConfig successful");
                 replayDone = true;
                 break;
@@ -2104,8 +2277,8 @@ public class BgpConfigurationManager {
                     LOG.debug("Starting the routesync for exception", bre);
                     startBgpRetry.errorOccured();
                     if (!startBgpRetry.shouldRetry()) {
-                        LOG.debug("starting route sync for BgpRouter exception");
-                        doRouteSync();
+                        doRouteSync = true;
+                        replayDone = true;
                     }
                 } else {
                     LOG.error("Replay: startBgp() received exception error {} : ",
@@ -2117,15 +2290,15 @@ public class BgpConfigurationManager {
                     LOG.debug("Starting the routesync for exception", tae);
                     startBgpRetry.errorOccured();
                     if (!startBgpRetry.shouldRetry()) {
-                        LOG.debug("starting route sync for Thrift BGP_ERR_ACTIVE exception");
-                        doRouteSync();
+                        doRouteSync = true;
+                        replayDone = true;
                     }
                 } else if (tae.getType() == BgpRouterException.BGP_ERR_COMMON_FAILURE) {
                     LOG.debug("Starting the routesync for AS-ID started exception", tae);
                     startBgpRetry.errorOccured();
                     if (!startBgpRetry.shouldRetry()) {
-                        LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception");
-                        doRouteSync();
+                        doRouteSync = true;
+                        replayDone = true;
                     }
                 } else {
                     LOG.error("Replay: startBgp() received exception type {}: ",
@@ -2154,10 +2327,34 @@ public class BgpConfigurationManager {
         //    LOG.error("Replay: delayEOR() number of seconds to wait for EOR from ODL:", e);
         //}
 
-        List<Neighbors> neighbors = config.getNeighbors();
-        if (neighbors != null) {
-            LOG.error("configuring existing Neighbors present for replay total neighbors {}", neighbors.size());
-            boolean neighborConfigReplayResult = replayNbrConfig(neighbors, br);
+        BfdConfig bfdConfig = bgpUtil.getBfdConfig();
+        if (bfdConfig != null) {
+            if (bfdConfig.isBfdEnabled()) {
+                LOG.debug("Replaying bfd config min-rx {} min-tx {} detect-mul {} mhop {}",
+                        bfdConfig.getMinRx(), bfdConfig.getMinTx(),
+                        bfdConfig.getDetectMult(), bfdConfig.isMultihop());
+                try {
+                    br.addBfd(bfdConfig.getDetectMult().intValue(), bfdConfig.getMinRx().intValue(),
+                            bfdConfig.getMinTx().intValue(), bfdConfig.isMultihop());
+                } catch (TApplicationException tae) {
+                    if (tae.getType() == BgpRouterException.BGP_ERR_PEER_EXISTS) {
+                        LOG.debug("Replay:addBfd() received exception", tae);
+                    } else {
+                        LOG.error("Replay:addBfd() received exception", tae);
+                    }
+                } catch (TException | BgpRouterException e) {
+                    LOG.error("Replay:addBfd() received exception", e);
+                }
+            }
+        }
+
+        Map<NeighborsKey, Neighbors> keyNeighborsMap = config.getNeighborsContainer() == null ? null
+                : config.getNeighborsContainer().getNeighbors();
+        if (keyNeighborsMap != null) {
+            LOG.error("configuring existing Neighbors present for replay total keyNeighborsMap {}",
+                    keyNeighborsMap.values().size());
+            boolean neighborConfigReplayResult
+                    = replayNbrConfig(new ArrayList<Neighbors>(keyNeighborsMap.values()), br);
             if (neighborConfigReplayResult == false) {
                 replaySucceded = false;
             }
@@ -2175,36 +2372,38 @@ public class BgpConfigurationManager {
         }
 
         GracefulRestart gracefulRestart = config.getGracefulRestart();
-        if (gracefulRestart != null) {
-            try {
-                br.addGracefulRestart(gracefulRestart.getStalepathTime().intValue());
-            } catch (TException | BgpRouterException e) {
-                LOG.error("Replay:addGr() received exception", e);
-            }
+        bgpGrRestartTime = ((gracefulRestart != null)
+                ? gracefulRestart.getStalepathTime().intValue() : bgpGrRestartTime);
+        try {
+            br.addGracefulRestart(bgpGrRestartTime);
+        } catch (Exception e) {
+            LOG.error("Replay:addGr() received exception: ", e);
         }
-
-        List<Vrfs> vrfs = config.getVrfs();
-        if (vrfs == null) {
-            vrfs = new ArrayList<>();
+        Map<VrfsKey, Vrfs> keyVrfsMap = config.getVrfsContainer() == null ? null
+                : config.getVrfsContainer().getVrfs();
+        if (keyVrfsMap == null) {
+            keyVrfsMap = new HashMap<VrfsKey, Vrfs>();
         }
-        for (Vrfs vrf : vrfs) {
-            for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf()) {
+        for (Vrfs vrf : keyVrfsMap.values()) {
+            for (AddressFamiliesVrf adf : vrf.getAddressFamiliesVrf().values()) {
                 try {
                     br.addVrf(BgpUtil.getLayerType(adf), vrf.getRd(), vrf.getImportRts(),
-                            vrf.getExportRts(), adf.getAfi(), adf.getSafi());
+                            vrf.getExportRts(), adf.getAfi().toJava(), adf.getSafi().toJava());
                 } catch (TException | BgpRouterException e) {
                     LOG.error("Replay:addVrf() received exception", e);
                 }
             }
         }
 
-        List<Networks> ln = config.getNetworks();
-        if (ln != null) {
-            for (Networks net : ln) {
+
+        Map<NetworksKey, Networks> keyNetworksMap = config.getNetworksContainer() == null ? null
+                : config.getNetworksContainer().getNetworks();
+        if (keyNetworksMap != null) {
+            for (Networks net : keyNetworksMap.values()) {
                 String rd = net.getRd();
                 String pfxlen = net.getPrefixLen();
                 String nh = net.getNexthop().getValue();
-                Long label = net.getLabel();
+                Long label = net.getLabel().toJava();
                 int lbl = label == null ? 0 : label.intValue();
                 int l3vni = net.getL3vni() == null ? 0 : net.getL3vni().intValue();
                 int l2vni = net.getL2vni() == null ? 0 : net.getL2vni().intValue();
@@ -2231,10 +2430,11 @@ public class BgpConfigurationManager {
         }
 
 
-        List<Multipath> multipaths = config.getMultipath();
+        Map<MultipathKey, Multipath> keyMultipathMap = config.getMultipathContainer() == null ? null
+                : config.getMultipathContainer().getMultipath();
 
-        if (multipaths != null) {
-            for (Multipath multipath : multipaths) {
+        if (keyMultipathMap != null) {
+            for (Multipath multipath : keyMultipathMap.values()) {
                 if (multipath != null) {
                     af_afi afi = af_afi.findByValue(multipath.getAfi().intValue());
                     af_safi safi = af_safi.findByValue(multipath.getSafi().intValue());
@@ -2246,31 +2446,30 @@ public class BgpConfigurationManager {
                             br.disableMultipath(afi, safi);
                         }
                     } catch (TException | BgpRouterException e) {
-                        LOG.info("Replay:multipaths() received exception: \"" + e + "\"");
+                        LOG.info("Replay:keyMultipathMap() received exception", e);
                     }
                 }
             }
         }
-        List<VrfMaxpath> vrfMaxpaths = config.getVrfMaxpath();
-        if (vrfMaxpaths != null) {
-            for (VrfMaxpath vrfMaxpath : vrfMaxpaths) {
+        Map<VrfMaxpathKey, VrfMaxpath> keyVrfMaxpathMap = config.getVrfMaxpathContainer() == null ? null
+                : config.getVrfMaxpathContainer().getVrfMaxpath();
+        if (keyVrfMaxpathMap != null) {
+            for (VrfMaxpath vrfMaxpath : keyVrfMaxpathMap.values()) {
                 try {
-                    br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths());
+                    br.multipaths(vrfMaxpath.getRd(), vrfMaxpath.getMaxpaths().toJava());
                 } catch (TException | BgpRouterException e) {
-                    LOG.info("Replay:vrfMaxPath() received exception: \"" + e + "\"");
+                    LOG.info("Replay:vrfMaxPath() received exception", e);
                 }
             }
         }
 
         //send End of Rib Marker to Qthriftd.
         final int numberOfEORRetries = 3;
-        replayDone = false;
         RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
         do {
             try {
                 br.sendEOR();
-                LOG.debug("Replay sendEOR {} successful");
-                replayDone = true;
+                LOG.debug("Replay sendEOR() successful");
                 break;
             } catch (Exception e) {
                 eorRetry.errorOccured();
@@ -2278,15 +2477,21 @@ public class BgpConfigurationManager {
             }
         } while (eorRetry.shouldRetry());
 
-        return replaySucceded && replayDone;
+        if (doRouteSync) {
+            LOG.debug("starting route sync for Thrift BGP_ERR_COMMON_FAILURE exception "
+                      + "happened earlier");
+            doRouteSync();
+        }
+
+        return replaySucceded;
     }
 
     private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
-        bgpUtil.update(LogicalDatastoreType.CONFIGURATION, iid, dto);
+        bgpUtil.update(iid, dto);
     }
 
     private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
-        bgpUtil.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        bgpUtil.delete(iid);
     }
 
     public void startConfig(String bgpHost, int thriftPort) {
@@ -2300,7 +2505,7 @@ public class BgpConfigurationManager {
     }
 
     public void startBgp(long as, String routerId, int spt, boolean fbit) {
-        IpAddress rid = routerId == null ? null : new IpAddress(routerId.toCharArray());
+        IpAddress rid = routerId == null ? null : IpAddressBuilder.getDefaultInstance(routerId);
         Long staleTime = (long) spt;
         InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
                 InstanceIdentifier.builder(Bgp.class).child(AsId.class);
@@ -2312,6 +2517,34 @@ public class BgpConfigurationManager {
         update(iid, dto);
     }
 
+    public void startBfd(long detectMult, long minRx, long minTx, boolean multiHop) {
+        InstanceIdentifier.InstanceIdentifierBuilder<BfdConfig> iib =
+                InstanceIdentifier.builder(BfdConfig.class);
+        InstanceIdentifier<BfdConfig> iid = iib.build();
+        BfdConfig dto = new BfdConfigBuilder()
+                .setBfdEnabled(true)
+                .setMultihop(multiHop)
+                .setMinRx(minRx)
+                .setMinTx(minTx)
+                .setDetectMult(detectMult)
+                .build();
+        update(iid, dto);
+    }
+
+    public void addDcgwTep(String dcgwIp, String tepIp) {
+        InstanceIdentifier.InstanceIdentifierBuilder<DcgwTep> iib =
+                InstanceIdentifier.builder(Bgp.class)
+                        .child(DcgwTepList.class)
+                        .child(DcgwTep.class, new DcgwTepKey(dcgwIp));
+        InstanceIdentifier<DcgwTep> iid = iib.build();
+        ArrayList<String> tepList = new ArrayList<String>();
+        tepList.add(tepIp);
+        DcgwTep dto = new DcgwTepBuilder().setDcGwIp(dcgwIp).setTepIps(tepList)
+                .build();
+        update(iid, dto);
+        bgpUtil.removeOrUpdateLBGroups(tepIp,NwConstants.MOD_FLOW);
+    }
+
     public void addLogging(String fileName, String logLevel) {
         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
@@ -2334,7 +2567,7 @@ public class BgpConfigurationManager {
             String nbrIp, long remoteAs, @Nullable final TcpMd5SignaturePasswordType md5Secret) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
         InstanceIdentifier<Neighbors> iid = iib.build();
         TcpSecurityOption tcpSecOption = null;
@@ -2350,7 +2583,7 @@ public class BgpConfigurationManager {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         Ipv4Address srcAddr = new Ipv4Address(srcIp);
         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
                         .child(UpdateSource.class);
         InstanceIdentifier<UpdateSource> iid = iib.build();
@@ -2362,7 +2595,7 @@ public class BgpConfigurationManager {
     public void addEbgpMultihop(String nbrIp, int hops) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
                         .child(EbgpMultihop.class);
         InstanceIdentifier<EbgpMultihop> iid = iib.build();
@@ -2374,7 +2607,7 @@ public class BgpConfigurationManager {
     public void addAddressFamily(String nbrIp, int afi, int safi) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
         InstanceIdentifier<AddressFamilies> iid = iib.build();
@@ -2384,11 +2617,12 @@ public class BgpConfigurationManager {
     }
 
     public void addPrefix(String rd, String macAddress, String pfx, List<String> nhList,
-              VrfEntry.EncapType encapType, long lbl, long l3vni, long l2vni, String gatewayMac) {
+              VrfEntry.EncapType encapType, Uint32 lbl, Uint32 l3vni, Uint32 l2vni, String gatewayMac) {
         for (String nh : nhList) {
             Ipv4Address nexthop = nh != null ? new Ipv4Address(nh) : null;
-            Long label = lbl;
+            Uint32 label = lbl;
             InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
+                    .child(NetworksContainer.class)
                     .child(Networks.class, new NetworksKey(pfx, rd)).build();
             NetworksBuilder networksBuilder = new NetworksBuilder().setRd(rd).setPrefixLen(pfx).setNexthop(nexthop)
                                                 .setLabel(label).setEthtag(BgpConstants.DEFAULT_ETH_TAG);
@@ -2397,8 +2631,8 @@ public class BgpConfigurationManager {
         }
     }
 
-    private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, long label,
-                                                  long l3vni, long l2vni, String macAddress, String gatewayMac) {
+    private static void buildVpnEncapSpecificInfo(NetworksBuilder builder, VrfEntry.EncapType encapType, Uint32 label,
+                                                  Uint32 l3vni, Uint32 l2vni, String macAddress, String gatewayMac) {
         if (encapType.equals(VrfEntry.EncapType.Mplsgre)) {
             builder.setLabel(label).setBgpControlPlaneType(BgpControlPlaneType.PROTOCOLL3VPN)
                     .setEncapType(EncapType.GRE);
@@ -2413,7 +2647,7 @@ public class BgpConfigurationManager {
         Vrfs vrf = bgpUtil.getVrfFromRd(rd);
         List<AddressFamiliesVrf> adfList = new ArrayList<>(1);
         if (vrf != null) {
-            adfList = vrf.getAddressFamiliesVrf();
+            adfList = new ArrayList<AddressFamiliesVrf>(vrf.getAddressFamiliesVrf().values());
         }
         AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
         if (addressFamily.equals(AddressFamily.IPV4)) {
@@ -2429,6 +2663,7 @@ public class BgpConfigurationManager {
         AddressFamiliesVrf adf = adfBuilder.build();
         adfList.add(adf);
         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib = InstanceIdentifier.builder(Bgp.class)
+                .child(VrfsContainer.class)
                 .child(Vrfs.class, new VrfsKey(rd));
         InstanceIdentifier<Vrfs> iid = iib.build();
         Vrfs dto = new VrfsBuilder().setRd(rd).setImportRts(irts)
@@ -2447,6 +2682,9 @@ public class BgpConfigurationManager {
             LOG.error("Error adding VRF to datastore", e);
             throw new RuntimeException(e);
         }
+
+        // enable multipath by default in all VRFs
+        setMultipaths(rd, BgpConstants.BGP_DEFAULT_MULTIPATH);
     }
 
     public void stopConfig() {
@@ -2463,6 +2701,50 @@ public class BgpConfigurationManager {
         delete(iid);
     }
 
+    public void stopBfd() {
+        InstanceIdentifier.InstanceIdentifierBuilder<BfdConfig> iib =
+                InstanceIdentifier.builder(BfdConfig.class);
+        InstanceIdentifier<BfdConfig> iid = iib.build();
+        delete(iid);
+    }
+
+    public void delDcgwTep(String dcgwIp, String tepIp) {
+        if (tepIp == null) {
+            InstanceIdentifier.InstanceIdentifierBuilder<DcgwTep> iib =
+                    InstanceIdentifier.builder(Bgp.class)
+                            .child(DcgwTepList.class)
+                            .child(DcgwTep.class, new DcgwTepKey(dcgwIp));
+            InstanceIdentifier<DcgwTep> iid = iib.build();
+            delete(iid);
+        } else {
+            InstanceIdentifier.InstanceIdentifierBuilder<DcgwTep> iib =
+                    InstanceIdentifier.builder(Bgp.class)
+                            .child(DcgwTepList.class)
+                            .child(DcgwTep.class, new DcgwTepKey(dcgwIp));
+            InstanceIdentifier<DcgwTep> iid = iib.build();
+            List<String> tepIpList = bgpUtil.getDcgwTepConfig(dcgwIp);
+            if (tepIpList == null) {
+                LOG.error("No Tep IP configured for DCGW {} on deleting the dcgwtep", dcgwIp);
+                return;
+            }
+            List<String> newTepIpList = new ArrayList<String>();
+            tepIpList.forEach(tep -> {
+                if (!tep.equals(tepIp)) {
+                    newTepIpList.add(tep);
+                }
+            });
+            DcgwTep dto = new DcgwTepBuilder().setDcGwIp(dcgwIp).setTepIps(newTepIpList)
+                    .build();
+            try {
+                SingleTransactionDataBroker.syncWrite(dataBroker,
+                        LogicalDatastoreType.CONFIGURATION, iid, dto);
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("delDcgwTep: Error deleting DCGW Tep", e);
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
     public void delLogging() {
         InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
                 InstanceIdentifier.builder(Bgp.class).child(Logging.class);
@@ -2481,7 +2763,7 @@ public class BgpConfigurationManager {
     public void delNeighbor(String nbrIp) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr));
         InstanceIdentifier<Neighbors> iid = iib.build();
         delete(iid);
@@ -2490,7 +2772,7 @@ public class BgpConfigurationManager {
     public void delUpdateSource(String nbrIp) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
                         .child(UpdateSource.class);
         InstanceIdentifier<UpdateSource> iid = iib.build();
@@ -2500,7 +2782,7 @@ public class BgpConfigurationManager {
     public void delEbgpMultihop(String nbrIp) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
                         .child(EbgpMultihop.class);
         InstanceIdentifier<EbgpMultihop> iid = iib.build();
@@ -2510,7 +2792,7 @@ public class BgpConfigurationManager {
     public void delAddressFamily(String nbrIp, int afi, int safi) {
         Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
         InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NeighborsContainer.class)
                         .child(Neighbors.class, new NeighborsKey(nbrAddr))
                         .child(AddressFamilies.class, new AddressFamiliesKey((long) afi, (long) safi));
         InstanceIdentifier<AddressFamilies> iid = iib.build();
@@ -2519,7 +2801,7 @@ public class BgpConfigurationManager {
 
     public void delPrefix(String rd, String pfx) {
         InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(NetworksContainer.class)
                         .child(Networks.class, new NetworksKey(pfx, rd));
         InstanceIdentifier<Networks> iid = iib.build();
         delete(iid);
@@ -2530,6 +2812,7 @@ public class BgpConfigurationManager {
             LOG.error("delVrf: vrf {}, addressFamily invalid", rd);
             return false;
         }
+        delMultipaths(rd);
         AddressFamiliesVrfBuilder adfBuilder = new AddressFamiliesVrfBuilder();
         if (addressFamily.equals(AddressFamily.IPV4)) {
             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
@@ -2541,6 +2824,9 @@ public class BgpConfigurationManager {
             adfBuilder.setAfi((long) af_afi.AFI_IP.getValue());
             adfBuilder.setSafi((long) af_safi.SAFI_EVPN.getValue());
         }
+        LOG.debug("delVrf: Received Delete VRF : rd:{}, address family: {} {}", rd,
+                adfBuilder.getAfi(), adfBuilder.getSafi());
+
         Vrfs vrfOriginal = bgpUtil.getVrfFromRd(rd);
         if (vrfOriginal == null) {
             LOG.error("delVrf: no vrf with existing rd {}. step aborted", rd);
@@ -2548,21 +2834,22 @@ public class BgpConfigurationManager {
         }
 
         InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
-                InstanceIdentifier.builder(Bgp.class)
+                InstanceIdentifier.builder(Bgp.class).child(VrfsContainer.class)
                         .child(Vrfs.class, new VrfsKey(rd));
 
         InstanceIdentifier<Vrfs> iid = iib.build();
 
         @SuppressWarnings("static-access")
         InstanceIdentifier<Bgp> iid6 =  iid.builder(Bgp.class).build()
+                .child(MultipathContainer.class)
                 .child(Multipath.class, new MultipathKey(adfBuilder.getAfi(), adfBuilder.getSafi())).create(Bgp.class);
-        InstanceIdentifierBuilder<Vrfs> iib3 = iid6.child(Vrfs.class, new VrfsKey(rd)).builder();
+        InstanceIdentifierBuilder<Vrfs> iib3 =
+                iid6.child(VrfsContainer.class).child(Vrfs.class, new VrfsKey(rd)).builder();
         InstanceIdentifier<Vrfs> iidFinal = iib3.build();
 
         //** update or delete the vrfs with the rest of AddressFamilies already present in the last list
         AddressFamiliesVrf adfToDel = adfBuilder.build();
-        List<AddressFamiliesVrf> adfListOriginal = vrfOriginal.getAddressFamiliesVrf() == null
-                ? new ArrayList<>() : vrfOriginal.getAddressFamiliesVrf();
+        List<AddressFamiliesVrf> adfListOriginal = new ArrayList<>(vrfOriginal.nonnullAddressFamiliesVrf().values());
         List<AddressFamiliesVrf> adfListToRemoveFromOriginal = new ArrayList<>();
         adfListOriginal.forEach(adf -> {
             if (adf.equals(adfToDel)) {
@@ -2581,6 +2868,7 @@ public class BgpConfigurationManager {
             }
         }
         if (adfListOriginal.isEmpty()) {
+            LOG.debug("delVrf: delete iid: {}", iidFinal);
             delete(iidFinal);
             return true;
         }
@@ -2594,7 +2882,7 @@ public class BgpConfigurationManager {
 
         InstanceIdentifier.InstanceIdentifierBuilder<Multipath> iib =
                 InstanceIdentifier
-                        .builder(Bgp.class)
+                        .builder(Bgp.class).child(MultipathContainer.class)
                         .child(Multipath.class,
                                 new MultipathKey(Long.valueOf(afi.getValue()), Long.valueOf(safi.getValue())));
 
@@ -2602,16 +2890,24 @@ public class BgpConfigurationManager {
         update(iib.build(), dto);
     }
 
-    public void multipaths(String rd, int maxpath) {
+    public void setMultipaths(String rd, int maxpath) {
         InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
                 InstanceIdentifier
-                        .builder(Bgp.class)
+                        .builder(Bgp.class).child(VrfMaxpathContainer.class)
                         .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
 
         VrfMaxpath dto = new VrfMaxpathBuilder().setRd(rd).setMaxpaths(maxpath).build();
         update(iib.build(), dto);
     }
 
+    public void delMultipaths(String rd) {
+        InstanceIdentifier.InstanceIdentifierBuilder<VrfMaxpath> iib =
+                InstanceIdentifier.builder(Bgp.class).child(VrfMaxpathContainer.class)
+                        .child(VrfMaxpath.class, new VrfMaxpathKey(rd));
+        InstanceIdentifier<VrfMaxpath> iid = iib.build();
+        delete(iid);
+    }
+
     /*
     * Remove Stale Marked Routes after timer expiry.
     */
@@ -2628,7 +2924,7 @@ public class BgpConfigurationManager {
                         if (Thread.interrupted()) {
                             return 0;
                         }
-                        Map<String, Long> map = staledFibEntriesMap.get(rd);
+                        Map<String, Uint32> map = staledFibEntriesMap.get(rd);
                         if (map != null) {
                             for (String key : map.keySet()) {
                                 if (Thread.interrupted()) {
@@ -2660,15 +2956,16 @@ public class BgpConfigurationManager {
         totalStaledCount = 0;
         try {
             staledFibEntriesMap.clear();
+            fibDSWriter.clearFibMap();
             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
 
             Optional<FibEntries> fibEntries = SingleTransactionDataBroker.syncReadOptional(dataBroker,
                     LogicalDatastoreType.CONFIGURATION, id);
             if (fibEntries.isPresent()) {
-                List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
-                for (VrfTables vrfTable : staleVrfTables) {
-                    Map<String, Long> staleFibEntMap = new HashMap<>();
-                    for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+                Map<VrfTablesKey, VrfTables> staleVrfTablesMap = fibEntries.get().getVrfTables();
+                for (VrfTables vrfTable : staleVrfTablesMap.values()) {
+                    Map<String, Uint32> staleFibEntMap = new HashMap<>();
+                    for (VrfEntry vrfEntry : vrfTable.getVrfEntry().values()) {
                         if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
                             //Stale marking and cleanup is only meant for the routes learned through BGP.
                             continue;
@@ -2677,19 +2974,25 @@ public class BgpConfigurationManager {
                             break;
                         }
                         totalStaledCount++;
-                        //Create MAP from staleVrfTables.
-                        vrfEntry.getRoutePaths()
+                        //Create MAP from staleVrfTablesMap.
+                        vrfEntry.getRoutePaths().values()
                                 .forEach(
-                                    routePath -> staleFibEntMap.put(
-                                            appendNextHopToPrefix(vrfEntry.getDestPrefix(),
-                                                    routePath.getNexthopAddress()), routePath.getLabel()));
+                                    routePath -> {
+                                        staleFibEntMap.put(
+                                                appendNextHopToPrefix(vrfEntry.getDestPrefix(),
+                                                        routePath.getNexthopAddress()), routePath.getLabel());
+                                        fibDSWriter.addEntryToFibMap(
+                                                vrfTable.getRouteDistinguisher(),  vrfEntry.getDestPrefix(),
+                                                routePath.getNexthopAddress());
+
+                                    });
                     }
                     staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), staleFibEntMap);
                 }
             } else {
                 LOG.error("createStaleFibMap:: FIBentries.class is not present");
             }
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("createStaleFibMap:: error ", e);
         }
         LOG.error("created {} staled entries ", totalStaledCount);
@@ -2712,11 +3015,11 @@ public class BgpConfigurationManager {
                     LOG.error("deleteExternalFibRoutes::getVrfTables is null");
                     return;
                 }
-                List<VrfTables> staleVrfTables = fibEntries.get().getVrfTables();
-                for (VrfTables vrfTable : staleVrfTables) {
+                Map<VrfTablesKey, VrfTables> staleVrfTablesMap = fibEntries.get().getVrfTables();
+                for (VrfTables vrfTable : staleVrfTablesMap.values()) {
                     String rd = vrfTable.getRouteDistinguisher();
                     if (vrfTable.getVrfEntry() != null) {
-                        for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+                        for (VrfEntry vrfEntry : vrfTable.getVrfEntry().values()) {
                             if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.BGP) {
                                 //route cleanup is only meant for the routes learned through BGP.
                                 continue;
@@ -2725,7 +3028,7 @@ public class BgpConfigurationManager {
                             fibDSWriter.removeFibEntryFromDS(rd, vrfEntry.getDestPrefix());
                         }
                     } else if (vrfTable.getMacVrfEntry() != null) {
-                        for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry()) {
+                        for (MacVrfEntry macEntry : vrfTable.getMacVrfEntry().values()) {
                             if (RouteOrigin.value(macEntry.getOrigin()) != RouteOrigin.BGP) {
                                 //route cleanup is only meant for the routes learned through BGP.
                                 continue;
@@ -2738,13 +3041,13 @@ public class BgpConfigurationManager {
             } else {
                 LOG.error("deleteExternalFibRoutes:: FIBentries.class is not present");
             }
-        } catch (ReadFailedException e) {
+        } catch (InterruptedException | ExecutionException e) {
             LOG.error("deleteExternalFibRoutes:: error ", e);
         }
         LOG.debug("deleted {} fib entries {} mac entries", totalExternalRoutes, totalExternalMacRoutes);
     }
 
-    public boolean addToRt2TepMap(String rd, String tepIp, String mac, Long l2vni) {
+    public boolean addToRt2TepMap(String rd, String tepIp, String mac, Uint32 l2vni) {
         boolean isFirstMacUpdateFromTep = false;
         if (rt2TepMap.containsKey(rd)) {
             if (rt2TepMap.get(rd).containsKey(tepIp)) {
@@ -2753,9 +3056,9 @@ public class BgpConfigurationManager {
                 rt2TepMap.get(rd).get(tepIp).put(mac, l2vni);
             } else {
                 LOG.debug("RT2 with mac {} l2vni {} from existing rd {} and new tep-ip {}",
-                        mac, rd, tepIp);
+                        mac, l2vni, rd, tepIp);
                 isFirstMacUpdateFromTep = true;
-                Map<String, Long> macList = new HashMap<>();
+                Map<String, Uint32> macList = new HashMap<>();
                 macList.put(mac, l2vni);
                 rt2TepMap.get(rd).put(tepIp, macList);
             }
@@ -2763,9 +3066,9 @@ public class BgpConfigurationManager {
             LOG.debug("RT2 with mac {} l2vni {} from new rd {} and tep ip {}",
                     mac, l2vni, rd, tepIp);
             isFirstMacUpdateFromTep = true;
-            Map<String, Long> macList = new HashMap<>();
+            Map<String, Uint32> macList = new HashMap<>();
             macList.put(mac, l2vni);
-            Map<String, Map<String, Long>> tepIpMacMap = new HashMap<>();
+            Map<String, Map<String, Uint32>> tepIpMacMap = new HashMap<>();
             tepIpMacMap.put(tepIp, macList);
             rt2TepMap.put(rd, tepIpMacMap);
         }
@@ -2796,24 +3099,24 @@ public class BgpConfigurationManager {
     }
 
     public Collection<String> getTepIPs(String rd) {
-        final Map<String, Map<String, Long>> tepIpMap = rt2TepMap.get(rd);
+        final Map<String, Map<String, Uint32>> tepIpMap = rt2TepMap.get(rd);
         return tepIpMap != null ? tepIpMap.keySet() : Collections.emptyList();
     }
 
     public boolean isBgpConnected() {
-        return bgpRouter.isBgpConnected();
+        return (bgpRouter == null) ? false : bgpRouter.isBgpConnected();
     }
 
     public long getLastConnectedTS() {
-        return bgpRouter.getLastConnectedTS();
+        return (bgpRouter == null) ? 0 : bgpRouter.getLastConnectedTS();
     }
 
     public long getConnectTS() {
-        return bgpRouter.getConnectTS();
+        return (bgpRouter == null) ? 0 : bgpRouter.getConnectTS();
     }
 
     public long getStartTS() {
-        return bgpRouter.getStartTS();
+        return (bgpRouter == null) ? 0 : bgpRouter.getStartTS();
     }
 
     public TTransport getTransport() {
@@ -2828,6 +3131,10 @@ public class BgpConfigurationManager {
         return totalCleared;
     }
 
+    public static List<Neighbors> getNbrList() {
+        return nbrList;
+    }
+
     public BgpCounters getBgpCounters() {
         return bgpCountersReference.get();
     }
@@ -2843,6 +3150,8 @@ public class BgpConfigurationManager {
         }
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private void stopBgpCountersTask() {
         final BgpCounters bgpCounters = bgpCountersReference.getAndSet(null);
         if (bgpCounters != null) {
@@ -2856,9 +3165,13 @@ public class BgpConfigurationManager {
             bgpAlarmsReference.get().init();
             bgpAlarmsTask = executor.scheduleAtFixedRate(bgpAlarmsReference.get(), 0, 60 * 1000, TimeUnit.MILLISECONDS);
             LOG.info("Bgp Alarms task scheduled for every minute.");
+        } else {
+            LOG.trace("Bgp Alarms task already scheduled for every minute.");
         }
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private void stopBgpAlarmsTask() {
         final BgpAlarms bgpAlarms = bgpAlarmsReference.getAndSet(null);
         if (bgpAlarms != null) {
@@ -2871,14 +3184,23 @@ public class BgpConfigurationManager {
         return bgpAlarmsReference.get();
     }
 
+    public void getPeerStatus(String nbrIp, long nbrAsNum) throws
+            BgpRouterException, TException {
+        bgpRouter.getPeerStatus(nbrIp, nbrAsNum);
+    }
+
     private static String appendNextHopToPrefix(String prefix, String nextHop) {
         return prefix + ":" + nextHop;
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static String extractPrefix(String prefixNextHop) {
         return prefixNextHop.split(":")[0];
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static String extractNextHop(String prefixNextHop) {
         return prefixNextHop.split(":")[1];
     }
@@ -2895,4 +3217,67 @@ public class BgpConfigurationManager {
         }
         return md5Secret;
     } // private method extractMd5Secret
+
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    @Override
+    public ListenableFuture<RpcResult<InitiateEorOutput>> initiateEor(InitiateEorInput input) {
+        boolean returnError = false;
+        String msg = null;
+        String neighborIp = null;
+        if (!isBGPEntityOwner()) {
+            msg = String.format("RPC triggered in Non-EoS Owner");
+            return Futures.immediateFuture(
+                    RpcResultBuilder.<InitiateEorOutput>failed().withError(RpcError.ErrorType.APPLICATION,
+                            msg).build());
+        }
+        if (input == null) {
+            msg = String.format("BGP invalid input for EoR");
+            LOG.error("Error : {}", msg);
+            returnError = true;
+        } else {
+            neighborIp = input.getNeighborIp();
+        }
+        if (eorSupressedDuetoUpgradeFlag.get() == false) {
+            msg = String.format("EoR triggerd by RBU-RPC call before replay"
+                    + "of BGP configuration (or) BGP not restarted");
+            LOG.error("Error : {}", msg);
+        }
+        if ("ALL".compareToIgnoreCase(neighborIp) == 0) {
+            //send EoR for all the neighbor
+            LOG.error("EoR trigger received to ALL neighbors");
+            final int numberOfEORRetries = 3;
+            RetryOnException eorRetry = new RetryOnException(numberOfEORRetries);
+            do {
+                try {
+                    BgpRouter br = bgpRouter;
+                    br.sendEOR();
+                    LOG.debug("RPC: sendEOR {} successful", br);
+                    break;
+                } catch (Exception e) {
+                    eorRetry.errorOccured();
+                    LOG.error("Replay:sedEOR() received exception:", e);
+                }
+            } while (eorRetry.shouldRetry());
+            eorSupressedDuetoUpgradeFlag.set(false);
+        } else if (InetAddresses.isInetAddress(neighborIp)) {
+            //send EoR for only one neighbor
+            msg = String.format("Inidividual neighbors EoR is not supported");
+            LOG.warn("Error : {}", msg);
+            returnError = true;
+        } else {
+            //error
+            msg = String.format("RPC: initiateEor: Invalid input ");
+            LOG.warn("Error : {}", msg);
+            returnError = true;
+        }
+        if (returnError) {
+            return Futures.immediateFuture(
+                    RpcResultBuilder.<InitiateEorOutput>failed().withError(RpcError.ErrorType.APPLICATION,
+                            msg).build());
+        }
+        InitiateEorOutput initiateEorOutput =
+                new InitiateEorOutputBuilder().setRetVal(0L).build();
+        return Futures.immediateFuture(RpcResultBuilder.<InitiateEorOutput>success()
+                .withResult(initiateEorOutput).build());
+    }
 }