YANG revision dates mass-update
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / BGPPeer.java
index b46c4385ed013893d6f6122935143cf8a1267c8b..937382a0f9a71c5ae1eede7e28d7eff88dd949fd 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.protocol.bgp.rib.impl;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.MoreObjects;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.MoreObjects;
-import com.google.common.base.Objects;
 import com.google.common.base.Stopwatch;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.base.Stopwatch;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
@@ -29,17 +28,19 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
-import javax.annotation.concurrent.GuardedBy;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
-import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.checkerframework.checker.lock.qual.Holding;
+import org.opendaylight.mdsal.binding.api.RpcProviderService;
+import org.opendaylight.mdsal.binding.api.Transaction;
+import org.opendaylight.mdsal.binding.api.TransactionChain;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPError;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
 import org.opendaylight.protocol.bgp.parser.BGPError;
@@ -59,19 +60,18 @@ import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPSessionState;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPTimersState;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPTransportState;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPSessionState;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPTimersState;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPTransportState;
-import org.opendaylight.protocol.concepts.AbstractRegistration;
 import org.opendaylight.protocol.util.Ipv4Util;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
 import org.opendaylight.protocol.util.Ipv4Util;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
-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.IpAddressNoZone;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.DestinationIpv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4Prefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationIpv4CaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.DestinationIpv4Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4Prefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.ipv4.prefixes.destination.ipv4.Ipv4PrefixesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationIpv4CaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.Update;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.BgpParameters;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.update.message.Nlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.Update;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.open.message.BgpParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.update.message.Nlri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpAddPathTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.RouteRefresh;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpAddPathTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.BgpTableType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.RouteRefresh;
@@ -85,18 +85,19 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mult
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev180329.BgpPeerRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev180329.BgpPeerRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.peer.rpc.rev180329.PeerContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.PeerKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.peer.AdjRibOut;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.PeerKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.peer.AdjRibOut;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.ClusterIdentifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteTarget;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.SubsequentAddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.UnicastSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.ClusterIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.SubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.Notification;
@@ -110,20 +111,21 @@ import org.slf4j.LoggerFactory;
  */
 public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class);
  */
 public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     private static final Logger LOG = LoggerFactory.getLogger(BGPPeer.class);
-    private static final TablesKey IPV4_UCAST_TABLE_KEY = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
+    private static final TablesKey IPV4_UCAST_TABLE_KEY = new TablesKey(Ipv4AddressFamily.class,
+        UnicastSubsequentAddressFamily.class);
 
 
-    private Set<TablesKey> tables = Collections.emptySet();
+    private ImmutableSet<TablesKey> tables = ImmutableSet.of();
     private final RIB rib;
     private final Map<TablesKey, AdjRibOutListener> adjRibOutListenerSet = new HashMap<>();
     private final List<RouteTarget> rtMemberships = new ArrayList<>();
     private final RIB rib;
     private final Map<TablesKey, AdjRibOutListener> adjRibOutListenerSet = new HashMap<>();
     private final List<RouteTarget> rtMemberships = new ArrayList<>();
-    private final RpcProviderRegistry rpcRegistry;
+    private final RpcProviderService rpcRegistry;
     private final BGPTableTypeRegistryConsumer tableTypeRegistry;
     private final BgpPeer bgpPeer;
     private InstanceIdentifier<AdjRibOut> peerRibOutIId;
     private KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib
             .rev180329.bgp.rib.rib.Peer, PeerKey> peerIId;
     @GuardedBy("this")
     private final BGPTableTypeRegistryConsumer tableTypeRegistry;
     private final BgpPeer bgpPeer;
     private InstanceIdentifier<AdjRibOut> peerRibOutIId;
     private KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib
             .rev180329.bgp.rib.rib.Peer, PeerKey> peerIId;
     @GuardedBy("this")
-    private AbstractRegistration trackerRegistration;
+    private Registration trackerRegistration;
     private final LoadingCache<TablesKey, KeyedInstanceIdentifier<Tables, TablesKey>> tablesIId
             = CacheBuilder.newBuilder()
             .build(new CacheLoader<TablesKey, KeyedInstanceIdentifier<Tables, TablesKey>>() {
     private final LoadingCache<TablesKey, KeyedInstanceIdentifier<Tables, TablesKey>> tablesIId
             = CacheBuilder.newBuilder()
             .build(new CacheLoader<TablesKey, KeyedInstanceIdentifier<Tables, TablesKey>>() {
@@ -134,33 +136,35 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
             });
 
     @GuardedBy("this")
             });
 
     @GuardedBy("this")
-    private BGPSession session;
+    private BGPSession currentSession;
     @GuardedBy("this")
     private AdjRibInWriter ribWriter;
     @GuardedBy("this")
     private EffectiveRibInWriter effRibInWriter;
     @GuardedBy("this")
     private AdjRibInWriter ribWriter;
     @GuardedBy("this")
     private EffectiveRibInWriter effRibInWriter;
-    private RoutedRpcRegistration<BgpPeerRpcService> rpcRegistration;
+    private ObjectRegistration<BgpPeerRpcService> rpcRegistration;
     private Map<TablesKey, SendReceive> addPathTableMaps = Collections.emptyMap();
     private YangInstanceIdentifier peerPath;
     private boolean sessionUp;
     private Map<TablesKey, SendReceive> addPathTableMaps = Collections.emptyMap();
     private YangInstanceIdentifier peerPath;
     private boolean sessionUp;
+    private boolean llgrSupport;
     private Stopwatch peerRestartStopwatch;
     private Stopwatch peerRestartStopwatch;
-    private long selectionDeferralTimerSeconds;
+    private long currentSelectionDeferralTimerSeconds;
     private final List<TablesKey> missingEOT = new ArrayList<>();
 
     public BGPPeer(
             final BGPTableTypeRegistryConsumer tableTypeRegistry,
     private final List<TablesKey> missingEOT = new ArrayList<>();
 
     public BGPPeer(
             final BGPTableTypeRegistryConsumer tableTypeRegistry,
-            final IpAddress neighborAddress,
+            final IpAddressNoZone neighborAddress,
             final String peerGroupName,
             final RIB rib,
             final PeerRole role,
             final ClusterIdentifier clusterId,
             final AsNumber localAs,
             final String peerGroupName,
             final RIB rib,
             final PeerRole role,
             final ClusterIdentifier clusterId,
             final AsNumber localAs,
-            final RpcProviderRegistry rpcRegistry,
+            final RpcProviderService rpcRegistry,
             final Set<TablesKey> afiSafisAdvertized,
             final Set<TablesKey> afiSafisGracefulAdvertized,
             final Set<TablesKey> afiSafisAdvertized,
             final Set<TablesKey> afiSafisGracefulAdvertized,
+            final Map<TablesKey, Integer> llGracefulTablesAdvertised,
             final BgpPeer bgpPeer) {
         super(rib, Ipv4Util.toStringIP(neighborAddress), peerGroupName, role, clusterId,
             final BgpPeer bgpPeer) {
         super(rib, Ipv4Util.toStringIP(neighborAddress), peerGroupName, role, clusterId,
-                localAs, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized, Collections.emptyMap());
+                localAs, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized, llGracefulTablesAdvertised);
         this.tableTypeRegistry = requireNonNull(tableTypeRegistry);
         this.rib = requireNonNull(rib);
         this.rpcRegistry = rpcRegistry;
         this.tableTypeRegistry = requireNonNull(tableTypeRegistry);
         this.rib = requireNonNull(rib);
         this.rpcRegistry = rpcRegistry;
@@ -210,8 +214,8 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
             Optional<Nlri> nlriAnounced = Optional.empty();
             if (isAnyNlriAnnounced) {
 
             Optional<Nlri> nlriAnounced = Optional.empty();
             if (isAnyNlriAnnounced) {
-                nlriAnounced = message.getNlri().stream().filter(n -> Objects.equal(n.getPrefix(), w.getPrefix())
-                        && Objects.equal(n.getPathId(), w.getPathId()))
+                nlriAnounced = message.getNlri().stream().filter(n -> Objects.equals(n.getPrefix(), w.getPrefix())
+                        && Objects.equals(n.getPathId(), w.getPathId()))
                         .findAny();
             }
             if (!nlriAnounced.isPresent()) {
                         .findAny();
             }
             if (!nlriAnounced.isPresent()) {
@@ -231,6 +235,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     }
 
     public synchronized void instantiateServiceInstance() {
     }
 
     public synchronized void instantiateServiceInstance() {
+        createDomChain();
         this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this);
         setActive(true);
     }
         this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this);
         setActive(true);
     }
@@ -259,13 +264,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         final Class<? extends SubsequentAddressFamily> rrSafi = message.getSafi();
 
         final TablesKey key = new TablesKey(rrAfi, rrSafi);
         final Class<? extends SubsequentAddressFamily> rrSafi = message.getSafi();
 
         final TablesKey key = new TablesKey(rrAfi, rrSafi);
-        final AdjRibOutListener listener = this.adjRibOutListenerSet.get(key);
-        if (listener != null) {
-            listener.close();
-            this.adjRibOutListenerSet.remove(key);
-            createAdjRibOutListener(key, listener.isMpSupported());
-        } else {
-            LOG.info("Ignoring RouteRefresh message. Afi/Safi is not supported: {}, {}.", rrAfi, rrSafi);
+        synchronized (this) {
+            final AdjRibOutListener listener = this.adjRibOutListenerSet.remove(key);
+            if (listener != null) {
+                listener.close();
+                createAdjRibOutListener(key, listener.isMpSupported());
+            } else {
+                LOG.info("Ignoring RouteRefresh message. Afi/Safi is not supported: {}, {}.", rrAfi, rrSafi);
+            }
         }
     }
 
         }
     }
 
@@ -306,7 +312,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         if (mpReach != null) {
             this.ribWriter.updateRoutes(mpReach, nextHopToAttribute(attrs, mpReach));
         }
         if (mpReach != null) {
             this.ribWriter.updateRoutes(mpReach, nextHopToAttribute(attrs, mpReach));
         }
-        MpUnreachNlri mpUnreach;
+        final MpUnreachNlri mpUnreach;
         if (message.getWithdrawnRoutes() != null) {
             mpUnreach = prefixesToMpUnreach(message, isAnyNlriAnnounced);
         } else {
         if (message.getWithdrawnRoutes() != null) {
             mpUnreach = prefixesToMpUnreach(message, isAnyNlriAnnounced);
         } else {
@@ -329,13 +335,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         }
     }
 
         }
     }
 
-    private synchronized void handleGracefulEndOfRib() {
+    @Holding("this")
+    private void handleGracefulEndOfRib() {
         if (isLocalRestarting()) {
             if (this.missingEOT.isEmpty()) {
                 createEffRibInWriter();
                 this.effRibInWriter.init();
                 registerPrefixesCounters(this.effRibInWriter, this.effRibInWriter);
         if (isLocalRestarting()) {
             if (this.missingEOT.isEmpty()) {
                 createEffRibInWriter();
                 this.effRibInWriter.init();
                 registerPrefixesCounters(this.effRibInWriter, this.effRibInWriter);
-                for (final TablesKey key : this.tables) {
+                for (final TablesKey key : getAfiSafisAdvertized()) {
                     createAdjRibOutListener(key, true);
                 }
                 setLocalRestartingState(false);
                     createAdjRibOutListener(key, true);
                 }
                 setLocalRestartingState(false);
@@ -346,16 +353,21 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
     @Override
     public synchronized void onSessionUp(final BGPSession session) {
 
     @Override
     public synchronized void onSessionUp(final BGPSession session) {
-        this.session = session;
+        this.currentSession = session;
         this.sessionUp = true;
         this.bindingChain = this.rib.createPeerChain(this);
         this.sessionUp = true;
         this.bindingChain = this.rib.createPeerChain(this);
-        if (this.session instanceof BGPSessionStateProvider) {
-            ((BGPSessionStateProvider) this.session).registerMessagesCounter(this);
+        if (this.currentSession instanceof BGPSessionStateProvider) {
+            ((BGPSessionStateProvider) this.currentSession).registerMessagesCounter(this);
         }
         final GracefulRestartCapability advertisedGracefulRestartCapability =
                 session.getAdvertisedGracefulRestartCapability();
         }
         final GracefulRestartCapability advertisedGracefulRestartCapability =
                 session.getAdvertisedGracefulRestartCapability();
-        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.Tables> advertisedTables =
-                advertisedGracefulRestartCapability.getTables();
+        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp
+                .capabilities.graceful.restart.capability.Tables> advertisedTables =
+                    advertisedGracefulRestartCapability.getTables();
+        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp
+                .capabilities.ll.graceful.restart.capability.Tables> advertisedLLTables =
+                    session.getAdvertisedLlGracefulRestartCapability().getTables();
+
         final List<AddressFamilies> addPathTablesType = session.getAdvertisedAddPathTableTypes();
         final Set<BgpTableType> advertizedTableTypes = session.getAdvertisedTableTypes();
         LOG.info("Session with peer {} went up with tables {} and Add Path tables {}", this.name,
         final List<AddressFamilies> addPathTablesType = session.getAdvertisedAddPathTableTypes();
         final Set<BgpTableType> advertizedTableTypes = session.getAdvertisedTableTypes();
         LOG.info("Session with peer {} went up with tables {} and Add Path tables {}", this.name,
@@ -363,6 +375,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         final Set<TablesKey> setTables = advertizedTableTypes.stream().map(t -> new TablesKey(t.getAfi(), t.getSafi()))
                 .collect(Collectors.toSet());
         this.tables = ImmutableSet.copyOf(setTables);
         final Set<TablesKey> setTables = advertizedTableTypes.stream().map(t -> new TablesKey(t.getAfi(), t.getSafi()))
                 .collect(Collectors.toSet());
         this.tables = ImmutableSet.copyOf(setTables);
+
         this.addPathTableMaps = mapTableTypesFamilies(addPathTablesType);
         final boolean restartingLocally = isLocalRestarting();
 
         this.addPathTableMaps = mapTableTypesFamilies(addPathTablesType);
         final boolean restartingLocally = isLocalRestarting();
 
@@ -382,13 +395,10 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
                     this.tables, this.addPathTableMaps);
 
             if (this.rpcRegistry != null) {
                     this.tables, this.addPathTableMaps);
 
             if (this.rpcRegistry != null) {
-                this.rpcRegistration = this.rpcRegistry.addRoutedRpcImplementation(BgpPeerRpcService.class,
-                        new BgpPeerRpc(this, session, this.tables));
-                final KeyedInstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib
-                        .rev180329.bgp.rib.rib.Peer, PeerKey> path = this.rib.getInstanceIdentifier()
-                        .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib
-                                .rib.Peer.class, new PeerKey(this.peerId));
-                this.rpcRegistration.registerPath(PeerContext.class, path);
+                this.rpcRegistration = this.rpcRegistry.registerRpcImplementation(BgpPeerRpcService.class,
+                    new BgpPeerRpc(this, session, this.tables), ImmutableSet.of(this.rib.getInstanceIdentifier().child(
+                        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib
+                        .Peer.class, new PeerKey(this.peerId))));
             }
         } else {
             final Set<TablesKey> forwardingTables;
             }
         } else {
             final Set<TablesKey> forwardingTables;
@@ -409,18 +419,39 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
                 this.missingEOT.addAll(this.tables);
             }
         }
                 this.missingEOT.addAll(this.tables);
             }
         }
-        if (advertisedTables == null ||
-                advertisedTables.isEmpty()) {
+        if (advertisedTables == null || advertisedTables.isEmpty()) {
             setAdvertizedGracefulRestartTableTypes(Collections.emptyList());
         } else {
             setAdvertizedGracefulRestartTableTypes(advertisedTables.stream()
                     .map(t -> new TablesKey(t.getAfi(), t.getSafi())).collect(Collectors.toList()));
         }
             setAdvertizedGracefulRestartTableTypes(Collections.emptyList());
         } else {
             setAdvertizedGracefulRestartTableTypes(advertisedTables.stream()
                     .map(t -> new TablesKey(t.getAfi(), t.getSafi())).collect(Collectors.toList()));
         }
-        final int restartTime = advertisedGracefulRestartCapability.getRestartTime();
-        setAfiSafiGracefulRestartState(restartTime, false, restartingLocally);
+        setAfiSafiGracefulRestartState(advertisedGracefulRestartCapability.getRestartTime().toJava(), false,
+            restartingLocally);
+
+        final Map<TablesKey, Integer> llTablesReceived;
+        if (advertisedLLTables != null) {
+            llTablesReceived = new HashMap<>();
+            for (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp
+                    .capabilities.ll.graceful.restart.capability.Tables table : advertisedLLTables) {
+                llTablesReceived.put(new TablesKey(table.getAfi(), table.getSafi()),
+                    table.getLongLivedStaleTime().getValue().intValue());
+            }
+        } else {
+            llTablesReceived = Collections.emptyMap();
+        }
+        setAdvertizedLlGracefulRestartTableTypes(llTablesReceived);
+
+        if (!llTablesReceived.isEmpty()) {
+            llgrSupport = true;
+            // FIXME: propagate preserved tables
+        } else {
+            // FIXME: clear preserved tables
+            llgrSupport = false;
+        }
+
         if (!restartingLocally) {
             addBgp4Support();
         if (!restartingLocally) {
             addBgp4Support();
-            for (final TablesKey key : this.tables) {
+            for (final TablesKey key : getAfiSafisAdvertized()) {
                 createAdjRibOutListener(key, true);
             }
         }
                 createAdjRibOutListener(key, true);
             }
         }
@@ -428,7 +459,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         // SpotBugs does not grok Optional.ifPresent() and thinks we are using unsynchronized access
         final Optional<RevisedErrorHandlingSupport> errorHandling = this.bgpPeer.getErrorHandling();
         if (errorHandling.isPresent()) {
         // SpotBugs does not grok Optional.ifPresent() and thinks we are using unsynchronized access
         final Optional<RevisedErrorHandlingSupport> errorHandling = this.bgpPeer.getErrorHandling();
         if (errorHandling.isPresent()) {
-            this.session.addDecoderConstraint(RevisedErrorHandlingSupport.class, errorHandling.get());
+            this.currentSession.addDecoderConstraint(RevisedErrorHandlingSupport.class, errorHandling.get());
         }
     }
 
         }
     }
 
@@ -438,14 +469,15 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
     private synchronized void createEffRibInWriter() {
         this.effRibInWriter = new EffectiveRibInWriter(this, this.rib,
 
     private synchronized void createEffRibInWriter() {
         this.effRibInWriter = new EffectiveRibInWriter(this, this.rib,
-                this.rib.createPeerChain(this),
-                this.peerIId, this.tables, this.tableTypeRegistry,
-                this.rtMemberships,
-                this.rtCache);
+            this.rib.createPeerDOMChain(this),
+            this.peerPath, this.tables, this.tableTypeRegistry,
+            this.rtMemberships,
+            this.rtCache);
     }
 
     //try to add a support for old-school BGP-4, if peer did not advertise IPv4-Unicast MP capability
     }
 
     //try to add a support for old-school BGP-4, if peer did not advertise IPv4-Unicast MP capability
-    private synchronized void addBgp4Support() {
+    @Holding("this")
+    private void addBgp4Support() {
         if (!this.tables.contains(IPV4_UCAST_TABLE_KEY)) {
             final HashSet<TablesKey> newSet = new HashSet<>(this.tables);
             newSet.add(IPV4_UCAST_TABLE_KEY);
         if (!this.tables.contains(IPV4_UCAST_TABLE_KEY)) {
             final HashSet<TablesKey> newSet = new HashSet<>(this.tables);
             newSet.add(IPV4_UCAST_TABLE_KEY);
@@ -454,13 +486,13 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         }
     }
 
         }
     }
 
-    private synchronized void createAdjRibOutListener(final TablesKey key,
-                                                      final boolean mpSupport) {
+    @Holding("this")
+    private void createAdjRibOutListener(final TablesKey key, final boolean mpSupport) {
         final RIBSupport<?, ?, ?, ?> ribSupport = this.rib.getRibSupportContext().getRIBSupport(key);
 
         // not particularly nice
         final RIBSupport<?, ?, ?, ?> ribSupport = this.rib.getRibSupportContext().getRIBSupport(key);
 
         // not particularly nice
-        if (ribSupport != null && this.session instanceof BGPSessionImpl) {
-            final ChannelOutputLimiter limiter = ((BGPSessionImpl) this.session).getLimiter();
+        if (ribSupport != null && this.currentSession instanceof BGPSessionImpl) {
+            final ChannelOutputLimiter limiter = ((BGPSessionImpl) this.currentSession).getLimiter();
             final AdjRibOutListener adjRibOut = AdjRibOutListener.create(this.peerId, key,
                     this.rib.getYangRibId(), this.rib.getCodecsRegistry(), ribSupport,
                     this.rib.getService(), limiter, mpSupport);
             final AdjRibOutListener adjRibOut = AdjRibOutListener.create(this.peerId, key,
                     this.rib.getYangRibId(), this.rib.getCodecsRegistry(), ribSupport,
                     this.rib.getService(), limiter, mpSupport);
@@ -470,11 +502,11 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     }
 
     @Override
     }
 
     @Override
-    public synchronized void onSessionDown(final BGPSession session, final Exception e) {
-        if (e.getMessage().equals(BGPSessionImpl.END_OF_INPUT)) {
+    public synchronized void onSessionDown(final BGPSession session, final Exception exc) {
+        if (exc.getMessage().equals(BGPSessionImpl.END_OF_INPUT)) {
             LOG.info("Session with peer {} went down", this.name);
         } else {
             LOG.info("Session with peer {} went down", this.name);
         } else {
-            LOG.info("Session with peer {} went down", this.name, e);
+            LOG.info("Session with peer {} went down", this.name, exc);
         }
         releaseConnectionGracefully();
     }
         }
         releaseConnectionGracefully();
     }
@@ -487,10 +519,8 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
     @Override
     public String toString() {
 
     @Override
     public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("name", this.name)
-                .add("tables", this.tables).toString();
-        }
+        return MoreObjects.toStringHelper(this).add("name", this.name).add("tables", this.tables).toString();
+    }
 
     @Override
     public synchronized FluentFuture<? extends CommitInfo> releaseConnection() {
 
     @Override
     public synchronized FluentFuture<? extends CommitInfo> releaseConnection() {
@@ -512,19 +542,25 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         }
         releaseBindingChain();
 
         }
         releaseBindingChain();
 
-        if (this.session != null) {
+        closeSession();
+        return future;
+    }
+
+    @Holding("this")
+    @SuppressWarnings("checkstyle:illegalCatch")
+    private void closeSession() {
+        if (this.currentSession != null) {
             try {
                 if (isRestartingGracefully()) {
             try {
                 if (isRestartingGracefully()) {
-                    this.session.closeWithoutMessage();
+                    this.currentSession.closeWithoutMessage();
                 } else {
                 } else {
-                    this.session.close();
+                    this.currentSession.close();
                 }
             } catch (final Exception e) {
                 LOG.warn("Error closing session with peer", e);
             }
                 }
             } catch (final Exception e) {
                 LOG.warn("Error closing session with peer", e);
             }
-            this.session = null;
+            this.currentSession = null;
         }
         }
-        return future;
     }
 
     private Set<TablesKey> getGracefulTables() {
     }
 
     private Set<TablesKey> getGracefulTables() {
@@ -548,7 +584,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         if (this.effRibInWriter != null) {
             this.effRibInWriter.close();
         }
         if (this.effRibInWriter != null) {
             this.effRibInWriter.close();
         }
-        this.tables = Collections.emptySet();
+        this.tables = ImmutableSet.of();
         this.addPathTableMaps = Collections.emptyMap();
         future = removePeer(this.peerPath);
         resetState();
         this.addPathTableMaps = Collections.emptyMap();
         future = removePeer(this.peerPath);
         resetState();
@@ -568,10 +604,10 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         final long elapsedNanos = this.peerRestartStopwatch.elapsed(TimeUnit.NANOSECONDS);
         if (elapsedNanos >= peerRestartTimeNanos) {
             setAfiSafiGracefulRestartState(0, false, false);
         final long elapsedNanos = this.peerRestartStopwatch.elapsed(TimeUnit.NANOSECONDS);
         if (elapsedNanos >= peerRestartTimeNanos) {
             setAfiSafiGracefulRestartState(0, false, false);
-            onSessionTerminated(this.session, new BGPTerminationReason(BGPError.HOLD_TIMER_EXPIRED));
+            onSessionTerminated(this.currentSession, new BGPTerminationReason(BGPError.HOLD_TIMER_EXPIRED));
         }
         }
-        new ScheduledThreadPoolExecutor(1)
-                .schedule(this::handleRestartTimer, peerRestartTimeNanos - elapsedNanos, TimeUnit.NANOSECONDS);
+
+        currentSession.schedule(this::handleRestartTimer, peerRestartTimeNanos - elapsedNanos, TimeUnit.NANOSECONDS);
     }
 
     private synchronized void handleSelectionReferralTimer() {
     }
 
     private synchronized void handleSelectionReferralTimer() {
@@ -579,14 +615,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
             return;
         }
 
             return;
         }
 
-        final long referalTimerNanos = TimeUnit.SECONDS.toNanos(this.selectionDeferralTimerSeconds);
+        final long referalTimerNanos = TimeUnit.SECONDS.toNanos(this.currentSelectionDeferralTimerSeconds);
         final long elapsedNanos = this.peerRestartStopwatch.elapsed(TimeUnit.NANOSECONDS);
         if (elapsedNanos >= referalTimerNanos) {
             this.missingEOT.clear();
             handleGracefulEndOfRib();
         }
         final long elapsedNanos = this.peerRestartStopwatch.elapsed(TimeUnit.NANOSECONDS);
         if (elapsedNanos >= referalTimerNanos) {
             this.missingEOT.clear();
             handleGracefulEndOfRib();
         }
-        new ScheduledThreadPoolExecutor(1)
-                .schedule(this::handleSelectionReferralTimer, referalTimerNanos - elapsedNanos, TimeUnit.NANOSECONDS);
+        currentSession.schedule(this::handleSelectionReferralTimer, referalTimerNanos - elapsedNanos,
+            TimeUnit.NANOSECONDS);
     }
 
     private void releaseConnectionGracefully() {
     }
 
     private void releaseConnectionGracefully() {
@@ -604,7 +640,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
     @Override
     public boolean supportsTable(final TablesKey tableKey) {
 
     @Override
     public boolean supportsTable(final TablesKey tableKey) {
-        return this.tables.contains(tableKey) && this.sessionUp;
+        return this.sessionUp && getAfiSafisAdvertized().contains(tableKey);
     }
 
     @Override
     }
 
     @Override
@@ -613,8 +649,15 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     }
 
     @Override
     }
 
     @Override
-    public synchronized void onTransactionChainFailed(final TransactionChain<?, ?> chain,
-            final AsyncTransaction<?, ?> transaction, final Throwable cause) {
+    public synchronized void onTransactionChainFailed(final DOMTransactionChain chain,
+            final DOMDataTreeTransaction transaction, final Throwable cause) {
+        LOG.error("Transaction domChain failed.", cause);
+        releaseConnection();
+    }
+
+    @Override
+    public synchronized void onTransactionChainFailed(final TransactionChain chain, final Transaction transaction,
+            final Throwable cause) {
         LOG.error("Transaction domChain failed.", cause);
         releaseConnection();
     }
         LOG.error("Transaction domChain failed.", cause);
         releaseConnection();
     }
@@ -626,24 +669,24 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
     @Override
     public synchronized BGPSessionState getBGPSessionState() {
 
     @Override
     public synchronized BGPSessionState getBGPSessionState() {
-        if (this.session instanceof BGPSessionStateProvider) {
-            return ((BGPSessionStateProvider) this.session).getBGPSessionState();
+        if (this.currentSession instanceof BGPSessionStateProvider) {
+            return ((BGPSessionStateProvider) this.currentSession).getBGPSessionState();
         }
         return null;
     }
 
     @Override
     public synchronized BGPTimersState getBGPTimersState() {
         }
         return null;
     }
 
     @Override
     public synchronized BGPTimersState getBGPTimersState() {
-        if (this.session instanceof BGPSessionStateProvider) {
-            return ((BGPSessionStateProvider) this.session).getBGPTimersState();
+        if (this.currentSession instanceof BGPSessionStateProvider) {
+            return ((BGPSessionStateProvider) this.currentSession).getBGPTimersState();
         }
         return null;
     }
 
     @Override
     public synchronized BGPTransportState getBGPTransportState() {
         }
         return null;
     }
 
     @Override
     public synchronized BGPTransportState getBGPTransportState() {
-        if (this.session instanceof BGPSessionStateProvider) {
-            return ((BGPSessionStateProvider) this.session).getBGPTransportState();
+        if (this.currentSession instanceof BGPSessionStateProvider) {
+            return ((BGPSessionStateProvider) this.currentSession).getBGPTransportState();
         }
         return null;
     }
         }
         return null;
     }
@@ -662,11 +705,16 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
                     "Peer is not capable of graceful restart"));
         }
         setGracefulPreferences(true, tablesToPreserve);
                     "Peer is not capable of graceful restart"));
         }
         setGracefulPreferences(true, tablesToPreserve);
-        this.selectionDeferralTimerSeconds = selectionDeferralTimerSeconds;
+        this.currentSelectionDeferralTimerSeconds = selectionDeferralTimerSeconds;
         setLocalRestartingState(true);
         return releaseConnection();
     }
 
         setLocalRestartingState(true);
         return releaseConnection();
     }
 
+    @Override
+    boolean supportsLLGR() {
+        return this.llgrSupport;
+    }
+
     private synchronized void setGracefulPreferences(final boolean localRestarting,
                                                      final Set<TablesKey> preservedTables) {
         final Set<TablesKey> gracefulTables = this.tables.stream()
     private synchronized void setGracefulPreferences(final boolean localRestarting,
                                                      final Set<TablesKey> preservedTables) {
         final Set<TablesKey> gracefulTables = this.tables.stream()