Add LLGR restart utilities 75/78775/6
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 13 Dec 2018 22:49:45 +0000 (23:49 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 14 Dec 2018 04:38:03 +0000 (05:38 +0100)
This adds utilities for dealing with LLGR capabilities and
advertizements.

JIRA: BGPCEP-495
Change-Id: I34a43270af8792f45e4a9c808eaa45febf1f7d7e
Signed-off-by: Matej Perina <matej.perina@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
bgp/parser-api/src/main/java/org/opendaylight/protocol/bgp/parser/GracefulRestartUtil.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BgpPeerUtil.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/GracefulRestartUtil.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/GracefulRestartUtilTest.java

index 420ca2d148806bf46eae0dd65a5539481f886e47..67c1f3931d1ac57d9f0a10610031977452de5133 100644 (file)
@@ -7,12 +7,24 @@
  */
 package org.opendaylight.protocol.bgp.parser;
 
+import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.optional.capabilities.CParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapability.RestartFlags;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.LlGracefulRestartCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.LlGracefulRestartCapabilityBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.Tables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.Tables.AfiFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.TablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.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.SubsequentAddressFamily;
 
 /**
  * Utility class for dealing with Graceful Restart.
@@ -37,4 +49,27 @@ public final class GracefulRestartUtil {
     private GracefulRestartUtil() {
 
     }
+
+    @Beta
+    public static Tables gracefulRestartTable(final Class<? extends AddressFamily> afi,
+            final Class<? extends SubsequentAddressFamily> safi, final boolean forwardingState) {
+        return gracefulRestartTable(new TablesKey(afi, safi), forwardingState);
+    }
+
+    @Beta
+    public static Tables gracefulRestartTable(final TablesKey table, final boolean forwardingState) {
+        return new TablesBuilder().withKey(table).setAfiFlags(new AfiFlags(forwardingState)).build();
+    }
+
+    @Beta
+    public static CParameters gracefulRestartCapability(final List<Tables> tables, final int restartTime,
+            final boolean localRestarting) {
+        return new CParametersBuilder().addAugmentation(CParameters1.class, new CParameters1Builder()
+            .setGracefulRestartCapability(new GracefulRestartCapabilityBuilder()
+                .setRestartFlags(new RestartFlags(localRestarting))
+                .setRestartTime(restartTime)
+                .setTables(tables)
+                .build())
+            .build()).build();
+    }
 }
index fd568c63c3a89477ed6179d1f5dc9977f647a8d6..fc79c5de97a0d27ed54eeda446650370fc42fb74 100644 (file)
@@ -680,7 +680,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
                 .collect(Collectors.toSet());
         final BgpParameters bgpParameters = GracefulRestartUtil.getGracefulBgpParameters(
                 this.bgpPeer.getBgpFixedCapabilities(), gracefulTables, preservedTables,
-                this.bgpPeer.getGracefulRestartTimer(), localRestarting);
+                this.bgpPeer.getGracefulRestartTimer(), localRestarting, Collections.emptySet());
         final BGPSessionPreferences oldPrefs = this.rib.getDispatcher().getBGPPeerRegistry()
                 .getPeerPreferences(getNeighborAddress());
         final BGPSessionPreferences newPrefs = new BGPSessionPreferences(
index d2d9545823e5b92bd0715d8277af4c3e46a40fb7..732cbc276f3accf0466f90f09731a2f8b2a80dd3 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import static java.util.Objects.requireNonNull;
+
 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.UpdateBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.UpdateMessage;
@@ -68,4 +70,34 @@ public final class BgpPeerUtil {
         return false;
     }
 
+    /**
+     * @deprecated This class is deprecated for refactoring.
+     */
+    // FIXME: there should be no need for this class, as we should be able to efficiently translate TableKey classes
+    //        and rely on yang-parser-api.
+    @Deprecated
+    public static final class LlGracefulRestartDTO {
+
+        private final TablesKey tableKey;
+        private final int staleTime;
+        private final boolean forwardingFlag;
+
+        public LlGracefulRestartDTO (final TablesKey tableKey, final int staleTime, final boolean forwardingFlag) {
+            this.tableKey = requireNonNull(tableKey);
+            this.staleTime = staleTime;
+            this.forwardingFlag = forwardingFlag;
+        }
+
+        public TablesKey getTableKey() {
+            return tableKey;
+        }
+
+        public int getStaleTime() {
+            return staleTime;
+        }
+
+        public boolean isForwarding() {
+            return forwardingFlag;
+        }
+    }
 }
index 7a534ad9ab7b08252e3deff9104afa09f69b5529..50661d60f6c10f621cf6e5a8aa2b2f4b6e1ea82e 100644 (file)
@@ -294,7 +294,7 @@ public class BgpPeer implements PeerBean, BGPPeerStateConsumer {
         private List<BgpParameters> getInitialBgpParameters(final Set<TablesKey> gracefulTables) {
             return Collections.singletonList(
                     GracefulRestartUtil.getGracefulBgpParameters(this.finalCapabilities, gracefulTables,
-                            Collections.emptySet(), gracefulRestartTimer, false));
+                            Collections.emptySet(), gracefulRestartTimer, false, Collections.emptySet()));
         }
 
         private synchronized void instantiateServiceInstance() {
index f5ae70e5df5d2a0795bbd1dc14adcedb005a1834..fbe55e1295570dabcdc0346ffec2be63d2ddac6c 100644 (file)
@@ -7,8 +7,11 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
+import static org.opendaylight.protocol.bgp.parser.GracefulRestartUtil.gracefulRestartCapability;
+import static org.opendaylight.protocol.bgp.parser.GracefulRestartUtil.gracefulRestartTable;
+
+import com.google.common.collect.Maps;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -17,8 +20,14 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
+import org.opendaylight.protocol.bgp.rib.impl.BgpPeerUtil;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.afi.safi.GracefulRestart;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.afi.safi.graceful.restart.Config;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.Config1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.Config2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.afi.safi.ll.graceful.restart.LlGracefulRestart;
 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.open.message.BgpParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.OptionalCapabilities;
@@ -27,40 +36,52 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.optional.capabilities.CParametersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1Builder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapability;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapabilityBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.Tables;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.TablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.LlGracefulRestartCapabilityBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+/**
+ * @deprecated This class is competing with bgp-parser-api's view of GR and will be renamed and/or eliminated.
+ */
+// FIXME: This functionality should live in bgp-parser-api, except the use of RIB version of TablesKey prevents that.
+//        We should be able to refactor this class by providing TablesKey translation somewhere.
+@Deprecated
 public final class GracefulRestartUtil {
-
-    public static final GracefulRestartCapability EMPTY_GRACEFUL_CAPABILITY = new GracefulRestartCapabilityBuilder()
-            .setRestartTime(0)
-            .setTables(Collections.emptyList())
-            .setRestartFlags(new GracefulRestartCapability.RestartFlags(false))
-            .build();
+    private static final Logger LOG = LoggerFactory.getLogger(GracefulRestartUtil.class);
 
     private GracefulRestartUtil() {
-        throw new UnsupportedOperationException();
+
     }
 
-    static CParameters getGracefulCapability(final Map<TablesKey, Boolean> tables,
+    public static CParameters getGracefulCapability(final Map<TablesKey, Boolean> tables,
                                                     final int restartTime,
                                                     final boolean localRestarting) {
-        final List<Tables> tablesList = tables.entrySet().stream()
-                .map(entry -> new TablesBuilder()
-                        .setAfi(entry.getKey().getAfi())
-                        .setSafi(entry.getKey().getSafi())
-                        .setAfiFlags(new Tables.AfiFlags(entry.getValue()))
+        return gracefulRestartCapability(tables.entrySet().stream()
+            .map(entry -> {
+                final TablesKey key = entry.getKey();
+                return gracefulRestartTable(key.getAfi(), key.getSafi(), entry.getValue());
+            })
+            .collect(Collectors.toList()), restartTime, localRestarting);
+    }
+
+    public static CParameters getLlGracefulCapability(final Set<BgpPeerUtil.LlGracefulRestartDTO> llGracefulRestarts) {
+        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.ll.graceful.restart.capability.Tables> tablesList =
+                llGracefulRestarts.stream()
+                .map(dto -> new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.ll.graceful.restart.capability.TablesBuilder()
+                        .setAfi(dto.getTableKey().getAfi())
+                        .setSafi(dto.getTableKey().getSafi())
+                        .setAfiFlags(
+                                new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.ll.graceful.restart.capability.Tables.AfiFlags(
+                                        dto.isForwarding()))
+                        .setLongLiveStaleTime((long) dto.getStaleTime())
                         .build())
                 .collect(Collectors.toList());
-       return new CParametersBuilder().addAugmentation(CParameters1.class,
-                new CParameters1Builder().setGracefulRestartCapability(new GracefulRestartCapabilityBuilder()
-                        .setRestartFlags(new GracefulRestartCapability.RestartFlags(localRestarting))
-                        .setRestartTime(restartTime)
+        return new CParametersBuilder().addAugmentation(CParameters1.class,
+                new CParameters1Builder().setLlGracefulRestartCapability(
+                        new LlGracefulRestartCapabilityBuilder()
                         .setTables(tablesList)
-               .build()).build()).build();
+                        .build()).build()).build();
     }
 
     static Set<TablesKey> getGracefulTables(final List<AfiSafi> afiSafis,
@@ -83,17 +104,62 @@ public final class GracefulRestartUtil {
         return gracefulTables;
     }
 
+    static Map<TablesKey, Integer> getLlGracefulTimers(final List<AfiSafi> afiSafis,
+                                                       final BGPTableTypeRegistryConsumer tableTypeRegistry) {
+        final Map<TablesKey, Integer> timers = new HashMap<>();
+        afiSafis.forEach(afiSafi -> {
+            final GracefulRestart gracefulRestart = afiSafi.getGracefulRestart();
+            if (gracefulRestart != null) {
+                final Config gracefulRestartConfig = gracefulRestart.getConfig();
+                if (gracefulRestartConfig != null) {
+                    final LlGracefulRestart llGracefulRestart;
+                    final Config1 peerAug = gracefulRestartConfig.augmentation(Config1.class);
+                    if (peerAug != null) {
+                       llGracefulRestart = peerAug.getLlGracefulRestart();
+                    } else {
+                        final Config2 neighborAug = gracefulRestartConfig.augmentation(Config2.class);
+                        if (neighborAug != null) {
+                            llGracefulRestart = neighborAug.getLlGracefulRestart();
+                        } else {
+                            return;
+                        }
+                    }
+                    if (llGracefulRestart != null) {
+                        final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart
+                                .rev181112.afi.safi.ll.graceful.restart.ll.graceful.restart.Config config =
+                                llGracefulRestart.getConfig();
+                        if(config != null) {
+                            final Long staleTime = config.getLongLivedStaleTime();
+                            if (staleTime != null && staleTime > 0) {
+                                final Optional<TablesKey> key = tableTypeRegistry.getTableKey(afiSafi.getAfiSafiName());
+                                if (key.isPresent()) {
+                                    timers.put(key.get(), staleTime.intValue());
+                                } else {
+                                    LOG.debug("Skipping unsupported afi-safi {}",afiSafi.getAfiSafiName());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        });
+        return timers;
+    }
+
     public static BgpParameters getGracefulBgpParameters(final List<OptionalCapabilities> fixedCapabilities,
                                                          final Set<TablesKey> gracefulTables,
                                                          final Set<TablesKey> preservedTables,
                                                          final int gracefulRestartTimer,
-                                                         final boolean localRestarting) {
+                                                         final boolean localRestarting,
+                                                         final Set<BgpPeerUtil.LlGracefulRestartDTO> llGracefulDTOs) {
         final List<OptionalCapabilities> capabilities = new ArrayList<>(fixedCapabilities);
-        final Map<TablesKey, Boolean> gracefulMap = new HashMap<>();
-        gracefulTables.forEach(table -> gracefulMap.put(table, preservedTables.contains(table)));
-        final CParameters gracefulCapability = getGracefulCapability(gracefulMap,
-                gracefulRestartTimer, localRestarting);
-        capabilities.add(new OptionalCapabilitiesBuilder().setCParameters(gracefulCapability).build());
+        capabilities.add(new OptionalCapabilitiesBuilder()
+            .setCParameters(getGracefulCapability(Maps.asMap(gracefulTables, preservedTables::contains),
+                gracefulRestartTimer, localRestarting))
+            .build());
+        capabilities.add(new OptionalCapabilitiesBuilder()
+            .setCParameters(getLlGracefulCapability(llGracefulDTOs))
+            .build());
 
         return new BgpParametersBuilder().setOptionalCapabilities(capabilities).build();
     }
index e39ac612626f77bb74673151afcbdb214c29ba51..fd8c63bf6bd4b209293f1b0a8f0b00d9bd6981b7 100644 (file)
@@ -14,6 +14,7 @@ import static org.mockito.Mockito.doReturn;
 import static org.mockito.MockitoAnnotations.initMocks;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -26,6 +27,7 @@ import org.mockito.Mock;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil;
 import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
+import org.opendaylight.protocol.bgp.rib.impl.BgpPeerUtil;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiBuilder;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.afi.safi.GracefulRestartBuilder;
@@ -33,12 +35,16 @@ import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.r
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4LABELLEDUNICAST;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV6UNICAST;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.Config1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.Config1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.afi.safi.ll.graceful.restart.LlGracefulRestartBuilder;
 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.open.message.bgp.parameters.OptionalCapabilities;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.OptionalCapabilitiesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.open.message.bgp.parameters.optional.capabilities.CParameters;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.CParameters1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.GracefulRestartCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.LlGracefulRestartCapability;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.graceful.restart.capability.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.Ipv4AddressFamily;
@@ -48,6 +54,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.type
 public class GracefulRestartUtilTest {
 
     private static final int RESTART_TIME = 5;
+    private static final int STALE_TIME = 10;
     private static final boolean RESTARTING = true;
     private static final AfiSafi IPV4_UNICAST_AFISAFI = new AfiSafiBuilder()
             .setAfiSafiName(IPV4UNICAST.class)
@@ -138,15 +145,65 @@ public class GracefulRestartUtilTest {
         final OptionalCapabilities expectedGracefulCapability = new OptionalCapabilitiesBuilder()
                 .setCParameters(GracefulRestartUtil.getGracefulCapability(gracefulMap, RESTART_TIME, RESTARTING))
                 .build();
+        final Set<BgpPeerUtil.LlGracefulRestartDTO> llGracefulDTOs = Collections.singleton(
+                new BgpPeerUtil.LlGracefulRestartDTO(IPV4_KEY, STALE_TIME, true));
+        final OptionalCapabilities expectedLlGracefulCapability = new OptionalCapabilitiesBuilder()
+                .setCParameters(GracefulRestartUtil.getLlGracefulCapability(llGracefulDTOs))
+                .build();
         final BgpParameters parameters = GracefulRestartUtil.getGracefulBgpParameters(fixedCaps, gracefulTables,
-                preservedTables, RESTART_TIME, RESTARTING);
+                preservedTables, RESTART_TIME, RESTARTING, llGracefulDTOs);
         final List<OptionalCapabilities> capabilities = parameters.getOptionalCapabilities();
         assertTrue(capabilities != null);
-        assertEquals(3, capabilities.size());
+        assertEquals(4, capabilities.size());
         assertTrue(capabilities.contains(cap1));
         assertTrue(capabilities.contains(cap2));
         assertTrue(capabilities.contains(expectedGracefulCapability));
+        assertTrue(capabilities.contains(expectedLlGracefulCapability));
+    }
 
+    @Test
+    public void getLlGracefulCapabilityTest() {
+        final Set<BgpPeerUtil.LlGracefulRestartDTO> llGracefulRestartDTOs = new HashSet<>();
+        llGracefulRestartDTOs.add(new BgpPeerUtil.LlGracefulRestartDTO(IPV4_KEY, STALE_TIME, true));
+        llGracefulRestartDTOs.add(new BgpPeerUtil.LlGracefulRestartDTO(IPV6_KEY, STALE_TIME, false));
+        CParameters capability = GracefulRestartUtil.getLlGracefulCapability(llGracefulRestartDTOs);
+        final CParameters1 params = capability.augmentation(CParameters1.class);
+        assertNotNull(params);
+        final LlGracefulRestartCapability llGracefulCapability = params.getLlGracefulRestartCapability();
+        assertNotNull(llGracefulCapability);
+        final List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.ll.graceful.restart.capability.Tables> tables =
+                llGracefulCapability.getTables();
+        assertNotNull(tables);
+        assertEquals(2, tables.size());
+        assertEquals(STALE_TIME, tables.get(0).getLongLiveStaleTime().intValue());
+        tables.forEach(table -> {
+            assertTrue((isSameKey(IPV4_KEY, table.key()) && table.getAfiFlags().isForwardingState()) ||
+                    (isSameKey(IPV6_KEY, table.key()) && !table.getAfiFlags().isForwardingState()));
+        });
+    }
+
+    @Test
+    public void getLlGracefulTimersTest() {
+        final List<AfiSafi> afiSafi = new ArrayList<>();
+        afiSafi.add(new AfiSafiBuilder()
+                .setAfiSafiName(IPV4UNICAST.class)
+                .setGracefulRestart(new GracefulRestartBuilder()
+                        .setConfig(new ConfigBuilder()
+                                .addAugmentation(Config1.class, new Config1Builder()
+                                        .setLlGracefulRestart(new LlGracefulRestartBuilder()
+                                                .setConfig(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.ll.graceful.restart.rev181112.afi.safi.ll.graceful.restart.ll.graceful.restart.ConfigBuilder()
+                                                        .setLongLivedStaleTime((long) STALE_TIME)
+                                                        .build())
+                                                .build())
+                                        .build())
+                                .build())
+                        .build())
+                .build());
+        final Map<TablesKey, Integer> llGracefulTimers = GracefulRestartUtil.getLlGracefulTimers(afiSafi,
+                this.tableRegistry);
+        assertNotNull(llGracefulTimers);
+        assertEquals(1, llGracefulTimers.size());
+        assertEquals(STALE_TIME, llGracefulTimers.get(IPV4_KEY).intValue());
     }
 
     private static boolean isSameKey(TablesKey key1,
@@ -154,4 +211,10 @@ public class GracefulRestartUtilTest {
         return key1.getAfi() == key2.getAfi() &&
                 key1.getSafi() == key2.getSafi();
     }
+
+    private static boolean isSameKey(TablesKey key1,
+                                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.mp.capabilities.ll.graceful.restart.capability.TablesKey key2) {
+        return key1.getAfi() == key2.getAfi() &&
+                key1.getSafi() == key2.getSafi();
+    }
 }