Fix some rib-impl warnigs
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / AbstractPeer.java
index 3b11484ad44ebe7332daf4eb94243b82d4c48dab..4d0eb7b8105115971396e7ff9accd63eab89368b 100644 (file)
@@ -11,7 +11,9 @@ import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
@@ -33,6 +35,7 @@ import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+import org.opendaylight.protocol.bgp.rib.spi.entry.AbstractAdvertizedRoute;
 import org.opendaylight.protocol.bgp.rib.spi.entry.ActualBestPathRoutes;
 import org.opendaylight.protocol.bgp.rib.spi.entry.AdvertizedRoute;
 import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryDependenciesContainer;
@@ -91,8 +94,10 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
             @Nullable final AsNumber localAs,
             final IpAddress neighborAddress,
             final Set<TablesKey> afiSafisAdvertized,
-            final Set<TablesKey> afiSafisGracefulAdvertized) {
-        super(rib.getInstanceIdentifier(), groupId, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized);
+            final Set<TablesKey> afiSafisGracefulAdvertized,
+            final Map<TablesKey, Integer> afiSafisLlGracefulAdvertized) {
+        super(rib.getInstanceIdentifier(), groupId, neighborAddress, afiSafisAdvertized, afiSafisGracefulAdvertized,
+                afiSafisLlGracefulAdvertized);
         this.name = peerName;
         this.peerRole = role;
         this.clusterId = clusterId;
@@ -109,7 +114,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
             final IpAddress neighborAddress,
             final Set<TablesKey> afiSafisGracefulAdvertized) {
         this(rib, peerName, groupId, role, null, null, neighborAddress,
-                rib.getLocalTablesKeys(), afiSafisGracefulAdvertized);
+                rib.getLocalTablesKeys(), afiSafisGracefulAdvertized, Collections.emptyMap());
     }
 
     final synchronized FluentFuture<? extends CommitInfo> removePeer(@Nullable final YangInstanceIdentifier peerPath) {
@@ -140,7 +145,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     }
 
     @Override
-    public synchronized final PeerId getPeerId() {
+    public final synchronized PeerId getPeerId() {
         return this.peerId;
     }
 
@@ -217,38 +222,42 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
             R extends Route & ChildOf<? super S> & Identifiable<I>,
-            I extends Identifier<R>> void initializeRibOut(
-            final RouteEntryDependenciesContainer entryDep,
-            final List<ActualBestPathRoutes<C, S, R, I>> routesToStore) {
+            I extends Identifier<R>> void initializeRibOut(final RouteEntryDependenciesContainer entryDep,
+                    final List<ActualBestPathRoutes<C, S, R, I>> routesToStore) {
         if (this.bindingChain == null) {
             LOG.debug("Session closed, skip changes to peer AdjRibsOut {}", getPeerId());
             return;
         }
 
-        final RIBSupport<C,S,R,I> ribSupport = entryDep.getRIBSupport();
+        final RIBSupport<C, S, R, I> ribSupport = entryDep.getRIBSupport();
         final TablesKey tk = entryDep.getRIBSupport().getTablesKey();
         final boolean addPathSupported = supportsAddPathSupported(tk);
 
         final WriteTransaction tx = this.bindingChain.newWriteOnlyTransaction();
-        for(final ActualBestPathRoutes<C,S,R,I> initializingRoute :routesToStore) {
+        for (final ActualBestPathRoutes<C, S, R, I> initializingRoute : routesToStore) {
+            if (!supportsLLGR() && initializingRoute.isDepreferenced()) {
+                // Stale Long-lived Graceful Restart routes should not be propagated
+                continue;
+            }
+
             final PeerId fromPeerId = initializingRoute.getFromPeerId();
-            final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
             if (!filterRoutes(fromPeerId, ribSupport.getTablesKey())) {
                 continue;
             }
-            final R route = initializingRoute.getRoute();
 
+            final R route = initializingRoute.getRoute();
+            final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
             final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
                     this, route.getRouteKey(), this.rtCache);
+
             final Optional<Attributes> effAttr = entryDep.getRoutingPolicies()
                     .applyExportPolicies(routeEntry, initializingRoute.getAttributes(), entryDep.getAfiSafType());
             final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
 
             effAttr.ifPresent(attributes
-                    -> storeRoute(ribSupport, addPathSupported, tableRibout, initializingRoute, route, attributes, tx));
+                -> storeRoute(ribSupport, addPathSupported, tableRibout, initializingRoute, route, attributes, tx));
         }
 
         final FluentFuture<? extends CommitInfo> future = tx.commit();
@@ -311,32 +320,30 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         final boolean addPathSupported = supportsAddPathSupported(tk);
 
         final WriteTransaction tx = this.bindingChain.newWriteOnlyTransaction();
-        for(final ActualBestPathRoutes<C,S,R,I> actualBestRoute :routesToStore) {
+        for (final ActualBestPathRoutes<C, S, R, I> actualBestRoute : routesToStore) {
             final PeerId fromPeerId = actualBestRoute.getFromPeerId();
-            final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
             if (!filterRoutes(fromPeerId, ribSupport.getTablesKey())) {
                 continue;
             }
-            final R route = actualBestRoute.getRoute();
 
-            final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
+            final R route = actualBestRoute.getRoute();
+            final Optional<Attributes> effAttr;
+            if (supportsLLGR() || !actualBestRoute.isDepreferenced()) {
+                final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
+                final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
                     this, route.getRouteKey(), this.rtCache);
-            final Optional<Attributes> effAttr = entryDep.getRoutingPolicies()
-                    .applyExportPolicies(routeEntry, actualBestRoute.getAttributes(), entryDep.getAfiSafType());
+                effAttr = entryDep.getRoutingPolicies()
+                        .applyExportPolicies(routeEntry, actualBestRoute.getAttributes(), entryDep.getAfiSafType());
+            } else {
+                // Stale Long-lived Graceful Restart routes should not be propagated
+                effAttr = Optional.empty();
+            }
+
             final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
             if (effAttr.isPresent()) {
                 storeRoute(ribSupport, addPathSupported, tableRibout, actualBestRoute, route, effAttr.get(), tx);
             } else {
-                final InstanceIdentifier<R> ribOut;
-                if (!addPathSupported) {
-                    ribOut = ribSupport.createRouteIdentifier(tableRibout,
-                            actualBestRoute.getNonAddPathRouteKeyIdentifier());
-                } else {
-                    ribOut = ribSupport.createRouteIdentifier(tableRibout,
-                            actualBestRoute.getAddPathRouteKeyIdentifier());
-                }
-                LOG.debug("Write advRoute {} to peer AdjRibsOut {}", actualBestRoute, getPeerId());
-                tx.delete(LogicalDatastoreType.OPERATIONAL, ribOut);
+                deleteRoute(ribSupport, addPathSupported, tableRibout, actualBestRoute, tx);
             }
         }
 
@@ -356,32 +363,44 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     }
 
     private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
-            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
-    void installRouteRibOut(final RouteEntryDependenciesContainer entryDep,
-            final List<AdvertizedRoute<C,S,R,I>> routes, final WriteTransaction tx) {
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>> void installRouteRibOut(
+                    final RouteEntryDependenciesContainer entryDep, final List<AdvertizedRoute<C, S, R, I>> routes,
+                    final WriteTransaction tx) {
         final TablesKey tk = entryDep.getRIBSupport().getTablesKey();
         final BGPPeerTracker peerTracker = entryDep.getPeerTracker();
-        final RIBSupport<C,S,R,I> ribSupport = entryDep.getRIBSupport();
+        final RIBSupport<C, S, R, I> ribSupport = entryDep.getRIBSupport();
         final BGPRibRoutingPolicy routingPolicies = entryDep.getRoutingPolicies();
         final boolean addPathSupported = supportsAddPathSupported(tk);
+        final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
 
-        for (final AdvertizedRoute<C,S,R,I> advRoute:routes) {
+        for (final AdvertizedRoute<C, S, R, I> advRoute : routes) {
             final PeerId fromPeerId = advRoute.getFromPeerId();
             if (!filterRoutes(fromPeerId, tk) || !advRoute.isFirstBestPath() && !addPathSupported) {
                 continue;
             }
+            if (!supportsLLGR() && advRoute.isDepreferenced()) {
+                // https://tools.ietf.org/html/draft-uttaro-idr-bgp-persistence-04#section-4.3
+                //     o  The route SHOULD NOT be advertised to any neighbor from which the
+                //        Long-lived Graceful Restart Capability has not been received.  The
+                //        exception is described in the Optional Partial Deployment
+                //        Procedure section (Section 4.7).  Note that this requirement
+                //        implies that such routes should be withdrawn from any such
+                //        neighbor.
+                deleteRoute(ribSupport, addPathSupported, tableRibout, advRoute, tx);
+                continue;
+            }
+
             final R route = advRoute.getRoute();
-            final Attributes attributes = advRoute.getAttributes();
             Optional<Attributes> effAttr = Optional.empty();
             final Peer fromPeer = peerTracker.getPeer(fromPeerId);
+            final Attributes attributes = advRoute.getAttributes();
             if (fromPeer != null && attributes != null) {
                 final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
                         this, route.getRouteKey(), this.rtCache);
                 effAttr = routingPolicies.applyExportPolicies(routeEntry, attributes, entryDep.getAfiSafType());
             }
-            final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
             effAttr.ifPresent(attributes1
-                    -> storeRoute(ribSupport, addPathSupported, tableRibout, advRoute, route, attributes1, tx));
+                -> storeRoute(ribSupport, addPathSupported, tableRibout, advRoute, route, attributes1, tx));
         }
     }
 
@@ -395,15 +414,15 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
         final boolean addPathSupported = supportsAddPathSupported(tk);
         staleRoutesIid.forEach(staleRouteIid
-                -> removeRoute(ribSupport, addPathSupported, tableRibout, staleRouteIid, tx));
+            -> removeRoute(ribSupport, addPathSupported, tableRibout, staleRouteIid, tx));
     }
 
     private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
-            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
-    void storeRoute(final RIBSupport<C, S, R, I> ribSupport, final boolean addPathSupported,
-            final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout,
-            final RouteKeyIdentifier<R, I> advRoute, final R route, final Attributes effAttr,
-            final WriteTransaction tx) {
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>> void storeRoute(
+                    final RIBSupport<C, S, R, I> ribSupport, final boolean addPathSupported,
+                    final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout,
+                    final RouteKeyIdentifier<R, I> advRoute, final R route, final Attributes effAttr,
+                    final WriteTransaction tx) {
         final InstanceIdentifier<R> ribOut;
         final I newKey;
         if (!addPathSupported) {
@@ -442,6 +461,18 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         }
     }
 
+    // FIXME: why is this different from removeRoute()?
+    private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>> void deleteRoute(
+            final RIBSupport<C, S, R, I> ribSupport,  final boolean addPathSupported,
+            final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout,
+            final AbstractAdvertizedRoute<C, S , R, I> advRoute, final WriteTransaction tx) {
+        final InstanceIdentifier<R> ribOutTarget = ribSupport.createRouteIdentifier(tableRibout,
+            addPathSupported ? advRoute.getAddPathRouteKeyIdentifier() : advRoute.getNonAddPathRouteKeyIdentifier());
+        LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, getPeerId());
+        tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
+    }
+
     final synchronized void releaseBindingChain() {
         if (this.submitted != null) {
             try {
@@ -468,4 +499,8 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
             this.domChain = null;
         }
     }
+
+    boolean supportsLLGR() {
+        return false;
+    }
 }