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();
}
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
* 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.
*
* @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
*/
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;
* 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;
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;
}
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);
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
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
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
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
}
@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
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;
}
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
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 {
throw new UnsupportedOperationException();
}
- public static PathSelectionMode createBestPathSelectionStrategy(final BGPPeerTracker peerTracker) {
- return new BasePathSelection(peerTracker);
+ public static PathSelectionMode createBestPathSelectionStrategy() {
+ return new BasePathSelection();
}
}
*/
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());
}
}
@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);
}
@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
+++ /dev/null
-/*
- * 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());
- }
-}
*/
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,
this.clusterId = clusterId;
this.localAs = localAs;
this.rib = rib;
+ this.domChain = this.rib.createPeerDOMChain(this);
}
AbstractPeer(
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() {
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;
+ }
+ }
}
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;
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;
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);
* @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());
}
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,
}
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);
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);
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);
}
}, MoreExecutors.directExecutor());
}
+
+ void releaseChain() {
+ if (this.submitted != null) {
+ try {
+ this.submitted.get();
+ } catch (final InterruptedException | ExecutionException throwable) {
+ LOG.error("Write routes failed", throwable);
+ }
+ }
+ }
}
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;
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;
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);
}
}
*/
@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());
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;
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;
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;
@GuardedBy("this")
private BGPSession session;
@GuardedBy("this")
- private final DOMTransactionChain chain;
- @GuardedBy("this")
private AdjRibInWriter ribWriter;
@GuardedBy("this")
private EffectiveRibInWriter effRibInWriter;
this.tableTypeRegistry = requireNonNull(tableTypeRegistry);
this.rib = requireNonNull(rib);
this.rpcRegistry = rpcRegistry;
- this.chain = rib.createPeerDOMChain(this);
}
BGPPeer(
}
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;
}
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);
}
}
}
- 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)) {
@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();
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) {
@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
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() {
public synchronized List<Peer> getPeers() {
return this.peersList;
}
+
+ @Override
+ public synchronized List<Peer> getNonInternalPeers() {
+ return this.peersFilteredList;
+ }
}
\ No newline at end of file
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;
private final BGPRibRoutingPolicy ribPolicies;
private final BGPRouteEntryImportParameters peerImportParameters;
private final BGPTableTypeRegistryConsumer tableTypeRegistry;
+ @GuardedBy("this")
+ private FluentFuture<? extends CommitInfo> submitted;
EffectiveRibInWriter(
final BGPRouteEntryImportParameters peer,
}
}
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");
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;
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;
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;
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();
@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,
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,
}
@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);
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());
}
@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();
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);
}
}
/*
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);
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;
}
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);
}
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);
}
}
return this.totalPathsCounter.longValue();
}
- public TablesKey getTableKey() {
+ TablesKey getTableKey() {
return this.tk;
}
}
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;
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;
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")
final DOMDataBroker domDataBroker,
final DataBroker dataBroker,
final BGPRibRoutingPolicy ribPolicies,
- final BGPPeerTracker bgpPeerTracker,
final List<BgpTableType> localTables,
final Map<TablesKey, PathSelectionMode> bestPathSelectionStrategies
) {
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);
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());
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(
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;
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);
}
@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() {
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;
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;
}
public BGPRibRoutingPolicy getRoutingPolicies() {
return this.routingPolicies;
}
+
+ @Override
+ public BGPPeerTracker getPeerTracker() {
+ return this.peerTracker;
+ }
}
}
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);
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);
}
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));
this.domBroker,
this.dataBroker,
ribPolicy,
- peerTracker,
toTableTypes(this.afiSafi, tableTypeRegistry),
pathSelectionModes);
}
--- /dev/null
+/*
+ * 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();
+}
private NioEventLoopGroup boss;
private org.opendaylight.protocol.bgp.inet.BGPActivator inetActivator;
protected StrictBGPPeerRegistry serverRegistry;
- protected final BGPPeerTrackerImpl peerTracker = new BGPPeerTrackerImpl();
protected CodecsRegistryImpl codecsRegistry;
@Before
@Mock
private ClusterSingletonServiceProvider clusterSingletonServiceProvider;
- private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl();
-
private static ModuleInfoBackedContext createClassLoadingStrategy() {
final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
try {
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);
}
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());
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));
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());
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;
private RIBSupportContextRegistry registry;
@Mock
private RIBSupportContext context;
+ @Mock
+ private PeerTransactionChain ptc;
private AdjRibInWriter writer;
@Before
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,
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;
@Mock
private BGPDispatcher dispatcher;
- private final BGPPeerTracker peerTracker = new BGPPeerTrackerImpl();
private CodecsRegistryImpl codecsRegistry;
@Before
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());
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);
@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());
@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());
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;
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
.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);
*/
@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();
}
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.
*/
@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);
}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
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;
* @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.
*/
@Nonnull
BGPRibRoutingPolicy getRoutingPolicies();
+
+ @Nonnull
+ BGPPeerTracker getPeerTracker();
}
--- /dev/null
+/*
+ * 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;
+ }
+}