Split Peer Ribout storage from loc rib 53/72953/1
authorClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Mon, 4 Jun 2018 11:23:56 +0000 (13:23 +0200)
committerClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Wed, 13 Jun 2018 08:04:05 +0000 (10:04 +0200)
Meanwhile loc rib is part of rib,
loc rib out is represented per peer.
Therefore loc rib should be updated
by rib transactions chains,
and peer shuld be on charge of
handling transaction for updating ribout.
Achieving a correct sync when closing session
and cleanin datastore Peer ribs.

JIRA: BGPCEP-785
Change-Id: I891a6842c68a1d017fff22a6c0f34c2090c140bc
Signed-off-by: Claudio D. Gasparini <claudio.gasparini@pantheon.tech>
39 files changed:
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/api/PathSelectionMode.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/api/RouteEntry.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/AddPathAbstractRouteEntry.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/all/paths/AllPathSelection.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/all/paths/AllPathsRouteEntry.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/n/paths/AddPathBestNPathSelection.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/add/n/paths/NPathsRouteEntry.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BasePathSelection.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BasePathSelectionModeFactory.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/impl/base/BaseRouteEntry.java
bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/spi/AbstractRouteEntry.java [deleted file]
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AbstractPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.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/BGPPeerTrackerImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/EffectiveRibInWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/LocRibWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBSupportContextImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RouteEntryDependenciesContainerImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/OpenConfigMappingUtil.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/RibImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/PeerTransactionChain.java [new file with mode: 0644]
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractAddPathTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractRIBTestSetup.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AddPathAllPathsTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AddPathBasePathsTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AddPathNPathsTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SynchronizationAndExceptionTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/OpenConfigMappingUtilTest.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/BGPPeerTracker.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/Peer.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/ActualBestPathRoutes.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/AdvertizedRoute.java [new file with mode: 0644]
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/RouteEntryDependenciesContainer.java
bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/StaleBestPathRoute.java [new file with mode: 0644]

index e468f1f2e981f78b7734a14984645df2ee0f6dac..4d8c8975a9a4624ba2a83dedd3fbf702e48dfbd8 100644 (file)
@@ -8,25 +8,23 @@
 package org.opendaylight.protocol.bgp.mode.api;
 
 import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
 public interface PathSelectionMode extends AutoCloseable {
-    /**
-     * Create a RouteEntry.
-     *
-     * @param isComplex true if is complex
-     * @return ComplexRouteEntry if is complex otherwise a SimpleRouteEntry
-     * @deprecated All routes are complex.
-     */
-    @Deprecated
-    default @Nonnull RouteEntry createRouteEntry(boolean isComplex) {
-        return createRouteEntry();
-    }
-
     /**
      * Create a RouteEntry.
      *
      * @return ComplexRouteEntry if is complex otherwise a SimpleRouteEntry
      */
     @Nonnull
-    RouteEntry createRouteEntry();
+    <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>
+            > RouteEntry<C, S, R, I> createRouteEntry();
 }
index df4f38b8f4e29f242193c9c8b04edc7c25f1c0d2..30344b9d7d404b4ee8d449e29a3943f5d175d37e 100644 (file)
@@ -9,11 +9,22 @@
 package org.opendaylight.protocol.bgp.mode.api;
 
 import com.google.common.primitives.UnsignedInteger;
+import java.util.List;
+import java.util.Optional;
 import javax.annotation.Nonnull;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryDependenciesContainer;
+import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+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.RouteEntryInfo;
+import org.opendaylight.protocol.bgp.rib.spi.entry.StaleBestPathRoute;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
 /**
  * A single route entry inside a route table. Maintains the attributes of
@@ -22,7 +33,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.
  * maintain low memory overhead in face of large number of routes and peers,
  * where individual object overhead becomes the dominating factor.
  */
-public interface RouteEntry {
+public interface RouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>> {
     /**
      * Remove route.
      *
@@ -48,29 +60,42 @@ public interface RouteEntry {
      * @param route        route Data change
      * @return returns the offset
      */
-    int addRoute(@Nonnull UnsignedInteger routerId, long remotePathId, @Nonnull Route route);
+    int addRoute(@Nonnull UnsignedInteger routerId, long remotePathId, @Nonnull R route);
+
+
+    /**
+     * Returns collections of present selected best path.
+     *
+     * @param ribSupport RIB Support
+     * @param entryInfo  Route Entry Info wrapper
+     */
+    @Nonnull
+    List<ActualBestPathRoutes<C, S, R, I>> actualBestPaths(
+            @Nonnull RIBSupport<C, S, R, I> ribSupport,
+            @Nonnull RouteEntryInfo entryInfo);
+
 
     /**
-     * Update LocRibOut and AdjRibsOut by removing stale best path and writing new best.
+     * Returns list of stale best path.
      *
-     * @param entryDependencies entry Dependencies container
-     * @param routeKey          route key
-     * @param tx                DOM transaction
+     * @param ribSupport RIB Support
+     * @param routeKey   of stale route
+     * @return list containing list of stale best path
      */
-    void updateBestPaths(
-            @Nonnull RouteEntryDependenciesContainer entryDependencies,
-            @Nonnull String routeKey,
-            @Nonnull WriteTransaction tx);
+    @Nonnull
+    Optional<StaleBestPathRoute<C, S, R, I>
+            > removeStalePaths(
+            @Nonnull RIBSupport<C, S, R, I> ribSupport,
+            @Nonnull String routeKey);
 
     /**
-     * Initialize LocRibOut and AdjRibsOut for new peers with already present best paths.
+     * Returns collection of best path routes after processing update of stale and new advertisement of routes.
      *
-     * @param entryDependencies Route Entry Dependencies wrapper
-     * @param entryInfo         Route Entry Info wrapper
-     * @param tx                transaction
+     * @param ribSupport RIB Support
+     * @param routeKey   route key
      */
-    void initializeBestPaths(
-            @Nonnull RouteEntryDependenciesContainer entryDependencies,
-            @Nonnull RouteEntryInfo entryInfo,
-            @Nonnull WriteTransaction tx);
+    @Nonnull
+    List<AdvertizedRoute<C, S, R, I>> newBestPaths(
+            @Nonnull RIBSupport<C, S, R, I> ribSupport,
+            @Nonnull String routeKey);
 }
\ No newline at end of file
index 7670536dbd28d08e5d2f1651ea36ef853bc4f41c..2f9e1f9f4d3b090cd09a132c204b88653c97ceb7 100644 (file)
@@ -7,33 +7,28 @@
  */
 package org.opendaylight.protocol.bgp.mode.impl.add;
 
-import static org.opendaylight.protocol.bgp.parser.spi.PathIdUtil.NON_PATH_ID_VALUE;
-
 import com.google.common.collect.Lists;
 import com.google.common.primitives.UnsignedInteger;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 import javax.annotation.concurrent.NotThreadSafe;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.protocol.bgp.mode.impl.BGPRouteEntryExportParametersImpl;
-import org.opendaylight.protocol.bgp.mode.spi.AbstractRouteEntry;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
-import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
-import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
-import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryDependenciesContainer;
+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.RouteEntryInfo;
-import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
-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.rib.rev180329.PeerId;
+import org.opendaylight.protocol.bgp.rib.spi.entry.StaleBestPathRoute;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
 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.rib.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,59 +40,40 @@ import org.slf4j.LoggerFactory;
  * where individual object overhead becomes the dominating factor.
  */
 @NotThreadSafe
-public abstract class AddPathAbstractRouteEntry extends AbstractRouteEntry<AddPathBestPath> {
+public abstract class AddPathAbstractRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>,
+        S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
+        implements RouteEntry<C, S, R, I> {
 
     private static final Logger LOG = LoggerFactory.getLogger(AddPathAbstractRouteEntry.class);
     private static final Long[] EMPTY_PATHS_ID = new Long[0];
+    private static final Route[] EMPTY_VALUES = new Route[0];
 
+    protected OffsetMap offsets = OffsetMap.EMPTY;
+    protected R[] values = (R[]) EMPTY_VALUES;
+    protected Long[] pathsId = EMPTY_PATHS_ID;
     private List<AddPathBestPath> bestPath;
     private List<AddPathBestPath> bestPathRemoved;
-    protected OffsetMap offsets = OffsetMap.EMPTY;
-    protected Route[] values = EMPTY_VALUES;
-    protected Long[] pathsId =  EMPTY_PATHS_ID;
     private long pathIdCounter = 0L;
-    private boolean oldNonAddPathBestPathTheSame;
+    private boolean isNonAddPathBestPathNew;
     private List<AddPathBestPath> newBestPathToBeAdvertised;
-    private List<RemovedPath> removedPaths;
-
-    public AddPathAbstractRouteEntry(final BGPPeerTracker peerTracker) {
-        super(peerTracker);
-    }
-
-    private static final class RemovedPath {
-        private final RouteKey key;
-        private final long pathId;
-
-        RemovedPath(final RouteKey key, final long pathId) {
-            this.key = key;
-            this.pathId = pathId;
-        }
-
-        long getPathId() {
-            return this.pathId;
-        }
+    private List<Long> removedPathsId;
 
-        UnsignedInteger getRouteId() {
-            return this.key.getRouteId();
-        }
-    }
-
-    @Override
-    public final Route createRoute(final RIBSupport ribSup, final String routeKey, final long pathId,
-            final AddPathBestPath path) {
+    private R createRoute(final RIBSupport<C, S, R, I> ribSup, final String routeKey,
+            final long pathId, final AddPathBestPath path) {
         final OffsetMap map = getOffsets();
-        final Route route = map.getValue(this.values, map.offsetOf(path.getRouteKey()));
+        final R route = map.getValue(this.values, map.offsetOf(path.getRouteKey()));
         return ribSup.createRoute(route, routeKey, pathId, path.getAttributes());
     }
 
     @Override
-    public final int addRoute(final UnsignedInteger routerId, final long remotePathId, final Route route) {
+    public final int addRoute(final UnsignedInteger routerId, final long remotePathId, final R route) {
         final RouteKey key = new RouteKey(routerId, remotePathId);
         int offset = this.offsets.offsetOf(key);
         if (offset < 0) {
             final OffsetMap newOffsets = this.offsets.with(key);
             offset = newOffsets.offsetOf(key);
-            final Route[] newRoute = newOffsets.expand(this.offsets, this.values, offset);
+            final R[] newRoute = newOffsets.expand(this.offsets, this.values, offset);
             final Long[] newPathsId = newOffsets.expand(this.offsets, this.pathsId, offset);
             this.values = newRoute;
             this.offsets = newOffsets;
@@ -114,175 +90,68 @@ public abstract class AddPathAbstractRouteEntry extends AbstractRouteEntry<AddPa
         final RouteKey key = new RouteKey(routerId, remotePathId);
         final int offset = getOffsets().offsetOf(key);
         final long pathId = this.offsets.getValue(this.pathsId, offset);
-        this.values = this.offsets.removeValue(this.values, offset, EMPTY_VALUES);
+        this.values = this.offsets.removeValue(this.values, offset, (R[]) EMPTY_VALUES);
         this.pathsId = this.offsets.removeValue(this.pathsId, offset, EMPTY_PATHS_ID);
         this.offsets = this.offsets.without(key);
-        if (this.removedPaths == null) {
-            this.removedPaths = new ArrayList<>();
+        if (this.removedPathsId == null) {
+            this.removedPathsId = new ArrayList<>();
         }
-        this.removedPaths.add(new RemovedPath(key, pathId));
+        this.removedPathsId.add(pathId);
         return isEmpty();
     }
 
     @Override
-    public void updateBestPaths(
-            final RouteEntryDependenciesContainer entryDependencies,
-            final String routeKey,
-            final WriteTransaction tx) {
-
-        final RIBSupport ribSupport = entryDependencies.getRibSupport();
-        final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget = entryDependencies.getLocRibTableTarget();
-        if (this.bestPathRemoved != null) {
-            this.bestPathRemoved.forEach(path -> {
-                final Identifier newRouteKey = ribSupport.createRouteListKey(path.getPathId(), routeKey);
-                final InstanceIdentifier routeTarget = ribSupport.createRouteIdentifier(locRibTarget, newRouteKey);
-                LOG.debug("Delete route from LocRib {}", routeTarget);
-                tx.delete(LogicalDatastoreType.OPERATIONAL, routeTarget);
-            });
-            this.bestPathRemoved = null;
-        }
-        if (this.removedPaths != null) {
-            this.removedPaths.forEach(removedPath -> {
-                final Identifier routeKeyAddPath
-                        = ribSupport.createRouteListKey(removedPath.getPathId(), routeKey);
-                final Identifier routeKeyNonAddPath = ribSupport.createRouteListKey(NON_PATH_ID_VALUE, routeKey);
-                fillAdjRibsOut(true, null, null, null,
-                        routeKeyNonAddPath, routeKeyAddPath,
-                        RouterIds.createPeerId(removedPath.getRouteId()),
-                        entryDependencies.getLocalTablesKey(), entryDependencies, tx);
-            });
-            this.removedPaths = null;
+    public final Optional<StaleBestPathRoute<C, S, R, I>> removeStalePaths(final RIBSupport<C, S, R, I> ribSupport,
+            final String routeKey) {
+        if ((this.bestPathRemoved == null || this.bestPathRemoved.isEmpty()) && this.removedPathsId == null) {
+            return Optional.empty();
         }
-
-        if (this.newBestPathToBeAdvertised != null) {
-            this.newBestPathToBeAdvertised.forEach(path -> addPathToDataStore(entryDependencies, path,
-                    isFirstBestPath(this.bestPath.indexOf(path)), routeKey, tx));
-            this.newBestPathToBeAdvertised = null;
+        List<Long> stalePaths = Collections.emptyList();
+        if (this.bestPathRemoved != null && !this.bestPathRemoved.isEmpty()) {
+            stalePaths = this.bestPathRemoved.stream().map(AddPathBestPath::getPathId).collect(Collectors.toList());
+            this.bestPathRemoved = null;
         }
+        final StaleBestPathRoute<C, S, R, I> stale = new StaleBestPathRoute<>(ribSupport, routeKey, stalePaths,
+                this.removedPathsId, this.isNonAddPathBestPathNew);
+        this.removedPathsId = null;
+        return Optional.of(stale);
     }
 
     @Override
-    public void initializeBestPaths(final RouteEntryDependenciesContainer routeEntryDep,
-            final RouteEntryInfo entryInfo, final WriteTransaction tx) {
-        if (this.bestPath != null) {
-            final Peer toPeer = entryInfo.getToPeer();
-            final TablesKey localTk = routeEntryDep.getLocalTablesKey();
-            final boolean destPeerSupAddPath = toPeer.supportsAddPathSupported(localTk);
-            for (final AddPathBestPath path : this.bestPath) {
-                if (!filterRoutes(path.getPeerId(), toPeer, localTk)) {
-                    continue;
-                }
-                final String routeKey = entryInfo.getRouteKey();
-                final RIBSupport ribSupport = routeEntryDep.getRibSupport();
-                final BGPRouteEntryExportParameters baseExp = new BGPRouteEntryExportParametersImpl(
-                        this.peerTracker.getPeer(path.getPeerId()), toPeer);
-                final Optional<Attributes> effAttrib = routeEntryDep.getRoutingPolicies()
-                        .applyExportPolicies(baseExp, path.getAttributes(), routeEntryDep.getAfiSafType());
-                if (effAttrib.isPresent()) {
-                    Identifier routeIdentifier = ribSupport.createRouteListKey(destPeerSupAddPath
-                            ? path.getPathId() : NON_PATH_ID_VALUE, routeKey);
-                    final Route route = createRoute(ribSupport, routeKey, destPeerSupAddPath
-                            ? path.getPathId() : NON_PATH_ID_VALUE, path);
-                    InstanceIdentifier ribOutIId
-                            = ribSupport.createRouteIdentifier(toPeer.getRibOutIId(localTk), routeIdentifier);
-
-                    LOG.debug("Write route {} to peer AdjRibsOut {}", route, toPeer.getPeerId());
-                    tx.put(LogicalDatastoreType.OPERATIONAL, ribOutIId, route);
-                    tx.put(LogicalDatastoreType.OPERATIONAL, ribOutIId.child(Attributes.class), effAttrib.get());
-                }
-            }
+    public final List<AdvertizedRoute<C, S, R, I>> newBestPaths(final RIBSupport<C, S, R, I> ribSupport,
+            final String routeKey) {
+        if (this.newBestPathToBeAdvertised == null || this.newBestPathToBeAdvertised.isEmpty()) {
+            return Collections.emptyList();
         }
+        final List<AdvertizedRoute<C, S, R, I>> advertized = new ArrayList<>();
+        for (final AddPathBestPath path : this.newBestPathToBeAdvertised) {
+            final boolean isFirstBestPath = isFirstBestPath(this.bestPath.indexOf(path));
+            final R routeAddPath = createRoute(ribSupport, routeKey, path.getPathId(), path);
+            final AdvertizedRoute<C, S, R, I> adv = new AdvertizedRoute<>(ribSupport, isFirstBestPath,
+                    routeAddPath, path.getAttributes(), path.getPeerId());
+            advertized.add(adv);
+        }
+        this.newBestPathToBeAdvertised = null;
+        return advertized;
     }
 
-    private void addPathToDataStore(
-            final RouteEntryDependenciesContainer entryDep,
-            final AddPathBestPath path,
-            final boolean isFirstBestPath,
-            final String routeKey,
-            final WriteTransaction tx) {
-        final RIBSupport ribSup = entryDep.getRibSupport();
-        final Identifier routeIdAddPath = ribSup.createRouteListKey(path.getPathId(), routeKey);
-        final Identifier routeIdAddNonPath = ribSup.createRouteListKey(NON_PATH_ID_VALUE, routeKey);
-        final Route routeAddPath = createRoute(ribSup, routeKey, path.getPathId(), path);
-        final Route routeNonAddPath = createRoute(ribSup, routeKey, NON_PATH_ID_VALUE, path);
-
-        final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget = entryDep.getLocRibTableTarget();
-        final InstanceIdentifier routeTarget = ribSup.createRouteIdentifier(locRibTarget, routeIdAddPath);
-        LOG.debug("Write route to LocRib {}", routeAddPath);
-        tx.put(LogicalDatastoreType.OPERATIONAL, routeTarget, routeAddPath);
-
-        fillAdjRibsOut(isFirstBestPath, path.getAttributes(), routeNonAddPath, routeAddPath, routeIdAddNonPath,
-            routeIdAddPath, path.getPeerId(), entryDep.getLocalTablesKey(), entryDep, tx);
-    }
-
-    @SuppressWarnings("unchecked")
-    private void fillAdjRibsOut(
-            final boolean isFirstBestPath,
-            final Attributes attributes,
-            final Route routeNonAddPath,
-            final Route routeAddPath,
-            final Identifier routeKeyAddNonPath,
-            final Identifier routeKeyAddPath,
-            final PeerId fromPeerId,
-            final TablesKey localTK,
-            final RouteEntryDependenciesContainer routeEntryDep,
-            final WriteTransaction tx) {
-        /*
-         * We need to keep track of routers and populate adj-ribs-out, too. If we do not, we need to
-         * expose from which client a particular route was learned from in the local RIB, and have
-         * the listener perform filtering.
-         *
-         * We walk the policy set in order to minimize the amount of work we do for multiple peers:
-         * if we have two eBGP peers, for example, there is no reason why we should perform the translation
-         * multiple times.
-         */
-        final RIBSupport ribSupport = routeEntryDep.getRibSupport();
-        for (final Peer toPeer : this.peerTracker.getPeers()) {
-            if (!filterRoutes(fromPeerId, toPeer, localTK)) {
-                continue;
-            }
-            final boolean destPeerSupAddPath = toPeer.supportsAddPathSupported(localTK);
-
-            if (toPeer.getPeerId().getValue().equals("bgp://127.0.0.5")) {
-                LOG.debug("Write route {} to peer AdjRibsOut {}", toPeer.getPeerId());
-            }
-            if (peersSupportsAddPathOrIsFirstBestPath(destPeerSupAddPath, isFirstBestPath)) {
-
-                Optional<Attributes> effAttrib = Optional.empty();
-                final Peer fromPeer = this.peerTracker.getPeer(fromPeerId);
-
-                if (fromPeer != null && attributes != null) {
-                    final BGPRouteEntryExportParameters baseExp
-                            = new BGPRouteEntryExportParametersImpl(fromPeer, toPeer);
-                    effAttrib = routeEntryDep.getRoutingPolicies()
-                            .applyExportPolicies(baseExp, attributes, routeEntryDep.getAfiSafType());
-                }
-                Route newRoute = null;
-                InstanceIdentifier ribOutRoute = null;
-                if (destPeerSupAddPath) {
-                    newRoute = routeAddPath;
-                    ribOutRoute
-                            = ribSupport.createRouteIdentifier(toPeer.getRibOutIId(localTK), routeKeyAddPath);
-                } else if (!this.oldNonAddPathBestPathTheSame) {
-                    ribOutRoute
-                            = ribSupport.createRouteIdentifier(toPeer.getRibOutIId(localTK), routeKeyAddNonPath);
-                    newRoute = routeNonAddPath;
-                }
-
-                if (effAttrib.isPresent() && newRoute != null) {
-                    LOG.debug("Write route {} to peer AdjRibsOut {}", newRoute, toPeer.getPeerId());
-                    tx.put(LogicalDatastoreType.OPERATIONAL, ribOutRoute, newRoute);
-                    tx.put(LogicalDatastoreType.OPERATIONAL, ribOutRoute.child(Attributes.class), effAttrib.get());
-                } else if (ribOutRoute != null) {
-                    LOG.trace("Removing {} from transaction for peer {}", ribOutRoute, toPeer.getPeerId());
-                    tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutRoute);
-                }
-            }
+    @Override
+    public final List<ActualBestPathRoutes<C, S, R, I>> actualBestPaths(final RIBSupport<C, S, R, I> ribSupport,
+            final RouteEntryInfo entryInfo) {
+        if (this.bestPath == null || this.bestPath.isEmpty()) {
+            return Collections.emptyList();
+        }
+        final List<ActualBestPathRoutes<C, S, R, I>> preexistentRoutes = new ArrayList<>();
+        for (final AddPathBestPath path : this.bestPath) {
+            final R route = createRoute(ribSupport, entryInfo.getRouteKey(), path.getPathId(), path);
+            final ActualBestPathRoutes<C, S, R, I> adv = new ActualBestPathRoutes<>(ribSupport, route, path.getPeerId(),
+                    path.getAttributes());
+            preexistentRoutes.add(adv);
         }
+        return preexistentRoutes;
     }
 
-
-    protected final OffsetMap getOffsets() {
+    private OffsetMap getOffsets() {
         return this.offsets;
     }
 
@@ -292,7 +161,7 @@ public abstract class AddPathAbstractRouteEntry extends AbstractRouteEntry<AddPa
 
     private void selectBest(final RouteKey key, final AddPathSelector selector) {
         final int offset = this.offsets.offsetOf(key);
-        final Route route = this.offsets.getValue(this.values, offset);
+        final R route = this.offsets.getValue(this.values, offset);
         final long pathId = this.offsets.getValue(this.pathsId, offset);
         LOG.trace("Processing router key {} route {}", key, route);
         selector.processPath(route.getAttributes(), key, offset, pathId);
@@ -319,13 +188,8 @@ public abstract class AddPathAbstractRouteEntry extends AbstractRouteEntry<AddPa
         return bestPathPosition == 0;
     }
 
-    private static boolean peersSupportsAddPathOrIsFirstBestPath(final boolean peerSupportsAddPath,
-            final boolean isFirstBestPath) {
-        return !(!peerSupportsAddPath && !isFirstBestPath);
-    }
-
     protected boolean isBestPathNew(final List<AddPathBestPath> newBestPathList) {
-        this.oldNonAddPathBestPathTheSame = isNonAddPathBestPathTheSame(newBestPathList);
+        this.isNonAddPathBestPathNew = !isNonAddPathBestPathTheSame(newBestPathList);
         filterRemovedPaths(newBestPathList);
         if (this.bestPathRemoved != null && !this.bestPathRemoved.isEmpty()
                 || newBestPathList != null
index 3aecc5b59a97cbe47a6a9e21bd709a1e2d774a0b..496e9b6210af6e8b81f9d62a7d0e10f956726f86 100644 (file)
@@ -8,21 +8,27 @@
 
 package org.opendaylight.protocol.bgp.mode.impl.add.all.paths;
 
-import static java.util.Objects.requireNonNull;
-
 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
+import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
-public class AllPathSelection implements PathSelectionMode {
-    private final BGPPeerTracker peerTracker;
+public final class AllPathSelection implements PathSelectionMode {
 
-    public AllPathSelection(final BGPPeerTracker peerTracker) {
-        this.peerTracker = requireNonNull(peerTracker);
+    public AllPathSelection() {
     }
 
     @Override
-    public org.opendaylight.protocol.bgp.mode.api.RouteEntry createRouteEntry() {
-        return new AllPathsRouteEntry(this.peerTracker);
+    public <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>
+            > RouteEntry<C,S,R,I> createRouteEntry() {
+        return new AllPathsRouteEntry<>();
     }
 
     @Override
index d8e08537872c8dcbb76370b602c088b7e160602f..ab2f96f6aa31f30dd50f7acf6d04c7e073e7584c 100644 (file)
@@ -18,12 +18,19 @@ import org.opendaylight.protocol.bgp.mode.impl.BestPathStateImpl;
 import org.opendaylight.protocol.bgp.mode.impl.add.AddPathAbstractRouteEntry;
 import org.opendaylight.protocol.bgp.mode.impl.add.AddPathBestPath;
 import org.opendaylight.protocol.bgp.mode.impl.add.RouteKey;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
-final class AllPathsRouteEntry extends AddPathAbstractRouteEntry {
-    AllPathsRouteEntry(final BGPPeerTracker peerTracker) {
-        super(peerTracker);
+final class AllPathsRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
+        extends AddPathAbstractRouteEntry<C, S, R, I> {
+    AllPathsRouteEntry() {
     }
 
     @Override
index 20c3c814c5c56c1e370f8c88a1684de45db62afc..6f2245a8f98fa943a5c12bad0f85e1017ae1cadf 100644 (file)
@@ -8,19 +8,22 @@
 
 package org.opendaylight.protocol.bgp.mode.impl.add.n.paths;
 
-import static java.util.Objects.requireNonNull;
-
 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
 import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
 public final class AddPathBestNPathSelection implements PathSelectionMode {
     private final long npaths;
-    private final BGPPeerTracker peerTracker;
 
-    public AddPathBestNPathSelection(final long npaths, final BGPPeerTracker peerTracker) {
+    public AddPathBestNPathSelection(final long npaths) {
         this.npaths = npaths;
-        this.peerTracker = requireNonNull(peerTracker);
     }
 
     @Override
@@ -29,7 +32,9 @@ public final class AddPathBestNPathSelection implements PathSelectionMode {
     }
 
     @Override
-    public RouteEntry createRouteEntry() {
-        return new NPathsRouteEntry(this.npaths, this.peerTracker);
+    public <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>
+            > RouteEntry<C,S,R,I> createRouteEntry() {
+        return new NPathsRouteEntry<>(this.npaths);
     }
 }
\ No newline at end of file
index acea9c66aaadc3fe1793bf203739b2f6e81986b4..ce8ab52e58ad13f1b85a518a8153be03e09e16a6 100644 (file)
@@ -14,13 +14,21 @@ import java.util.List;
 import org.opendaylight.protocol.bgp.mode.impl.add.AddPathAbstractRouteEntry;
 import org.opendaylight.protocol.bgp.mode.impl.add.AddPathBestPath;
 import org.opendaylight.protocol.bgp.mode.impl.add.RouteKey;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
-final class NPathsRouteEntry extends AddPathAbstractRouteEntry {
+final class NPathsRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
+        extends AddPathAbstractRouteEntry<C, S, R, I> {
     private final long npaths;
 
-    NPathsRouteEntry(final long npaths, final BGPPeerTracker peerTracker) {
-        super(peerTracker);
+    NPathsRouteEntry(final long npaths) {
         this.npaths = npaths;
     }
 
index be7140b64d6e126a9aab899fbd71f23cd934cee6..28ae734e59cdfd974d80c8532da61e8a782cb31e 100644 (file)
@@ -8,21 +8,27 @@
 
 package org.opendaylight.protocol.bgp.mode.impl.base;
 
-import static java.util.Objects.requireNonNull;
-
 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
+import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
 final class BasePathSelection implements PathSelectionMode {
-    private final BGPPeerTracker peerTracker;
 
-    BasePathSelection(final BGPPeerTracker peerTracker) {
-        this.peerTracker = requireNonNull(peerTracker);
+    BasePathSelection() {
     }
 
     @Override
-    public org.opendaylight.protocol.bgp.mode.api.RouteEntry createRouteEntry() {
-        return new BaseRouteEntry(this.peerTracker);
+    public <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>
+            > RouteEntry<C,S,R,I> createRouteEntry() {
+        return new BaseRouteEntry<>();
     }
 
     @Override
index 7f16156ac489ed4477b6c4c0fe1435ca8473e7a2..eef41587aa49b47c09ebe0a2b29610c3be115de8 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.protocol.bgp.mode.impl.base;
 
 import org.opendaylight.protocol.bgp.mode.api.PathSelectionMode;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 
 public final class BasePathSelectionModeFactory {
 
@@ -16,7 +15,7 @@ public final class BasePathSelectionModeFactory {
         throw new UnsupportedOperationException();
     }
 
-    public static PathSelectionMode createBestPathSelectionStrategy(final BGPPeerTracker peerTracker) {
-        return new BasePathSelection(peerTracker);
+    public static PathSelectionMode createBestPathSelectionStrategy() {
+        return new BasePathSelection();
     }
 }
index 95acceb707b29353aa1a79010693c819b76c79c0..b1c35906ddd273bf0d07d99e4bdb9cf34f6b4bbd 100644 (file)
@@ -7,57 +7,56 @@
  */
 package org.opendaylight.protocol.bgp.mode.impl.base;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.primitives.UnsignedInteger;
+import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
-import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.protocol.bgp.mode.impl.BGPRouteEntryExportParametersImpl;
-import org.opendaylight.protocol.bgp.mode.spi.AbstractRouteEntry;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
-import org.opendaylight.protocol.bgp.rib.spi.Peer;
+import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
-import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryDependenciesContainer;
+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.RouteEntryInfo;
-import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
-import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
+import org.opendaylight.protocol.bgp.rib.spi.entry.StaleBestPathRoute;
 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.rib.rev180329.PeerId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
 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.rib.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @NotThreadSafe
-final class BaseRouteEntry extends AbstractRouteEntry<BaseBestPath> {
+final class BaseRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>,
+        S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>,
+        I extends Identifier<R>> implements RouteEntry<C,S,R,I> {
     private static final Logger LOG = LoggerFactory.getLogger(BaseRouteEntry.class);
+    private static final Route[] EMPTY_VALUES = new Route[0];
+
     private OffsetMap offsets = OffsetMap.EMPTY;
-    private Route[] values = EMPTY_VALUES;
+    private R[] values = (R[]) EMPTY_VALUES;
     private BaseBestPath bestPath;
     private BaseBestPath removedBestPath;
 
-    BaseRouteEntry(final BGPPeerTracker peerTracker) {
-        super(peerTracker);
+    BaseRouteEntry() {
     }
 
     @Override
-    public  boolean removeRoute(final UnsignedInteger routerId, final long remotePathId) {
+    public boolean removeRoute(final UnsignedInteger routerId, final long remotePathId) {
         final int offset = this.offsets.offsetOf(routerId);
-        this.values = this.offsets.removeValue(this.values, offset, EMPTY_VALUES);
+        this.values = this.offsets.removeValue(this.values, offset, (R[]) EMPTY_VALUES);
         this.offsets = this.offsets.without(routerId);
         return this.offsets.isEmpty();
     }
 
-    @Override
-    public Route createRoute(final RIBSupport ribSup, String routeKey, final long pathId,
+    private  R createRoute(final RIBSupport<C, S, R, I> ribSup, String routeKey, final long pathId,
             final BaseBestPath path) {
-        final Route route = this.offsets.getValue(this.values, this.offsets.offsetOf(path.getRouterId()));
+        final R route = this.offsets.getValue(this.values, this.offsets.offsetOf(path.getRouterId()));
         return ribSup.createRoute(route, routeKey, pathId, path.getAttributes());
     }
 
@@ -90,7 +89,7 @@ final class BaseRouteEntry extends AbstractRouteEntry<BaseBestPath> {
     }
 
     @Override
-    public int addRoute(final UnsignedInteger routerId, final long remotePathId, final Route route) {
+    public int addRoute(final UnsignedInteger routerId, final long remotePathId, final R route) {
         int offset = this.offsets.offsetOf(routerId);
         if (offset < 0) {
             final OffsetMap newOffsets = this.offsets.with(routerId);
@@ -106,122 +105,37 @@ final class BaseRouteEntry extends AbstractRouteEntry<BaseBestPath> {
     }
 
     @Override
-    public void updateBestPaths(
-            final RouteEntryDependenciesContainer entryDependencies,
-            final String routeKey,
-            final WriteTransaction tx) {
-        if (this.removedBestPath != null) {
-            removePathFromDataStore(entryDependencies, routeKey, tx);
-            this.removedBestPath = null;
-        }
-        if (this.bestPath != null) {
-            addPathToDataStore(entryDependencies, routeKey, tx);
+    public Optional<StaleBestPathRoute<C, S, R, I>> removeStalePaths(final RIBSupport<C, S, R, I> ribSupport,
+            final String routeKey) {
+        if (this.removedBestPath == null) {
+            return Optional.empty();
         }
+        final StaleBestPathRoute<C, S, R, I> stale = new StaleBestPathRoute<>(ribSupport, routeKey);
+        this.removedBestPath = null;
+        return Optional.of(stale);
     }
 
     @Override
-    @SuppressWarnings("unchecked")
-    public void initializeBestPaths(
-            final RouteEntryDependenciesContainer entryDep,
-            final RouteEntryInfo entryInfo,
-            final WriteTransaction tx) {
+    public List<AdvertizedRoute<C, S, R, I>> newBestPaths(final RIBSupport<C, S, R, I> ribSupport,
+            final String routeKey) {
         if (this.bestPath == null) {
-            return;
-        }
-        final TablesKey localTK = entryDep.getLocalTablesKey();
-        final Peer toPeer = entryInfo.getToPeer();
-        if (!filterRoutes(this.bestPath.getPeerId(), toPeer, localTK)) {
-            return;
-        }
-        final RIBSupport ribSupport = entryDep.getRibSupport();
-        Identifier routeIdentifier = ribSupport.createRouteListKey(this.bestPath.getPathId(), entryInfo.getRouteKey());
-        final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(
-                this.peerTracker.getPeer(this.bestPath.getPeerId()), toPeer);
-        final Optional<Attributes> effAttrib = entryDep.getRoutingPolicies()
-                .applyExportPolicies(routeEntry, this.bestPath.getAttributes(), entryDep.getAfiSafType());
-        if (effAttrib.isPresent()) {
-            final Route route = createRoute(ribSupport,
-                    entryInfo.getRouteKey(), this.bestPath.getPathId(), this.bestPath);
-            InstanceIdentifier ribOutIId = ribSupport.createRouteIdentifier(toPeer.getRibOutIId(localTK),
-                    routeIdentifier);
-            LOG.debug("Write route {} to peer AdjRibsOut {}", route, toPeer.getPeerId());
-            tx.put(LogicalDatastoreType.OPERATIONAL, ribOutIId, route);
-            tx.put(LogicalDatastoreType.OPERATIONAL, ribOutIId.child(Attributes.class), effAttrib.get());
+            return Collections.emptyList();
         }
-    }
-
-    @SuppressWarnings("unchecked")
-    private void removePathFromDataStore(final RouteEntryDependenciesContainer entryDep,
-            final String routeKey, final WriteTransaction tx) {
-        LOG.trace("Best Path removed {}", this.removedBestPath);
-        final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget = entryDep.getLocRibTableTarget();
-        final RIBSupport ribSup = entryDep.getRibSupport();
-        Identifier routeIdentifier = ribSup.createRouteListKey(this.removedBestPath.getPathId(), routeKey);
-        final InstanceIdentifier routeTarget = ribSup.createRouteIdentifier(locRibTarget, routeIdentifier);
-        LOG.debug("Delete route from LocRib {}", routeTarget);
-        tx.delete(LogicalDatastoreType.OPERATIONAL, routeTarget);
-        fillAdjRibsOut(null, null, routeIdentifier, this.removedBestPath.getPeerId(),
-                entryDep, tx);
-    }
-
-    @SuppressWarnings("unchecked")
-    private void addPathToDataStore(final RouteEntryDependenciesContainer entryDep,
-            final String routeKey, final WriteTransaction tx) {
-        final RIBSupport ribSup = entryDep.getRibSupport();
-        final Route route = createRoute(ribSup, routeKey, this.bestPath.getPathId(), this.bestPath);
+        final R route = createRoute(ribSupport, routeKey, this.bestPath.getPathId(), this.bestPath);
+        final AdvertizedRoute<C, S, R, I> adv = new AdvertizedRoute<>(ribSupport, route, this.bestPath.getAttributes(),
+                this.bestPath.getPeerId());
         LOG.trace("Selected best route {}", route);
-
-        Identifier routeIdentifier = ribSup.createRouteListKey(this.bestPath.getPathId(), routeKey);
-        final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget = entryDep.getLocRibTableTarget();
-        final InstanceIdentifier routeTarget = ribSup.createRouteIdentifier(locRibTarget, routeIdentifier);
-        LOG.debug("Write route to LocRib {}", route);
-        tx.put(LogicalDatastoreType.OPERATIONAL, routeTarget, route);
-        fillAdjRibsOut(this.bestPath.getAttributes(), route, routeIdentifier, this.bestPath.getPeerId(),
-                entryDep, tx);
+        return Collections.singletonList(adv);
     }
 
-    @VisibleForTesting
-    @SuppressWarnings("unchecked")
-    private void fillAdjRibsOut(
-            @Nullable final Attributes attributes,
-            @Nullable final Route route,
-            final Identifier routeKey,
-            final PeerId fromPeerId,
-            final RouteEntryDependenciesContainer routeEntryDep,
-            final WriteTransaction tx) {
-        /*
-         * We need to keep track of routers and populate adj-ribs-out, too. If we do not, we need to
-         * expose from which client a particular route was learned from in the local RIB, and have
-         * the listener perform filtering.
-         *
-         * We walk the policy set in order to minimize the amount of work we do for multiple peers:
-         * if we have two eBGP peers, for example, there is no reason why we should perform the translation
-         * multiple times.
-         */
-        final TablesKey localTK = routeEntryDep.getLocalTablesKey();
-        final BGPRibRoutingPolicy routingPolicies = routeEntryDep.getRoutingPolicies();
-        final RIBSupport ribSupport = routeEntryDep.getRibSupport();
-        for (final Peer toPeer : this.peerTracker.getPeers()) {
-            if (!filterRoutes(fromPeerId, toPeer, localTK)) {
-                continue;
-            }
-            Optional<Attributes> effAttr = Optional.empty();
-            final Peer fromPeer = this.peerTracker.getPeer(fromPeerId);
-            if (fromPeer != null && attributes != null) {
-                final BGPRouteEntryExportParameters routeEntry
-                        = new BGPRouteEntryExportParametersImpl(fromPeer, toPeer);
-                effAttr = routingPolicies.applyExportPolicies(routeEntry, attributes, routeEntryDep.getAfiSafType());
-            }
-            final InstanceIdentifier ribOutTarget
-                    = ribSupport.createRouteIdentifier(toPeer.getRibOutIId(localTK), routeKey);
-            if (effAttr.isPresent() && route != null) {
-                LOG.debug("Write route {} to peer AdjRibsOut {}", route, toPeer.getPeerId());
-                tx.put(LogicalDatastoreType.OPERATIONAL, ribOutTarget, route);
-                tx.put(LogicalDatastoreType.OPERATIONAL, ribOutTarget.child(Attributes.class), effAttr.get());
-            } else {
-                LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, toPeer.getPeerId());
-                tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
-            }
+    @Override
+    public List<ActualBestPathRoutes<C, S, R, I>> actualBestPaths(final RIBSupport<C, S, R, I> ribSupport,
+            final RouteEntryInfo entryInfo) {
+        if (this.bestPath == null) {
+            return Collections.emptyList();
         }
+        final R route = createRoute(ribSupport, entryInfo.getRouteKey(), this.bestPath.getPathId(), this.bestPath);
+        return Collections.singletonList(new ActualBestPathRoutes<>(ribSupport, route, this.bestPath.getPeerId(),
+                this.bestPath.getAttributes()));
     }
 }
\ No newline at end of file
diff --git a/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/spi/AbstractRouteEntry.java b/bgp/path-selection-mode/src/main/java/org/opendaylight/protocol/bgp/mode/spi/AbstractRouteEntry.java
deleted file mode 100644 (file)
index 3704386..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.protocol.bgp.mode.spi;
-
-import static java.util.Objects.requireNonNull;
-
-import javax.annotation.Nonnull;
-import org.opendaylight.protocol.bgp.mode.api.BestPath;
-import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
-import org.opendaylight.protocol.bgp.rib.spi.Peer;
-import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId;
-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.Route;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
-
-public abstract class AbstractRouteEntry<T extends BestPath> implements RouteEntry {
-    protected static final Route[] EMPTY_VALUES = new Route[0];
-    protected final BGPPeerTracker peerTracker;
-
-    public AbstractRouteEntry(final BGPPeerTracker peerTracker) {
-        this.peerTracker = requireNonNull(peerTracker);
-    }
-
-    /**
-     * Create new Route with route jey created from passed parameters.
-     */
-    public abstract Route createRoute(@Nonnull RIBSupport ribSup, @Nonnull String routeKey, long pathId, T path);
-
-    /**
-     * Returns true if route can be send.
-     */
-    protected boolean filterRoutes(final PeerId fromPeer, final Peer toPeer, final TablesKey localTK) {
-        return !(toPeer == null
-                || !toPeer.supportsTable(localTK)
-                || PeerRole.Internal.equals(toPeer.getRole()))
-                && !fromPeer.equals(toPeer.getPeerId());
-    }
-}
index ba2f53af7173df4b8fc47fb5562c7da08202bdae..d3b4bddde65c761b3c3810c10cbbcb221f15b2f1 100644 (file)
@@ -7,48 +7,80 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import static org.opendaylight.protocol.bgp.parser.spi.PathIdUtil.NON_PATH_ID_VALUE;
+
 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.List;
+import java.util.Optional;
 import java.util.Set;
-import javax.annotation.Nonnull;
+import java.util.concurrent.ExecutionException;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.protocol.bgp.mode.impl.BGPRouteEntryExportParametersImpl;
+import org.opendaylight.protocol.bgp.rib.impl.spi.PeerTransactionChain;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.bgp.rib.impl.state.BGPPeerStateImpl;
+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.ActualBestPathRoutes;
+import org.opendaylight.protocol.bgp.rib.spi.entry.AdvertizedRoute;
+import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryDependenciesContainer;
+import org.opendaylight.protocol.bgp.rib.spi.entry.StaleBestPathRoute;
+import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
+import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryImportParameters;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPAfiSafiState;
 import org.opendaylight.protocol.bgp.rib.spi.state.BGPErrorHandlingState;
 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.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId;
 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.Route;
+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.rib.tables.Routes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.ClusterIdentifier;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImportParameters, TransactionChainListener,
-        Peer {
+        Peer, PeerTransactionChain {
     private static final Logger LOG = LoggerFactory.getLogger(AbstractPeer.class);
     protected final RIB rib;
     final String name;
     final PeerRole peerRole;
     private final ClusterIdentifier clusterId;
     private final AsNumber localAs;
+    @GuardedBy("this")
+    private DOMTransactionChain domChain;
+    @GuardedBy("this")
+    BindingTransactionChain bindingChain;
     byte[] rawIdentifier;
     @GuardedBy("this")
     PeerId peerId;
+    private FluentFuture<? extends CommitInfo> submitted;
 
     AbstractPeer(
             final RIB rib,
@@ -66,6 +98,7 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
         this.clusterId = clusterId;
         this.localAs = localAs;
         this.rib = rib;
+        this.domChain = this.rib.createPeerDOMChain(this);
     }
 
     AbstractPeer(
@@ -79,28 +112,26 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
                 rib.getLocalTablesKeys(), afiSafisGracefulAdvertized);
     }
 
-    final synchronized FluentFuture<? extends CommitInfo> removePeer(
-            @Nonnull final DOMTransactionChain chain,
-            @Nullable final YangInstanceIdentifier peerPath) {
-        if (peerPath != null) {
-            LOG.info("AdjRibInWriter closed per Peer {} removed", peerPath);
-            final DOMDataWriteTransaction tx = chain.newWriteOnlyTransaction();
-            tx.delete(LogicalDatastoreType.OPERATIONAL, peerPath);
-            final FluentFuture<? extends CommitInfo> future = tx.commit();
-            future.addCallback(new FutureCallback<CommitInfo>() {
-                @Override
-                public void onSuccess(final CommitInfo result) {
-                    LOG.debug("Peer {} removed", peerPath);
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    LOG.error("Failed to remove Peer {}", peerPath, t);
-                }
-            }, MoreExecutors.directExecutor());
-            return future;
+    final synchronized FluentFuture<? extends CommitInfo> removePeer(@Nullable final YangInstanceIdentifier peerPath) {
+        if (peerPath == null) {
+            return CommitInfo.emptyFluentFuture();
         }
-        return CommitInfo.emptyFluentFuture();
+        LOG.info("Closed per Peer {} removed", peerPath);
+        final DOMDataWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
+        tx.delete(LogicalDatastoreType.OPERATIONAL, peerPath);
+        final FluentFuture<? extends CommitInfo> future = tx.commit();
+        future.addCallback(new FutureCallback<CommitInfo>() {
+            @Override
+            public void onSuccess(final CommitInfo result) {
+                LOG.debug("Peer {} removed", peerPath);
+            }
+
+            @Override
+            public void onFailure(final Throwable throwable) {
+                LOG.error("Failed to remove Peer {}", peerPath, throwable);
+            }
+        }, MoreExecutors.directExecutor());
+        return future;
     }
 
     synchronized YangInstanceIdentifier createPeerPath() {
@@ -172,4 +203,213 @@ abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImp
     public final AsNumber getLocalAs() {
         return this.localAs;
     }
+
+    @Override
+    public synchronized DOMTransactionChain getDomChain() {
+        return this.domChain;
+    }
+
+    @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,
+            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 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) {
+            final PeerId fromPeerId = initializingRoute.getFromPeerId();
+            final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
+            if (!filterRoutes(fromPeerId, ribSupport.getTablesKey())) {
+                continue;
+            }
+            final R route = initializingRoute.getRoute();
+
+            final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer, this);
+            final Optional<Attributes> effAttrib = entryDep.getRoutingPolicies()
+                    .applyExportPolicies(routeEntry, initializingRoute.getAttributes(), entryDep.getAfiSafType());
+            if (effAttrib.isPresent()) {
+
+                final InstanceIdentifier<R> ribOut;
+                final R newRoute;
+                if (!addPathSupported) {
+                    ribOut = ribSupport.createRouteIdentifier(getRibOutIId(tk),
+                            initializingRoute.getNonAddPathRouteKeyIdentifier());
+                    newRoute = ribSupport.createRoute(route, route.getRouteKey(),
+                            NON_PATH_ID_VALUE, effAttrib.get());
+                } else {
+                    ribOut = ribSupport.createRouteIdentifier(getRibOutIId(tk),
+                            initializingRoute.getAddPathRouteKeyIdentifier());
+                    newRoute = ribSupport.createRoute(route, route.getRouteKey(),
+                            route.getPathId().getValue(), effAttrib.get());
+                }
+
+                LOG.debug("Write advRoute {} to peer AdjRibsOut {}", initializingRoute, getPeerId());
+                tx.put(LogicalDatastoreType.OPERATIONAL, ribOut, newRoute);
+            }
+        }
+
+        final FluentFuture<? extends CommitInfo> future = tx.commit();
+        this.submitted = future;
+        future.addCallback(new FutureCallback<CommitInfo>() {
+            @Override
+            public void onSuccess(final CommitInfo result) {
+                LOG.trace("Successful update commit");
+            }
+
+            @Override
+            public void onFailure(final Throwable trw) {
+                LOG.error("Failed update commit", trw);
+            }
+        }, MoreExecutors.directExecutor());
+
+    }
+
+    /**
+     * Returns true if route can be send.
+     */
+    private boolean filterRoutes(final PeerId fromPeer, final TablesKey localTK) {
+        return supportsTable(localTK) && !fromPeer.equals(getPeerId());
+    }
+
+    @Override
+    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 refreshRibOut(final RouteEntryDependenciesContainer entryDep,
+            final List<StaleBestPathRoute<C, S, R, I>> staleRoutes, List<AdvertizedRoute<C, S, R, I>> newRoutes) {
+        if (this.bindingChain == null) {
+            LOG.debug("Session closed, skip changes to peer AdjRibsOut {}", getPeerId());
+            return;
+        }
+        final WriteTransaction tx = this.bindingChain.newWriteOnlyTransaction();
+        final RIBSupport<C, S, R, I> ribSupport = entryDep.getRIBSupport();
+        deleteRouteRibOut(ribSupport, staleRoutes, tx);
+        installRouteRibOut(entryDep, newRoutes, tx);
+
+        final FluentFuture<? extends CommitInfo> future = tx.commit();
+        this.submitted = future;
+        future.addCallback(new FutureCallback<CommitInfo>() {
+            @Override
+            public void onSuccess(final CommitInfo result) {
+                LOG.trace("Successful update commit");
+            }
+
+            @Override
+            public void onFailure(final Throwable trw) {
+                LOG.error("Failed update commit", trw);
+            }
+        }, MoreExecutors.directExecutor());
+    }
+
+    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) {
+        final TablesKey tk = entryDep.getRIBSupport().getTablesKey();
+        final BGPPeerTracker peerTracker = entryDep.getPeerTracker();
+        final RIBSupport<C,S,R,I> ribSupport = entryDep.getRIBSupport();
+        final BGPRibRoutingPolicy routingPolicies = entryDep.getRoutingPolicies();
+        final boolean addPathSupported = supportsAddPathSupported(tk);
+
+        for (final AdvertizedRoute<C,S,R,I> advRoute:routes) {
+            final PeerId fromPeerId = advRoute.getFromPeerId();
+            if (!filterRoutes(fromPeerId, tk) || (!advRoute.isFirstBestPath() && !addPathSupported)) {
+                continue;
+            }
+            final R route = advRoute.getRoute();
+            final Attributes attributes = advRoute.getAttributes();
+            Optional<Attributes> effAttr = Optional.empty();
+            final Peer fromPeer = peerTracker.getPeer(fromPeerId);
+            if (fromPeer != null && attributes != null) {
+                final BGPRouteEntryExportParameters routeEntry
+                        = new BGPRouteEntryExportParametersImpl(fromPeer, this);
+                effAttr = routingPolicies.applyExportPolicies(routeEntry, attributes, entryDep.getAfiSafType());
+            }
+
+            if (effAttr.isPresent()) {
+                final InstanceIdentifier<R> ribOut;
+                final R newRoute;
+                if (!addPathSupported) {
+                    ribOut = ribSupport.createRouteIdentifier(getRibOutIId(tk),
+                            advRoute.getNonAddPathRouteKeyIdentifier());
+                    newRoute = ribSupport.createRoute(route, route.getRouteKey(),
+                            NON_PATH_ID_VALUE, effAttr.get());
+                } else {
+                    ribOut = ribSupport.createRouteIdentifier(getRibOutIId(tk),
+                            advRoute.getAddPathRouteKeyIdentifier());
+                    newRoute = ribSupport.createRoute(route, route.getRouteKey(),
+                            route.getPathId().getValue(), effAttr.get());
+                }
+
+                LOG.debug("Write advRoute {} to peer AdjRibsOut {}", advRoute, getPeerId());
+                tx.put(LogicalDatastoreType.OPERATIONAL, ribOut, newRoute);
+            }
+        }
+    }
+
+    private 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 deleteRouteRibOut(
+            final RIBSupport<C, S, R, I> ribSupport,
+            final List<StaleBestPathRoute<C, S, R, I>> staleRoutesIid,
+            final WriteTransaction tx) {
+        final TablesKey tk = ribSupport.getTablesKey();
+        final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
+        final boolean addPathSupported = supportsAddPathSupported(tk);
+        for (final StaleBestPathRoute<C, S, R, I> staleRouteIid : staleRoutesIid) {
+            if (addPathSupported) {
+                List<I> staleRoutesIId = staleRouteIid.getAddPathRouteKeyIdentifiers();
+                for (final I id : staleRoutesIId) {
+                    final InstanceIdentifier<R> ribOutTarget = ribSupport.createRouteIdentifier(tableRibout, id);
+                    LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, getPeerId());
+                    tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
+                }
+            } else {
+                if (!staleRouteIid.isNonAddPathBestPathNew()) {
+                    continue;
+                }
+                final InstanceIdentifier<R> ribOutTarget = ribSupport.createRouteIdentifier(tableRibout,
+                        staleRouteIid.getNonAddPathRouteKeyIdentifier());
+                LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, getPeerId());
+                tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
+            }
+        }
+    }
+
+    final synchronized void releaseBindingChain() {
+        if (this.submitted != null) {
+            try {
+                this.submitted.get();
+            } catch (final InterruptedException | ExecutionException throwable) {
+                LOG.error("Write routes failed", throwable);
+            }
+        }
+        closeBindingChain();
+    }
+
+    private synchronized void closeBindingChain() {
+        if (this.bindingChain != null) {
+            LOG.info("Closing peer chain {}", getPeerId());
+            this.bindingChain.close();
+            this.bindingChain = null;
+        }
+    }
+
+    final synchronized void closeDomChain() {
+        if (this.domChain != null) {
+            LOG.info("Closing DOM peer chain {}", getPeerId());
+            this.domChain.close();
+            this.domChain = null;
+        }
+    }
 }
index a954e99ac6237de85fe8f61ce949f73a8e8bf158..333f28313aff5ae59107b271683cf995434652bc 100644 (file)
@@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Collections;
@@ -19,14 +20,16 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.protocol.bgp.rib.impl.ApplicationPeer.RegisterAppPeerListener;
+import org.opendaylight.protocol.bgp.rib.impl.spi.PeerTransactionChain;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
@@ -97,10 +100,12 @@ final class AdjRibInWriter {
 
     private final Map<TablesKey, TableContext> tables;
     private final YangInstanceIdentifier ribPath;
-    private final DOMTransactionChain chain;
+    private final PeerTransactionChain chain;
     private final PeerRole role;
+    @GuardedBy("this")
+    private FluentFuture<? extends CommitInfo> submitted;
 
-    private AdjRibInWriter(final YangInstanceIdentifier ribPath, final DOMTransactionChain chain, final PeerRole role,
+    private AdjRibInWriter(final YangInstanceIdentifier ribPath, final PeerTransactionChain chain, final PeerRole role,
             final Map<TablesKey, TableContext> tables) {
         this.ribPath = requireNonNull(ribPath);
         this.chain = requireNonNull(chain);
@@ -115,7 +120,7 @@ final class AdjRibInWriter {
      * @param chain               transaction chain  @return A fresh writer instance
      */
     static AdjRibInWriter create(@Nonnull final YangInstanceIdentifier ribId, @Nonnull final PeerRole role,
-            @Nonnull final DOMTransactionChain chain) {
+            @Nonnull final PeerTransactionChain chain) {
         return new AdjRibInWriter(ribId, chain, role, Collections.emptyMap());
     }
 
@@ -141,7 +146,7 @@ final class AdjRibInWriter {
             final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes,
             final Map<TablesKey, SendReceive> addPathTablesType,
             @Nullable final RegisterAppPeerListener registerAppPeerListener) {
-        final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
+        final DOMDataWriteTransaction tx = this.chain.getDomChain().newWriteOnlyTransaction();
 
         createEmptyPeerStructure(newPeerId, peerPath, tx);
         final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(peerPath, registry, tableTypes,
@@ -248,7 +253,7 @@ final class AdjRibInWriter {
     }
 
     void markTableUptodate(final TablesKey tableTypes) {
-        final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
+        final DOMDataWriteTransaction tx = this.chain.getDomChain().newWriteOnlyTransaction();
         final TableContext ctx = this.tables.get(tableTypes);
         tx.merge(LogicalDatastoreType.OPERATIONAL, ctx.getTableId().node(Attributes.QNAME)
                 .node(ATTRIBUTES_UPTODATE_TRUE.getNodeType()), ATTRIBUTES_UPTODATE_TRUE);
@@ -274,10 +279,12 @@ final class AdjRibInWriter {
             return;
         }
 
-        final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
+        final DOMDataWriteTransaction tx = this.chain.getDomChain().newWriteOnlyTransaction();
         ctx.writeRoutes(tx, nlri, attributes);
         LOG.trace("Write routes {}", nlri);
-        tx.commit().addCallback(new FutureCallback<CommitInfo>() {
+        final FluentFuture<? extends CommitInfo> future = tx.commit();
+        this.submitted = future;
+        future.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
                 LOG.trace("Write routes {}, succeed", nlri);
@@ -298,9 +305,11 @@ final class AdjRibInWriter {
             return;
         }
         LOG.trace("Removing routes {}", nlri);
-        final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
+        final DOMDataWriteTransaction tx = this.chain.getDomChain().newWriteOnlyTransaction();
         ctx.removeRoutes(tx, nlri);
-        tx.commit().addCallback(new FutureCallback<CommitInfo>() {
+        final FluentFuture<? extends CommitInfo> future = tx.commit();
+        this.submitted = future;
+        future.addCallback(new FutureCallback<CommitInfo>() {
             @Override
             public void onSuccess(final CommitInfo result) {
                 LOG.trace("Removing routes {}, succeed", nlri);
@@ -312,4 +321,14 @@ final class AdjRibInWriter {
             }
         }, MoreExecutors.directExecutor());
     }
+
+    void releaseChain() {
+        if (this.submitted != null) {
+            try {
+                this.submitted.get();
+            } catch (final InterruptedException | ExecutionException throwable) {
+                LOG.error("Write routes failed", throwable);
+            }
+        }
+    }
 }
index d32058a831ad625764473931627d5300182e8bfc..ad81f3c8c67b70854b16b3279da60da7f9cc7c98 100644 (file)
@@ -28,7 +28,6 @@ import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeList
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
@@ -86,8 +85,6 @@ public class ApplicationPeer extends AbstractPeer implements ClusteredDOMDataTre
     private final InstanceIdentifier<AdjRibOut> peerRibOutIId;
     private final KeyedInstanceIdentifier<Peer, PeerKey> peerIId;
     private final BGPTableTypeRegistryConsumer tableTypeRegistry;
-    private DOMTransactionChain chain;
-    private DOMTransactionChain writerChain;
     private EffectiveRibInWriter effectiveRibInWriter;
     private AdjRibInWriter adjRibInWriter;
     private ListenerRegistration<ApplicationPeer> registration;
@@ -132,18 +129,15 @@ public class ApplicationPeer extends AbstractPeer implements ClusteredDOMDataTre
     public synchronized void instantiateServiceInstance(final DOMDataTreeChangeService dataTreeChangeService,
             final DOMDataTreeIdentifier appPeerDOMId) {
         setActive(true);
-        this.chain = this.rib.createPeerDOMChain(this);
-        this.writerChain = this.rib.createPeerDOMChain(this);
-
         final Set<TablesKey> localTables = this.rib.getLocalTablesKeys();
         localTables.forEach(tablesKey -> this.supportedTables.add(RibSupportUtils.toYangTablesKey(tablesKey)));
         setAdvertizedGracefulRestartTableTypes(Collections.emptyList());
 
-        this.adjRibInWriter = AdjRibInWriter.create(this.rib.getYangRibId(), PeerRole.Internal, this.writerChain);
+        this.adjRibInWriter = AdjRibInWriter.create(this.rib.getYangRibId(), PeerRole.Internal, this);
         final RIBSupportContextRegistry context = this.rib.getRibSupportContext();
         final RegisterAppPeerListener registerAppPeerListener = () -> {
             synchronized (this) {
-                if (this.chain != null) {
+                if (getDomChain() != null) {
                     this.registration = dataTreeChangeService.registerDataTreeChangeListener(appPeerDOMId, this);
                 }
             }
@@ -167,11 +161,11 @@ public class ApplicationPeer extends AbstractPeer implements ClusteredDOMDataTre
      */
     @Override
     public synchronized void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
-        if (this.chain == null) {
+        if (getDomChain() == null) {
             LOG.trace("Skipping data changed called to Application Peer. Change : {}", changes);
             return;
         }
-        final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
+        final DOMDataWriteTransaction tx = getDomChain().newWriteOnlyTransaction();
         LOG.debug("Received data change to ApplicationRib {}", changes);
         for (final DataTreeCandidate tc : changes) {
             LOG.debug("Modification Type {}", tc.getRootNode().getModificationType());
@@ -267,21 +261,15 @@ public class ApplicationPeer extends AbstractPeer implements ClusteredDOMDataTre
             this.registration.close();
             this.registration = null;
         }
+        if (this.adjRibInWriter != null) {
+            this.adjRibInWriter.releaseChain();
+        }
         if (this.effectiveRibInWriter != null) {
             this.effectiveRibInWriter.close();
         }
         final FluentFuture<? extends CommitInfo> future;
-        if (this.chain != null) {
-            future = removePeer(this.chain, this.peerPath);
-            this.chain.close();
-            this.chain = null;
-        } else {
-            future = CommitInfo.emptyFluentFuture();
-        }
-        if (this.writerChain != null) {
-            this.writerChain.close();
-            this.writerChain = null;
-        }
+        future = removePeer(this.peerPath);
+        closeDomChain();
         if (this.trackerRegistration != null) {
             this.trackerRegistration.close();
             this.trackerRegistration = null;
index 1936fd6dc329538c4f2c0cc8f6cbe846d25fc436..98c06d212c51a2794247b60a9f758321f7a05392 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 com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Objects;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
@@ -32,7 +31,6 @@ 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.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.mdsal.common.api.CommitInfo;
@@ -120,8 +118,6 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     @GuardedBy("this")
     private BGPSession session;
     @GuardedBy("this")
-    private final DOMTransactionChain chain;
-    @GuardedBy("this")
     private AdjRibInWriter ribWriter;
     @GuardedBy("this")
     private EffectiveRibInWriter effRibInWriter;
@@ -146,7 +142,6 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         this.tableTypeRegistry = requireNonNull(tableTypeRegistry);
         this.rib = requireNonNull(rib);
         this.rpcRegistry = rpcRegistry;
-        this.chain = rib.createPeerDOMChain(this);
     }
 
     BGPPeer(
@@ -226,14 +221,14 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     }
 
     public synchronized void instantiateServiceInstance() {
-        this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this.chain);
+        this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this);
         setActive(true);
     }
 
     @Override
     public synchronized FluentFuture<? extends CommitInfo> close() {
         final FluentFuture<? extends CommitInfo> future = releaseConnection();
-        this.chain.close();
+        closeDomChain();
         setActive(false);
         return future;
     }
@@ -318,6 +313,7 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     public synchronized void onSessionUp(final BGPSession session) {
         this.session = session;
         this.sessionUp = true;
+        this.bindingChain = this.rib.createPeerChain(this);
         if (this.session instanceof BGPSessionStateProvider) {
             ((BGPSessionStateProvider) this.session).registerMessagesCounter(this);
         }
@@ -394,18 +390,6 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         }
     }
 
-    private synchronized FluentFuture<? extends CommitInfo> cleanup() {
-        // FIXME: BUG-196: support graceful
-        this.adjRibOutListenerSet.values().forEach(AdjRibOutListener::close);
-        this.adjRibOutListenerSet.clear();
-        if (this.effRibInWriter != null) {
-            this.effRibInWriter.close();
-        }
-        this.tables = Collections.emptySet();
-        this.addPathTableMaps = Collections.emptyMap();
-        return removePeer(this.chain, this.peerPath);
-    }
-
     @Override
     public synchronized void onSessionDown(final BGPSession session, final Exception e) {
         if (e.getMessage().equals(BGPSessionImpl.END_OF_INPUT)) {
@@ -424,25 +408,35 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
 
     @Override
     public String toString() {
-        return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
-    }
-
-    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-        toStringHelper.add("name", this.name);
-        toStringHelper.add("tables", this.tables);
-        return toStringHelper;
-    }
+        return MoreObjects.toStringHelper(this)
+                .add("name", this.name)
+                .add("tables", this.tables).toString();
+        }
 
     @Override
     public synchronized FluentFuture<? extends CommitInfo> releaseConnection() {
         LOG.info("Closing session with peer");
         this.sessionUp = false;
-        closeRegistration();
+        this.adjRibOutListenerSet.values().forEach(AdjRibOutListener::close);
+        this.adjRibOutListenerSet.clear();
+        if (this.trackerRegistration != null) {
+            this.trackerRegistration.close();
+            this.trackerRegistration = null;
+        }
         if (this.rpcRegistration != null) {
             this.rpcRegistration.close();
         }
-        final FluentFuture<? extends CommitInfo> future = cleanup();
+        releaseBindingChain();
+
+        this.ribWriter.releaseChain();
+        // FIXME: BUG-196: support graceful
 
+        if (this.effRibInWriter != null) {
+            this.effRibInWriter.close();
+        }
+        this.tables = Collections.emptySet();
+        this.addPathTableMaps = Collections.emptyMap();
+        final FluentFuture<? extends CommitInfo> future = removePeer(this.peerPath);
         if (this.session != null) {
             try {
                 this.session.close();
@@ -455,13 +449,6 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
         return future;
     }
 
-    private synchronized void closeRegistration() {
-        if (this.trackerRegistration != null) {
-            this.trackerRegistration.close();
-            this.trackerRegistration = null;
-        }
-    }
-
     @SuppressFBWarnings("IS2_INCONSISTENT_SYNC")
     @Override
     public SendReceive getSupportedAddPathTables(final TablesKey tableKey) {
@@ -481,13 +468,8 @@ public class BGPPeer extends AbstractPeer implements BGPSessionListener {
     @Override
     public synchronized void onTransactionChainFailed(final TransactionChain<?, ?> chain,
             final AsyncTransaction<?, ?> transaction, final Throwable cause) {
-        LOG.error("Transaction chain failed.", cause);
-        this.chain.close();
-        //FIXME BGPCEP-731
-        /*
-        this.chain = this.rib.createPeerDOMChain(this);
-        this.ribWriter = AdjRibInWriter.create(this.rib.getYangRibId(), this.peerRole, this.chain);
-        releaseConnection();*/
+        LOG.error("Transaction domChain failed.", cause);
+        releaseConnection();
     }
 
     @Override
index 7873b3a2d5b3eb12855631097f56ce6f6231997b..612efded635fbdec6b020372b02242bf2dfbc451 100644 (file)
@@ -11,21 +11,27 @@ import com.google.common.collect.ImmutableList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.Peer;
 import org.opendaylight.protocol.concepts.AbstractRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.PeerRole;
 
 public final class BGPPeerTrackerImpl implements BGPPeerTracker {
     @GuardedBy("this")
     private final Map<PeerId, Peer> peers = new HashMap<>();
     private ImmutableList<Peer> peersList;
+    private ImmutableList<Peer> peersFilteredList;
 
     @Override
     public synchronized AbstractRegistration registerPeer(final Peer peer) {
         this.peers.put(peer.getPeerId(), peer);
         this.peersList = ImmutableList.copyOf(this.peers.values());
+        this.peersFilteredList = ImmutableList.copyOf(this.peers.values().stream()
+                .filter(p1->p1.getRole() != PeerRole.Internal)
+                .collect(Collectors.toList()));
         return new AbstractRegistration() {
             @Override
             protected void removeRegistration() {
@@ -45,4 +51,9 @@ public final class BGPPeerTrackerImpl implements BGPPeerTracker {
     public synchronized List<Peer> getPeers() {
         return this.peersList;
     }
+
+    @Override
+    public synchronized List<Peer> getNonInternalPeers() {
+        return this.peersFilteredList;
+    }
 }
\ No newline at end of file
index 98a48e90e1ba002b808582b248b2bc9ae0497905..b5178712092f615a0f0e98a8df59a3f34f58bd5a 100644 (file)
@@ -11,14 +11,17 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.FluentFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.LongAdder;
 import javax.annotation.Nonnull;
+import javax.annotation.concurrent.GuardedBy;
 import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
@@ -88,6 +91,8 @@ final class EffectiveRibInWriter implements PrefixesReceivedCounters, PrefixesIn
     private final BGPRibRoutingPolicy ribPolicies;
     private final BGPRouteEntryImportParameters peerImportParameters;
     private final BGPTableTypeRegistryConsumer tableTypeRegistry;
+    @GuardedBy("this")
+    private FluentFuture<? extends CommitInfo> submitted;
 
     EffectiveRibInWriter(
             final BGPRouteEntryImportParameters peer,
@@ -182,7 +187,9 @@ final class EffectiveRibInWriter implements PrefixesReceivedCounters, PrefixesIn
             }
         }
         if (tx != null) {
-            tx.commit().addCallback(new FutureCallback<CommitInfo>() {
+            final FluentFuture<? extends CommitInfo> future = tx.commit();
+            this.submitted = future;
+            future.addCallback(new FutureCallback<CommitInfo>() {
                 @Override
                 public void onSuccess(final CommitInfo result) {
                     LOG.trace("Successful commit");
@@ -278,6 +285,13 @@ final class EffectiveRibInWriter implements PrefixesReceivedCounters, PrefixesIn
             this.reg.close();
             this.reg = null;
         }
+        if (this.submitted != null) {
+            try {
+                this.submitted.get();
+            } catch (final InterruptedException | ExecutionException throwable) {
+                LOG.error("Write routes failed", throwable);
+            }
+        }
         if (this.chain != null) {
             this.chain.close();
             this.chain = null;
index 3313b1e6862a191685ee0c9a9764b6c4d274be2e..671af0a551884e4c6d0f8e350eba870179d1af8a 100644 (file)
@@ -12,8 +12,10 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.primitives.UnsignedInteger;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.MoreExecutors;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.LongAdder;
@@ -36,6 +38,9 @@ import org.opendaylight.protocol.bgp.rib.impl.state.rib.TotalPrefixesCounter;
 import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
 import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
+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.StaleBestPathRoute;
 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
@@ -50,22 +55,29 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.
 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.rib.tables.Attributes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
 import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @NotThreadSafe
-final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPathsCounter,
+final class LocRibWriter<C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
+        implements AutoCloseable, TotalPrefixesCounter, TotalPathsCounter,
         ClusteredDataTreeChangeListener<Tables> {
 
     private static final Logger LOG = LoggerFactory.getLogger(LocRibWriter.class);
 
-    private final Map<String, RouteEntry> routeEntries = new HashMap<>();
+    private final Map<String, RouteEntry<C,S,R,I>> routeEntries = new HashMap<>();
     private final Long ourAs;
-    private final RIBSupport ribSupport;
+    private final RIBSupport<C,S,R,I> ribSupport;
     private final DataBroker dataBroker;
     private final PathSelectionMode pathSelectionMode;
     private final LongAdder totalPathsCounter = new LongAdder();
@@ -79,7 +91,7 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
     @GuardedBy("this")
     private ListenerRegistration<LocRibWriter> reg;
 
-    private LocRibWriter(final RIBSupport<?, ?, ?, ?> ribSupport,
+    private LocRibWriter(final RIBSupport<C,S,R,I> ribSupport,
             final BindingTransactionChain chain,
             final KeyedInstanceIdentifier<Rib, RibKey> ribIId,
             final Long ourAs,
@@ -99,13 +111,13 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
         this.peerTracker = peerTracker;
         this.pathSelectionMode = pathSelectionMode;
 
-        this.entryDep = new RouteEntryDependenciesContainerImpl(this.ribSupport, ribPolicies,
+        this.entryDep = new RouteEntryDependenciesContainerImpl(this.ribSupport, this.peerTracker, ribPolicies,
                 tablesKey, afiSafiType, this.locRibTableIID);
         init();
     }
 
     public static LocRibWriter create(
-            @Nonnull final RIBSupport<?, ?, ?, ?> ribSupport,
+            @Nonnull final RIBSupport ribSupport,
             @Nonnull final TablesKey tablesKey,
             @Nonnull final Class<? extends AfiSafiType> afiSafiType,
             @Nonnull final BindingTransactionChain chain,
@@ -167,8 +179,8 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
     }
 
     @Nonnull
-    private RouteEntry createEntry(final String routeId) {
-        final RouteEntry ret = this.pathSelectionMode.createRouteEntry();
+    private RouteEntry<C,S,R,I> createEntry(final String routeId) {
+        final RouteEntry<C,S,R,I> ret = this.pathSelectionMode.createRouteEntry();
         this.routeEntries.put(routeId, ret);
         this.totalPrefixesCounter.increment();
         LOG.trace("Created new entry for {}", routeId);
@@ -190,7 +202,7 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
         LOG.trace("Received data change {} to LocRib {}", changes, this);
         final WriteTransaction tx = this.chain.newWriteOnlyTransaction();
         try {
-            final Map<RouteUpdateKey, RouteEntry> toUpdate = update(tx, changes);
+            final Map<RouteUpdateKey, RouteEntry<C,S,R,I>> toUpdate = update(tx, changes);
 
             if (!toUpdate.isEmpty()) {
                 walkThrough(tx, toUpdate.entrySet());
@@ -213,9 +225,9 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
     }
 
     @SuppressWarnings("unchecked")
-    private Map<RouteUpdateKey, RouteEntry> update(final WriteTransaction tx,
+    private Map<RouteUpdateKey, RouteEntry<C,S,R,I>> update(final WriteTransaction tx,
             final Collection<DataTreeModification<Tables>> changes) {
-        final Map<RouteUpdateKey, RouteEntry> ret = new HashMap<>();
+        final Map<RouteUpdateKey, RouteEntry<C,S,R,I>> ret = new HashMap<>();
         for (final DataTreeModification<Tables> tc : changes) {
             final DataObjectModification<Tables> table = tc.getRootNode();
             final DataTreeIdentifier<Tables> rootPath = tc.getRootPath();
@@ -226,12 +238,17 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
             Initialize Peer with routes under loc rib
              */
             if (!this.routeEntries.isEmpty() && table.getDataBefore() == null) {
-                final org.opendaylight.protocol.bgp.rib.spi.Peer peer
+                final org.opendaylight.protocol.bgp.rib.spi.Peer toPeer
                         = this.peerTracker.getPeer(peerKIid.getKey().getPeerId());
-                if (peer != null && peer.supportsTable(this.entryDep.getLocalTablesKey())) {
-                    LOG.debug("Peer {} table has been created, inserting existent routes", peer.getPeerId());
-                    this.routeEntries.forEach((key, value) -> value.initializeBestPaths(this.entryDep,
-                            new RouteEntryInfoImpl(peer, key), tx));
+                if (toPeer != null && toPeer.supportsTable(this.entryDep.getLocalTablesKey())) {
+                    LOG.debug("Peer {} table has been created, inserting existent routes", toPeer.getPeerId());
+                    final List<ActualBestPathRoutes<C,S,R,I>> routesToStore = new ArrayList<>();
+                    for (final Map.Entry<String, RouteEntry<C,S,R,I>> entry:this.routeEntries.entrySet()) {
+                        final List<ActualBestPathRoutes<C,S,R,I>> filteredRoute = entry.getValue()
+                                .actualBestPaths(this.ribSupport, new RouteEntryInfoImpl(toPeer, entry.getKey()));
+                        routesToStore.addAll(filteredRoute);
+                    }
+                    toPeer.initializeRibOut(this.entryDep, routesToStore);
                 }
             }
             /*
@@ -247,7 +264,7 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
             final DataObjectModification<Tables> table,
             final UnsignedInteger peerUuid,
             final WriteTransaction tx,
-            final Map<RouteUpdateKey, RouteEntry> routes
+            final Map<RouteUpdateKey, RouteEntry<C,S,R,I>> routes
     ) {
 
         final DataObjectModification<Attributes> attUpdate = table.getModifiedChildContainer(Attributes.class);
@@ -258,8 +275,8 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
             tx.put(LogicalDatastoreType.OPERATIONAL, this.locRibTableIID.child(Attributes.class), newAttValue);
         }
 
-        final DataObjectModification routesChangesContainer =
-                table.getModifiedChildContainer(this.ribSupport.routesContainerClass());
+        final DataObjectModification routesChangesContainer
+                = table.getModifiedChildContainer((Class) this.ribSupport.routesContainerClass());
         if (routesChangesContainer == null) {
             return;
         }
@@ -269,13 +286,13 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
     private void updateRoutesEntries(
             final Collection<DataObjectModification<? extends DataObject>> routeChanges,
             final UnsignedInteger routerId,
-            final Map<RouteUpdateKey, RouteEntry> routes
+            final Map<RouteUpdateKey, RouteEntry<C,S,R,I>> routes
     ) {
         for (final DataObjectModification<? extends DataObject> route : routeChanges) {
-            final Route newRoute = (Route) route.getDataAfter();
-            final Route oldRoute = (Route) route.getDataBefore();
+            final R newRoute = (R) route.getDataAfter();
+            final R oldRoute = (R) route.getDataBefore();
             String routeKey;
-            RouteEntry entry;
+            RouteEntry<C,S,R,I> entry;
             if (newRoute != null) {
                 routeKey = newRoute.getRouteKey();
                 entry = this.routeEntries.get(routeKey);
@@ -307,16 +324,45 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
     }
 
     private void walkThrough(final WriteTransaction tx,
-            final Set<Map.Entry<RouteUpdateKey, RouteEntry>> toUpdate) {
-        for (final Map.Entry<RouteUpdateKey, RouteEntry> e : toUpdate) {
+            final Set<Map.Entry<RouteUpdateKey, RouteEntry<C,S,R,I>>> toUpdate) {
+        final List<StaleBestPathRoute<C,S,R,I>> staleRoutes = new ArrayList<>();
+        final List<AdvertizedRoute<C,S,R,I>> newRoutes = new ArrayList<>();
+        for (final Map.Entry<RouteUpdateKey, RouteEntry<C,S,R,I>> e : toUpdate) {
             LOG.trace("Walking through {}", e);
-            final RouteEntry entry = e.getValue();
+            final RouteEntry<C,S,R,I> entry = e.getValue();
 
             if (!entry.selectBest(this.ourAs)) {
                 LOG.trace("Best path has not changed, continuing");
                 continue;
             }
-            entry.updateBestPaths(entryDep, e.getKey().getRouteId(), tx);
+             entry.removeStalePaths(this.ribSupport, e.getKey().getRouteId()).ifPresent(staleRoutes::add);
+            newRoutes.addAll(entry.newBestPaths(this.ribSupport, e.getKey().getRouteId()));
+        }
+        updateLocRib(newRoutes, staleRoutes, tx);
+        this.peerTracker.getNonInternalPeers().parallelStream()
+                .forEach(toPeer->toPeer.refreshRibOut(this.entryDep, staleRoutes, newRoutes));
+    }
+
+    private void updateLocRib(final List<AdvertizedRoute<C, S, R, I>> newRoutes,
+            final List<StaleBestPathRoute<C, S, R, I>> staleRoutes,
+            final WriteTransaction tx) {
+        final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget = this.entryDep.getLocRibTableTarget();
+
+        for (final StaleBestPathRoute<C, S, R, I> staleContainer:staleRoutes) {
+            for (final I routeId: staleContainer.getStaleRouteKeyIdentifiers()) {
+                final InstanceIdentifier<R> routeTarget = ribSupport.createRouteIdentifier(locRibTarget, routeId);
+                LOG.debug("Delete route from LocRib {}", routeTarget);
+                tx.delete(LogicalDatastoreType.OPERATIONAL, routeTarget);
+            }
+        }
+
+        for (final AdvertizedRoute<C,S,R,I> advRoute : newRoutes) {
+            final R route = advRoute.getRoute();
+            final I iid = advRoute.getAddPathRouteKeyIdentifier();
+            final InstanceIdentifier<R> locRibRouteTarget
+                    = this.ribSupport.createRouteIdentifier(locRibTarget, iid);
+            LOG.debug("Write route to LocRib {}", route);
+            tx.put(LogicalDatastoreType.OPERATIONAL, locRibRouteTarget, route);
         }
     }
 
@@ -330,7 +376,7 @@ final class LocRibWriter implements AutoCloseable, TotalPrefixesCounter, TotalPa
         return this.totalPathsCounter.longValue();
     }
 
-    public TablesKey getTableKey() {
+    TablesKey getTableKey() {
         return this.tk;
     }
 }
index 78009f6f5e0bfa818f715c76e86322105bcd97ae..47308451160d23ad79a9c214f14db73befa16ba3 100755 (executable)
@@ -43,7 +43,6 @@ import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 import org.opendaylight.protocol.bgp.rib.impl.spi.CodecsRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
-import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.state.BGPRIBStateImpl;
 import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
@@ -61,6 +60,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.Peer;
 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.rib.tables.Routes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.BgpId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -99,15 +99,14 @@ public final class RIBImpl extends BGPRIBStateImpl implements RIB, TransactionCh
     private final RIBSupportContextRegistryImpl ribContextRegistry;
     private final CodecsRegistryImpl codecsRegistry;
     private final BGPTableTypeRegistryConsumer tableTypeRegistry;
-    @GuardedBy("this")
-    private ClusterSingletonServiceRegistration registration;
     private final DOMDataBrokerExtension domService;
     private final Map<TransactionChain<?, ?>, LocRibWriter> txChainToLocRibWriter = new HashMap<>();
     private final Map<TablesKey, PathSelectionMode> bestPathSelectionStrategies;
     private final RibId ribId;
-    private final BGPPeerTracker peerTracker;
+    private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl();
     private final BGPRibRoutingPolicy ribPolicies;
-
+    @GuardedBy("this")
+    private ClusterSingletonServiceRegistration registration;
     @GuardedBy("this")
     private DOMTransactionChain domChain;
     @GuardedBy("this")
@@ -124,7 +123,6 @@ public final class RIBImpl extends BGPRIBStateImpl implements RIB, TransactionCh
             final DOMDataBroker domDataBroker,
             final DataBroker dataBroker,
             final BGPRibRoutingPolicy ribPolicies,
-            final BGPPeerTracker bgpPeerTracker,
             final List<BgpTableType> localTables,
             final Map<TablesKey, PathSelectionMode> bestPathSelectionStrategies
     ) {
@@ -141,7 +139,6 @@ public final class RIBImpl extends BGPRIBStateImpl implements RIB, TransactionCh
         this.domService = this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class);
         this.extensions = requireNonNull(extensions);
         this.ribPolicies = requireNonNull(ribPolicies);
-        this.peerTracker = requireNonNull(bgpPeerTracker);
         this.codecsRegistry = codecsRegistry;
         this.ribContextRegistry = RIBSupportContextRegistryImpl.create(extensions, this.codecsRegistry);
         final InstanceIdentifierBuilder yangRibIdBuilder = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Rib.QNAME);
@@ -172,9 +169,9 @@ public final class RIBImpl extends BGPRIBStateImpl implements RIB, TransactionCh
             table.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue()));
         }
 
-        final RIBSupportContext supportContext = this.ribContextRegistry.getRIBSupportContext(key);
-        if (supportContext != null) {
-            final ChoiceNode routes = supportContext.getRibSupport().emptyRoutes();
+        final RIBSupport<? extends Routes, ?, ?, ?> ribSupport = this.ribContextRegistry.getRIBSupport(key);
+        if (ribSupport != null) {
+            final ChoiceNode routes = ribSupport.emptyRoutes();
             table.withChild(routes);
 
             tx.put(LogicalDatastoreType.OPERATIONAL, tableId.build(), table.build());
@@ -197,7 +194,7 @@ public final class RIBImpl extends BGPRIBStateImpl implements RIB, TransactionCh
         final BindingTransactionChain txChain = createPeerChain(this);
         PathSelectionMode pathSelectionStrategy = this.bestPathSelectionStrategies.get(key);
         if (pathSelectionStrategy == null) {
-            pathSelectionStrategy = BasePathSelectionModeFactory.createBestPathSelectionStrategy(this.peerTracker);
+            pathSelectionStrategy = BasePathSelectionModeFactory.createBestPathSelectionStrategy();
         }
 
         final LocRibWriter locRibWriter = LocRibWriter.create(
index bd587872564314e087b1a5c96113aa196bb81e6c..82c41358da6d157323aabd8d235c6308a5dd4d1b 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.protocol.bgp.rib.impl;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.base.Verify;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.Map.Entry;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
@@ -44,7 +45,7 @@ class RIBSupportContextImpl extends RIBSupportContext {
     private final RIBSupport<?, ?, ?, ?> ribSupport;
     private final Codecs codecs;
 
-    public RIBSupportContextImpl(final RIBSupport<?, ?, ?, ?> ribSupport, final CodecsRegistry codecs) {
+    RIBSupportContextImpl(final RIBSupport<?, ?, ?, ?> ribSupport, final CodecsRegistry codecs) {
         this.ribSupport = requireNonNull(ribSupport);
         this.codecs = codecs.getCodecs(this.ribSupport);
     }
@@ -85,6 +86,7 @@ class RIBSupportContextImpl extends RIBSupportContext {
 
     @Override
     @SuppressWarnings("unchecked")
+    @SuppressFBWarnings("NM_CONFUSING")
     public <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
         R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
             RIBSupport<C, S, R, I> getRibSupport() {
index feae21443225f8a56e8b4a7371d8a72da5676c10..e75dd3793c6c8c1a38ca2e122851e28bbe3e355e 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.protocol.bgp.rib.impl;
 
 import static java.util.Objects.requireNonNull;
 
+import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
 import org.opendaylight.protocol.bgp.rib.spi.entry.RouteEntryDependenciesContainer;
 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
@@ -24,31 +25,34 @@ import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
-public final class RouteEntryDependenciesContainerImpl implements RouteEntryDependenciesContainer {
+final class RouteEntryDependenciesContainerImpl implements RouteEntryDependenciesContainer {
     private final RIBSupport<?, ?, ?, ?> ribSupport;
     private final TablesKey tablesKey;
     private final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget;
     private final BGPRibRoutingPolicy routingPolicies;
     private final Class<? extends AfiSafiType> afiSafiType;
+    private final BGPPeerTracker peerTracker;
 
-    public RouteEntryDependenciesContainerImpl(
+    RouteEntryDependenciesContainerImpl(
             final RIBSupport<?, ?, ?, ?> ribSupport,
+            final BGPPeerTracker peerTracker,
             final BGPRibRoutingPolicy routingPolicies,
             final TablesKey tablesKey,
             final Class<? extends AfiSafiType> afiSafiType,
             final KeyedInstanceIdentifier<Tables, TablesKey> locRibTarget) {
         this.ribSupport = requireNonNull(ribSupport);
+        this.peerTracker = requireNonNull(peerTracker);
         this.tablesKey = requireNonNull(tablesKey);
         this.afiSafiType = requireNonNull(afiSafiType);
         this.routingPolicies = requireNonNull(routingPolicies);
         this.locRibTarget = requireNonNull(locRibTarget);
     }
 
-    @SuppressWarnings("unchecked")
     @Override
-    public <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<C>,
-        R extends Route & ChildOf<S> & Identifiable<I>, I extends Identifier<R>>
-            RIBSupport<C, S, R, I> getRibSupport() {
+    @SuppressWarnings("unchecked")
+    public <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>>
+    RIBSupport<C, S, R, I> getRIBSupport() {
         return (RIBSupport<C, S, R, I>) this.ribSupport;
     }
 
@@ -71,4 +75,9 @@ public final class RouteEntryDependenciesContainerImpl implements RouteEntryDepe
     public BGPRibRoutingPolicy getRoutingPolicies() {
         return this.routingPolicies;
     }
+
+    @Override
+    public BGPPeerTracker getPeerTracker() {
+        return this.peerTracker;
+    }
 }
index b557cdc4f5a2c53b584f2931d1f6f85e5ebbc2c9..abea6acb9ecce77af40c67742489207c838cac1b 100644 (file)
@@ -221,7 +221,7 @@ public final class OpenConfigMappingUtil {
     }
 
     public static Map<BgpTableType, PathSelectionMode> toPathSelectionMode(final List<AfiSafi> afiSafis,
-            final BGPTableTypeRegistryConsumer tableTypeRegistry, final BGPPeerTracker peerTracker) {
+            final BGPTableTypeRegistryConsumer tableTypeRegistry) {
         final Map<BgpTableType, PathSelectionMode> pathSelectionModes = new HashMap<>();
         for (final AfiSafi afiSafi : afiSafis) {
             final BgpNeighborAddPathsConfig afiSafi2 = afiSafi.augmentation(GlobalAddPathsConfig.class);
@@ -231,9 +231,9 @@ public final class OpenConfigMappingUtil {
                     final Short sendMax = afiSafi2.getSendMax();
                     final PathSelectionMode selectionMode;
                     if (sendMax > 1) {
-                        selectionMode = new AddPathBestNPathSelection(sendMax.longValue(), peerTracker);
+                        selectionMode = new AddPathBestNPathSelection(sendMax.longValue());
                     } else {
-                        selectionMode = new AllPathSelection(peerTracker);
+                        selectionMode = new AllPathSelection();
                     }
                     pathSelectionModes.put(bgpTableType.get(), selectionMode);
                 }
index 8f7125b63b19386277b917adafef0927434f0427..c3f8c5c8a13d751796d18cb6a0c3f5866c1514a9 100644 (file)
@@ -253,9 +253,8 @@ public final class RibImpl implements RIB, BGPRibStateConsumer, AutoCloseable {
         this.asNumber = globalConfig.getAs();
         this.routerId = globalConfig.getRouterId();
         this.clusterId = getGlobalClusterIdentifier(globalConfig);
-        final BGPPeerTrackerImpl peerTracker = new BGPPeerTrackerImpl();
         final Map<TablesKey, PathSelectionMode> pathSelectionModes = OpenConfigMappingUtil
-                .toPathSelectionMode(this.afiSafi, tableTypeRegistry, peerTracker).entrySet()
+                .toPathSelectionMode(this.afiSafi, tableTypeRegistry).entrySet()
                 .stream()
                 .collect(Collectors.toMap(entry ->
                         new TablesKey(entry.getKey().getAfi(), entry.getKey().getSafi()), Map.Entry::getValue));
@@ -276,7 +275,6 @@ public final class RibImpl implements RIB, BGPRibStateConsumer, AutoCloseable {
                 this.domBroker,
                 this.dataBroker,
                 ribPolicy,
-                peerTracker,
                 toTableTypes(this.afiSafi, tableTypeRegistry),
                 pathSelectionModes);
     }
diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/PeerTransactionChain.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/PeerTransactionChain.java
new file mode 100644 (file)
index 0000000..bdd7005
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.rib.impl.spi;
+
+import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
+
+/**
+ * Provides access to unique DOMTransactionChain per Peer.
+ */
+public interface PeerTransactionChain {
+    /**
+     * Returns Peer DOMTransactionChain.
+     *
+     * @return DOMTransactionChain
+     */
+    DOMTransactionChain getDomChain();
+}
index 7a3751f0f0066d2187b9f1adcb2f24c32a65595a..861a40bc7767416d84e7bbd08e78534242efd4be 100644 (file)
@@ -136,7 +136,6 @@ public abstract class AbstractAddPathTest extends DefaultRibPoliciesMockTest {
     private NioEventLoopGroup boss;
     private org.opendaylight.protocol.bgp.inet.BGPActivator inetActivator;
     protected StrictBGPPeerRegistry serverRegistry;
-    protected final BGPPeerTrackerImpl peerTracker = new BGPPeerTrackerImpl();
     protected CodecsRegistryImpl codecsRegistry;
 
     @Before
index 68651b4f6cf4cb349b2463677e55af9d56f778de..84a01294122818a9409fbf88ea16bb72bcb0bf6a 100644 (file)
@@ -136,8 +136,6 @@ public class AbstractRIBTestSetup extends DefaultRibPoliciesMockTest {
 
     @Mock
     private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
-    private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl();
-
     private static ModuleInfoBackedContext createClassLoadingStrategy() {
         final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
         try {
@@ -183,9 +181,9 @@ public class AbstractRIBTestSetup extends DefaultRibPoliciesMockTest {
         doReturn(mock(ClusterSingletonServiceRegistration.class)).when(this.clusterSingletonServiceProvider)
                 .registerClusterSingletonService(any(ClusterSingletonService.class));
         this.rib = new RIBImpl(this.tableRegistry, new RibId("test"), new AsNumber(5L), RIB_ID, context,
-                this.dispatcher, codecsRegistry, this.dom, getDataBroker(), this.policies, this.peerTracker,
+                this.dispatcher, codecsRegistry, this.dom, getDataBroker(), this.policies,
                 localTables, Collections.singletonMap(new TablesKey(AFI, SAFI),
-                BasePathSelectionModeFactory.createBestPathSelectionStrategy(this.peerTracker)));
+                BasePathSelectionModeFactory.createBestPathSelectionStrategy()));
         this.rib.onGlobalContextUpdated(schemaContext);
         this.ribSupport = getRib().getRibSupportContext().getRIBSupport(KEY);
     }
index ff5a2612027e87a9965a399966185254bdbf2eb7..fc0cbd8da2d0b83a569cd527f7a8444ada20d482 100644 (file)
@@ -53,11 +53,11 @@ public class AddPathAllPathsTest extends AbstractAddPathTest {
     public void setUp() throws Exception {
         super.setUp();
         final Map<TablesKey, PathSelectionMode> pathTables
-                = ImmutableMap.of(TABLES_KEY, new AllPathSelection(this.peerTracker));
+                = ImmutableMap.of(TABLES_KEY, new AllPathSelection());
 
         this.ribImpl = new RIBImpl(this.tableRegistry, new RibId("test-rib"), AS_NUMBER, BGP_ID,
                 this.ribExtension, this.serverDispatcher, this.codecsRegistry,
-            getDomBroker(), getDataBroker(), this.policies, this.peerTracker, TABLES_TYPE, pathTables);
+            getDomBroker(), getDataBroker(), this.policies, TABLES_TYPE, pathTables);
 
         this.ribImpl.instantiateServiceInstance();
         this.ribImpl.onGlobalContextUpdated(this.schemaService.getGlobalContext());
index 34f428df36bb81b89cf21bbae71685964f9fa1dc..59531c02a85292f54e1a1c600c2c3d22d4c47069 100644 (file)
@@ -40,12 +40,12 @@ public class AddPathBasePathsTest extends AbstractAddPathTest {
         super.setUp();
         final TablesKey tk = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
         final Map<TablesKey, PathSelectionMode> pathTables = ImmutableMap.of(tk,
-            BasePathSelectionModeFactory.createBestPathSelectionStrategy(this.peerTracker));
+            BasePathSelectionModeFactory.createBestPathSelectionStrategy());
 
         this.ribImpl = new RIBImpl(this.tableRegistry, new RibId("test-rib"), AS_NUMBER, new BgpId(RIB_ID),
                 this.ribExtension,
                 this.serverDispatcher, this.codecsRegistry, getDomBroker(), getDataBroker(), this.policies,
-                this.peerTracker, TABLES_TYPE, pathTables);
+                TABLES_TYPE, pathTables);
         this.ribImpl.instantiateServiceInstance();
         this.ribImpl.onGlobalContextUpdated(this.schemaService.getGlobalContext());
         final ChannelFuture channelFuture = this.serverDispatcher.createServer(new InetSocketAddress(RIB_ID, PORT));
index 28ebdcb764a40b560f111a4ca4243c43c5b6d863..a3e2d4941531ba11b7475aace80f9348b83c69f6 100644 (file)
@@ -39,13 +39,12 @@ public class AddPathNPathsTest extends AbstractAddPathTest {
     public void setUp() throws Exception {
         super.setUp();
         final TablesKey tk = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
-        final Map<TablesKey, PathSelectionMode> pathTables = ImmutableMap.of(tk,
-                new AddPathBestNPathSelection(2L, this.peerTracker));
+        final Map<TablesKey, PathSelectionMode> pathTables = ImmutableMap.of(tk, new AddPathBestNPathSelection(2L));
 
         this.ribImpl = new RIBImpl(this.tableRegistry, new RibId("test-rib"), AS_NUMBER, new BgpId(RIB_ID),
                 this.ribExtension,
                 this.serverDispatcher, this.codecsRegistry, getDomBroker(), getDataBroker(), this.policies,
-                this.peerTracker, TABLES_TYPE,  pathTables);
+                TABLES_TYPE,  pathTables);
 
         this.ribImpl.instantiateServiceInstance();
         this.ribImpl.onGlobalContextUpdated(this.schemaService.getGlobalContext());
index e7b0a52cb71f5ac910103df41785f763d1fd66ef..5c1f284c022450fa5eae5c2ef2a68f1f7531edd8 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.protocol.bgp.rib.impl.spi.PeerTransactionChain;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
@@ -61,6 +62,8 @@ public class AdjRibsInWriterTest {
     private RIBSupportContextRegistry registry;
     @Mock
     private RIBSupportContext context;
+    @Mock
+    private PeerTransactionChain ptc;
     private AdjRibInWriter writer;
 
     @Before
@@ -76,12 +79,13 @@ public class AdjRibsInWriterTest {
         doNothing().when(this.tx).merge(eq(LogicalDatastoreType.OPERATIONAL),
                 any(YangInstanceIdentifier.class), any(NormalizedNode.class));
         doReturn(this.context).when(this.registry).getRIBSupportContext(any(TablesKey.class));
+        doReturn(this.chain).when(this.ptc).getDomChain();
         doNothing().when(this.context).createEmptyTableStructure(eq(this.tx), any(YangInstanceIdentifier.class));
     }
 
     @Test
     public void testTransform() {
-        this.writer = AdjRibInWriter.create(YangInstanceIdentifier.of(Rib.QNAME), PeerRole.Ebgp, this.chain);
+        this.writer = AdjRibInWriter.create(YangInstanceIdentifier.of(Rib.QNAME), PeerRole.Ebgp, this.ptc);
         assertNotNull(this.writer);
         final YangInstanceIdentifier peerPath = YangInstanceIdentifier.builder().node(Rib.QNAME)
                 .node(Peer.QNAME).nodeWithKey(Peer.QNAME,
index e3148da2437fb2632bcb7c4381968faf2e822609..67e9c04ba4ce745c94a7218ef0976476058b9f2e 100755 (executable)
@@ -40,7 +40,6 @@ import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionPr
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 import org.opendaylight.protocol.bgp.rib.mock.BGPMock;
 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBExtensionProviderActivator;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
 import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext;
 import org.opendaylight.protocol.bgp.util.HexDumpBGPFileParser;
@@ -74,7 +73,6 @@ public class ParserToSalTest extends DefaultRibPoliciesMockTest {
 
     @Mock
     private BGPDispatcher dispatcher;
-    private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl();
     private CodecsRegistryImpl codecsRegistry;
 
     @Before
@@ -113,9 +111,9 @@ public class ParserToSalTest extends DefaultRibPoliciesMockTest {
                 LinkstateSubsequentAddressFamily.class));
 
         final RIBImpl rib = new RIBImpl(this.tableRegistry, new RibId(TEST_RIB_ID), AS_NUMBER, BGP_ID, this.ext2,
-                this.dispatcher, this.codecsRegistry, getDomBroker(), getDataBroker(), this.policies, this.peerTracker,
+                this.dispatcher, this.codecsRegistry, getDomBroker(), getDataBroker(), this.policies,
                 tables, Collections.singletonMap(TABLE_KEY, BasePathSelectionModeFactory
-                        .createBestPathSelectionStrategy(this.peerTracker)));
+                        .createBestPathSelectionStrategy()));
         rib.instantiateServiceInstance();
         assertTablesExists(tables);
         rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
@@ -131,9 +129,9 @@ public class ParserToSalTest extends DefaultRibPoliciesMockTest {
         final List<BgpTableType> tables = ImmutableList.of(new BgpTableTypeImpl(Ipv4AddressFamily.class,
                 UnicastSubsequentAddressFamily.class));
         final RIBImpl rib = new RIBImpl(this.tableRegistry, new RibId(TEST_RIB_ID), AS_NUMBER, BGP_ID, this.ext1,
-                this.dispatcher, this.codecsRegistry, getDomBroker(), getDataBroker(), this.policies, this.peerTracker,
+                this.dispatcher, this.codecsRegistry, getDomBroker(), getDataBroker(), this.policies,
                 tables, Collections.singletonMap(TABLE_KEY,
-                BasePathSelectionModeFactory.createBestPathSelectionStrategy(this.peerTracker)));
+                BasePathSelectionModeFactory.createBestPathSelectionStrategy()));
         rib.instantiateServiceInstance();
         rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
         assertTablesExists(tables);
index 4dd744b4c196e03f209422897356721ea7d3616a..cc581d0bb10e7dfcd475d50688c02351e9a11b22 100644 (file)
@@ -207,11 +207,11 @@ public class SynchronizationAndExceptionTest extends AbstractAddPathTest {
     @Test
     public void testHandleMessageAfterException() {
         final Map<TablesKey, PathSelectionMode> pathTables = ImmutableMap.of(TABLES_KEY,
-            BasePathSelectionModeFactory.createBestPathSelectionStrategy(this.peerTracker));
+            BasePathSelectionModeFactory.createBestPathSelectionStrategy());
         final RIBImpl ribImpl = new RIBImpl(this.tableRegistry, new RibId(RIB_ID), AS_NUMBER,  new BgpId(RIB_ID),
                 this.ribExtension,
                 this.serverDispatcher, this.codecsRegistry, this.domBroker, getDataBroker(), this.policies,
-                this.peerTracker, ImmutableList.of(this.ipv4tt), pathTables);
+                ImmutableList.of(this.ipv4tt), pathTables);
         ribImpl.instantiateServiceInstance();
         ribImpl.onGlobalContextUpdated(this.schemaService.getGlobalContext());
 
@@ -256,11 +256,11 @@ public class SynchronizationAndExceptionTest extends AbstractAddPathTest {
     @Test
     public void testUseCase1() {
         final Map<TablesKey, PathSelectionMode> pathTables = ImmutableMap.of(TABLES_KEY,
-                BasePathSelectionModeFactory.createBestPathSelectionStrategy(this.peerTracker));
+                BasePathSelectionModeFactory.createBestPathSelectionStrategy());
         final RIBImpl ribImpl = new RIBImpl(this.tableRegistry, new RibId(RIB_ID), AS_NUMBER, new BgpId(RIB_ID),
                 this.ribExtension,
                 this.serverDispatcher, this.codecsRegistry, this.domBroker, getDataBroker(), this.policies,
-                this.peerTracker, ImmutableList.of(this.ipv4tt), pathTables);
+                ImmutableList.of(this.ipv4tt), pathTables);
         ribImpl.instantiateServiceInstance();
         ribImpl.onGlobalContextUpdated(this.schemaService.getGlobalContext());
 
index d4cfaa462cd540ed6782cc310ca4548760bb1454..66da908cd8094c36b2848544e1a81c1d94961b39 100644 (file)
@@ -43,9 +43,7 @@ import org.opendaylight.protocol.bgp.mode.impl.add.all.paths.AllPathSelection;
 import org.opendaylight.protocol.bgp.mode.impl.add.n.paths.AddPathBestNPathSelection;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
-import org.opendaylight.protocol.bgp.rib.impl.BGPPeerTrackerImpl;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
-import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 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.rev151009.BgpNeighborTransportConfig;
@@ -117,10 +115,8 @@ public class OpenConfigMappingUtilTest {
 
     private static final Long ALL_PATHS = 0L;
     private static final Long N_PATHS = 2L;
-    private static final BGPPeerTracker PEER_TRACKER = new BGPPeerTrackerImpl();
-    private static final PathSelectionMode ADD_PATH_BEST_N_PATH_SELECTION = new AddPathBestNPathSelection(N_PATHS,
-            PEER_TRACKER);
-    private static final PathSelectionMode ADD_PATH_BEST_ALL_PATH_SELECTION = new AllPathSelection(PEER_TRACKER);
+    private static final PathSelectionMode ADD_PATH_BEST_N_PATH_SELECTION = new AddPathBestNPathSelection(N_PATHS);
+    private static final PathSelectionMode ADD_PATH_BEST_ALL_PATH_SELECTION = new AllPathSelection();
     private static final BgpTableType BGP_TABLE_TYPE_IPV4 = new BgpTableTypeImpl(Ipv4AddressFamily.class,
             UnicastSubsequentAddressFamily.class);
     private static final BgpTableType BGP_TABLE_TYPE_IPV6
@@ -408,7 +404,7 @@ public class OpenConfigMappingUtilTest {
             .addAugmentation(GlobalAddPathsConfig.class, new GlobalAddPathsConfigBuilder()
                     .setSendMax(Shorts.checkedCast(ALL_PATHS)).build()).build());
         final Map<BgpTableType, PathSelectionMode> result = OpenConfigMappingUtil
-                .toPathSelectionMode(families, this.tableTypeRegistry, PEER_TRACKER);
+                .toPathSelectionMode(families, this.tableTypeRegistry);
         final Map<BgpTableType, PathSelectionMode> expected = new HashMap<>();
         expected.put(new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class),
                 ADD_PATH_BEST_N_PATH_SELECTION);
index 163ffd1c7eca83c8180d027ec1a5878ed9890256..c75d06960a0101391f416dd81443e1a8cebc8ffc 100644 (file)
@@ -43,4 +43,13 @@ public interface BGPPeerTracker {
      */
     @Nonnull
     List<Peer> getPeers();
+
+    /**
+     * Returns map of PeerId per PeerRole, filtering internal Peers.
+     * Role with none peerId will be filtered.
+     *
+     * @return Returns map of Peer group by PeerRole
+     */
+    @Nonnull
+    List<Peer> getNonInternalPeers();
 }
index 42f2aadbd6228f1a7d4c30bf8f42d522572c1a89..5d8269cf87bdaed9a4ca952b5f0fc9e334546685 100644 (file)
@@ -8,7 +8,20 @@
 package org.opendaylight.protocol.bgp.rib.spi;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.List;
 import javax.annotation.Nonnull;
+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;
+import org.opendaylight.protocol.bgp.rib.spi.entry.StaleBestPathRoute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
 
 /**
  * Marker interface identifying a BGP peer.
@@ -36,4 +49,30 @@ public interface Peer extends PeerTrackerInformation {
      */
     @Nonnull
     ListenableFuture<?> close();
+
+    /**
+     * Update peers ribout after path selection processing.
+     *
+     * @param entryDep    RouteEntryDependenciesContainer
+     * @param staleRoutes routes to be removed.
+     * @param newRoutes   routes to be advertized.
+     */
+    <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>,
+            I extends Identifier<R>> void refreshRibOut(
+            @Nonnull RouteEntryDependenciesContainer entryDep,
+            @Nonnull List<StaleBestPathRoute<C, S, R, I>> staleRoutes,
+            @Nonnull List<AdvertizedRoute<C, S, R, I>> newRoutes);
+
+    /**
+     * Stores under peers rib Out already present routes, before proceed to process any new route advertizement.
+     *
+     * @param entryDep RouteEntryDependenciesContainer
+     * @param routes   routes to be advertized.
+     */
+    <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(
+            @Nonnull RouteEntryDependenciesContainer entryDep,
+            List<ActualBestPathRoutes<C, S, R, I>> routes);
 }
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/ActualBestPathRoutes.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/ActualBestPathRoutes.java
new file mode 100644 (file)
index 0000000..4a68a1b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.rib.spi.entry;
+
+import static org.opendaylight.protocol.bgp.parser.spi.PathIdUtil.NON_PATH_ID_VALUE;
+
+import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+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.rib.rev180329.PeerId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+/**
+ * Preexistent routes to be advertized before process any route advertized by the peer.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class ActualBestPathRoutes<C extends Routes & DataObject & ChoiceIn<Tables>,
+        S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>,
+        I extends Identifier<R>> {
+    private final PeerId fromPeerId;
+    private final R route;
+    private final Attributes attributes;
+    private final I nonAddPathRouteKeyIdentifier;
+    private final I addPathRouteKeyIdentifier;
+
+    public ActualBestPathRoutes(final RIBSupport<C, S, R, I> ribSupport, final R route, final PeerId fromPeerId,
+            final Attributes attributes) {
+        this.fromPeerId = fromPeerId;
+        this.route = route;
+        this.attributes = attributes;
+        this.nonAddPathRouteKeyIdentifier
+                = ribSupport.createRouteListKey(NON_PATH_ID_VALUE, route.getRouteKey());
+        this.addPathRouteKeyIdentifier
+                = ribSupport.createRouteListKey(route.getPathId().getValue(), route.getRouteKey());
+    }
+
+    public PeerId getFromPeerId() {
+        return this.fromPeerId;
+    }
+
+    public R getRoute() {
+        return route;
+    }
+
+    public Attributes getAttributes() {
+        return attributes;
+    }
+
+    public I getNonAddPathRouteKeyIdentifier() {
+        return this.nonAddPathRouteKeyIdentifier;
+    }
+
+    public I getAddPathRouteKeyIdentifier() {
+        return this.addPathRouteKeyIdentifier;
+    }
+}
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/AdvertizedRoute.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/AdvertizedRoute.java
new file mode 100644 (file)
index 0000000..60dbf26
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.rib.spi.entry;
+
+import static org.opendaylight.protocol.bgp.parser.spi.PathIdUtil.NON_PATH_ID_VALUE;
+
+import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+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.rib.rev180329.PeerId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+/**
+ * new Routes to be advertized.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class AdvertizedRoute<C extends Routes & DataObject & ChoiceIn<Tables>,
+        S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>,
+        I extends Identifier<R>> {
+    private final R route;
+    private final PeerId peerId;
+    private final Attributes attributes;
+    private final boolean isFirstBestPath;
+    private final I nonAddPathRouteKeyIdentifier;
+    private final I addPathRouteKeyIdentifier;
+
+    public AdvertizedRoute(
+            final RIBSupport<C, S, R, I> ribSupport,
+            final R route,
+            final Attributes attributes,
+            final PeerId peerId) {
+        this(ribSupport, true, route, attributes, peerId);
+    }
+
+    public AdvertizedRoute(
+            final RIBSupport<C, S, R, I> ribSupport,
+            final boolean isFirstBestPath,
+            final R route,
+            final Attributes attributes,
+            final PeerId peerId) {
+        this.isFirstBestPath = isFirstBestPath;
+        this.route = route;
+        this.peerId = peerId;
+        this.attributes = attributes;
+        this.nonAddPathRouteKeyIdentifier
+                = ribSupport.createRouteListKey(NON_PATH_ID_VALUE, route.getRouteKey());
+        this.addPathRouteKeyIdentifier
+                = ribSupport.createRouteListKey(route.getPathId().getValue(), route.getRouteKey());
+
+    }
+
+    public R getRoute() {
+        return this.route;
+    }
+
+    public PeerId getFromPeerId() {
+        return this.peerId;
+    }
+
+    public Attributes getAttributes() {
+        return this.attributes;
+    }
+
+    public boolean isFirstBestPath() {
+        return this.isFirstBestPath;
+    }
+
+    public I getNonAddPathRouteKeyIdentifier() {
+        return this.nonAddPathRouteKeyIdentifier;
+    }
+
+    public I getAddPathRouteKeyIdentifier() {
+        return this.addPathRouteKeyIdentifier;
+    }
+}
index 57627ac0f2335f6d9a2bbc2070377df7ad314d91..7b58734f574060707bab60b91c90ea57d989e706 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.protocol.bgp.rib.spi.entry;
 
 import javax.annotation.Nonnull;
+import org.opendaylight.protocol.bgp.rib.spi.BGPPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
@@ -32,9 +33,9 @@ public interface RouteEntryDependenciesContainer {
      * @return RIBSupport
      */
     @Nonnull
-    <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<C>,
-        R extends Route & ChildOf<S> & Identifiable<I>, I extends Identifier<R>>
-            RIBSupport<C, S, R, I> getRibSupport();
+    <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
+            R extends Route & ChildOf<? super S> & Identifiable<I>,
+            I extends Identifier<R>> RIBSupport<C, S, R, I> getRIBSupport();
 
     /**
      * Returns the table key(AFI/SAFI) corresponding to the Route Entry.
@@ -67,4 +68,7 @@ public interface RouteEntryDependenciesContainer {
      */
     @Nonnull
     BGPRibRoutingPolicy getRoutingPolicies();
+
+    @Nonnull
+    BGPPeerTracker getPeerTracker();
 }
diff --git a/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/StaleBestPathRoute.java b/bgp/rib-spi/src/main/java/org/opendaylight/protocol/bgp/rib/spi/entry/StaleBestPathRoute.java
new file mode 100644 (file)
index 0000000..9da32ac
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.protocol.bgp.rib.spi.entry;
+
+import static org.opendaylight.protocol.bgp.parser.spi.PathIdUtil.NON_PATH_ID_VALUE;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.Route;
+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.tables.Routes;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.ChoiceIn;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+/**
+ * Routes to be removed from Data Store.
+ *
+ * @author Claudio D. Gasparini
+ */
+public final class StaleBestPathRoute<C extends Routes & DataObject & ChoiceIn<Tables>,
+        S extends ChildOf<? super C>,
+        R extends Route & ChildOf<? super S> & Identifiable<I>,
+        I extends Identifier<R>> {
+    private final I nonAddPathRouteKeyIdentifier;
+    private final List<I> addPathRouteKeyIdentifier;
+    private final boolean isNonAddPathBestPathNew;
+    private final List<I> staleRouteKeyIdentifier;
+
+    public StaleBestPathRoute(
+            final RIBSupport<C, S, R, I> ribSupport,
+            final String routeKey,
+            final List<Long> staleRoutesPathIds,
+            final List<Long> withdrawalRoutePathIds,
+            final boolean isNonAddPathBestPathNew) {
+        this.isNonAddPathBestPathNew = isNonAddPathBestPathNew;
+
+        this.staleRouteKeyIdentifier = staleRoutesPathIds.stream()
+                .map(pathId -> ribSupport.createRouteListKey(pathId, routeKey)).collect(Collectors.toList());
+        if (withdrawalRoutePathIds != null) {
+            this.addPathRouteKeyIdentifier = withdrawalRoutePathIds.stream()
+                    .map(pathId -> ribSupport.createRouteListKey(pathId, routeKey)).collect(Collectors.toList());
+        } else {
+            this.addPathRouteKeyIdentifier = Collections.emptyList();
+        }
+        this.nonAddPathRouteKeyIdentifier = ribSupport.createRouteListKey(NON_PATH_ID_VALUE, routeKey);
+    }
+
+    public StaleBestPathRoute(final RIBSupport<C, S, R, I> ribSupport, final String routeKey) {
+        this(ribSupport, routeKey, Collections.singletonList(NON_PATH_ID_VALUE),
+                Collections.emptyList(), true);
+    }
+
+    public I getNonAddPathRouteKeyIdentifier() {
+        return this.nonAddPathRouteKeyIdentifier;
+    }
+
+    /**
+     * Route Identifier List of withdrawn routes to advertize peers supporting additional Path.
+     *
+     * @return Route Identifier List
+     */
+    public List<I> getStaleRouteKeyIdentifiers() {
+        return this.staleRouteKeyIdentifier;
+    }
+
+    /**
+     * Route Identifier List of withdrawn routes to advertize peers supporting additional Path.
+     *
+     * @return Route Identifier List
+     */
+    public List<I> getAddPathRouteKeyIdentifiers() {
+        return this.addPathRouteKeyIdentifier;
+    }
+
+    /**
+     * Route Identifier of withdrawn routes to advertize peers no supporting additional Path.
+     *
+     * @return Route Identifier
+     */
+    public boolean isNonAddPathBestPathNew() {
+        return this.isNonAddPathBestPathNew;
+    }
+}