*/
package org.opendaylight.protocol.bgp.mode.impl.base;
-import com.google.common.primitives.UnsignedInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import javax.annotation.concurrent.NotThreadSafe;
import org.opendaylight.protocol.bgp.mode.api.RouteEntry;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
+import org.opendaylight.protocol.bgp.rib.spi.RouterId;
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.message.rev180329.path.attributes.Attributes;
-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;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-@NotThreadSafe
-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];
+final class BaseRouteEntry<C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+ implements RouteEntry<C, S> {
+ private static final class Stale extends StaleBestPathRoute {
+ Stale(final NodeIdentifierWithPredicates nonAddPathRouteKeyIdentifier) {
+ super(nonAddPathRouteKeyIdentifier);
+ }
- private OffsetMap offsets = OffsetMap.EMPTY;
- private R[] values = (R[]) EMPTY_VALUES;
- private BaseBestPath bestPath;
- private BaseBestPath removedBestPath;
+ @Override
+ public List<NodeIdentifierWithPredicates> getStaleRouteKeyIdentifiers() {
+ return Collections.singletonList(getNonAddPathRouteKeyIdentifier());
+ }
+
+ @Override
+ public List<NodeIdentifierWithPredicates> getAddPathRouteKeyIdentifiers() {
+ return Collections.emptyList();
+ }
- BaseRouteEntry() {
+ @Override
+ public boolean isNonAddPathBestPathNew() {
+ return true;
+ }
}
+ private static final Logger LOG = LoggerFactory.getLogger(BaseRouteEntry.class);
+ private static final MapEntryNode[] EMPTY_VALUES = new MapEntryNode[0];
+
+ private RouterIdOffsets offsets = RouterIdOffsets.EMPTY;
+ private MapEntryNode[] values = EMPTY_VALUES;
+ private BaseBestPath bestPath = null;
+ private BaseBestPath removedBestPath;
+
@Override
- public boolean removeRoute(final UnsignedInteger routerId, final long remotePathId) {
- final int offset = this.offsets.offsetOf(routerId);
- this.values = this.offsets.removeValue(this.values, offset, (R[]) EMPTY_VALUES);
- this.offsets = this.offsets.without(routerId);
- return this.offsets.isEmpty();
+ public boolean removeRoute(final RouterId routerId, final Uint32 remotePathId) {
+ final int offset = offsets.offsetOf(routerId);
+ values = offsets.removeValue(values, offset, EMPTY_VALUES);
+ offsets = offsets.without(routerId);
+ return offsets.isEmpty();
}
- private R createRoute(final RIBSupport<C, S, R, I> ribSup, final String routeKey, final long pathId,
- final BaseBestPath path) {
- final R route = this.offsets.getValue(this.values, this.offsets.offsetOf(path.getRouterId()));
- return ribSup.createRoute(route, routeKey, pathId, path.getAttributes());
+ private MapEntryNode createRoute(final RIBSupport<C, S> ribSup, final String routeKey) {
+ final MapEntryNode route = offsets.getValue(values, offsets.offsetOf(bestPath.getRouterId()));
+ return ribSup.createRoute(route, ribSup.createRouteListArgument(routeKey), bestPath.getAttributes());
}
@Override
- public boolean selectBest(final long localAs) {
+ public boolean selectBest(final RIBSupport<C, S> ribSupport, final long localAs) {
/*
* FIXME: optimize flaps by making sure we consider stability of currently-selected route.
*/
final BasePathSelector selector = new BasePathSelector(localAs);
// Select the best route.
- for (int i = 0; i < this.offsets.size(); ++i) {
- final UnsignedInteger routerId = this.offsets.getRouterKey(i);
- final Attributes attributes = this.offsets.getValue(this.values, i).getAttributes();
+ for (int i = 0; i < offsets.size(); ++i) {
+ final RouterId routerId = offsets.getKey(i);
+ final ContainerNode attributes = ribSupport.extractAttributes(offsets.getValue(values, i));
LOG.trace("Processing router id {} attributes {}", routerId, attributes);
selector.processPath(routerId, attributes);
}
// Get the newly-selected best path.
final BaseBestPath newBestPath = selector.result();
- final boolean modified = newBestPath == null || !newBestPath.equals(this.bestPath);
+ final boolean modified = newBestPath == null || !newBestPath.equals(bestPath);
if (modified) {
- if (this.offsets.isEmpty()) {
- this.removedBestPath = this.bestPath;
+ if (offsets.isEmpty()) {
+ removedBestPath = bestPath;
}
- LOG.trace("Previous best {}, current best {}", this.bestPath, newBestPath);
- this.bestPath = newBestPath;
+ LOG.trace("Previous best {}, current best {}", bestPath, newBestPath);
+ bestPath = newBestPath;
}
return modified;
}
@Override
- public int addRoute(final UnsignedInteger routerId, final long remotePathId, final R route) {
- int offset = this.offsets.offsetOf(routerId);
+ public int addRoute(final RouterId routerId, final Uint32 remotePathId, final MapEntryNode route) {
+ int offset = offsets.offsetOf(routerId);
if (offset < 0) {
- final OffsetMap newOffsets = this.offsets.with(routerId);
+ final RouterIdOffsets newOffsets = offsets.with(routerId);
offset = newOffsets.offsetOf(routerId);
- this.values = newOffsets.expand(this.offsets, this.values, offset);
- this.offsets = newOffsets;
+ values = newOffsets.expand(offsets, values, offset);
+ offsets = newOffsets;
}
- this.offsets.setValue(this.values, offset, route);
+ offsets.setValue(values, offset, route);
LOG.trace("Added route {} from {}", route, routerId);
return offset;
}
@Override
- public Optional<StaleBestPathRoute<C, S, R, I>> removeStalePaths(final RIBSupport<C, S, R, I> ribSupport,
- final String routeKey) {
- if (this.removedBestPath == null) {
+ public Optional<StaleBestPathRoute> removeStalePaths(final RIBSupport<C, S> ribSupport, final String routeKey) {
+ if (removedBestPath == null) {
return Optional.empty();
}
- final StaleBestPathRoute<C, S, R, I> stale = new StaleBestPathRoute<>(ribSupport, routeKey);
- this.removedBestPath = null;
- return Optional.of(stale);
+ removedBestPath = null;
+ return Optional.of(new Stale(ribSupport.createRouteListArgument(routeKey)));
}
@Override
- public List<AdvertizedRoute<C, S, R, I>> newBestPaths(final RIBSupport<C, S, R, I> ribSupport,
- final String routeKey) {
- if (this.bestPath == null) {
+ public List<AdvertizedRoute<C, S>> newBestPaths(final RIBSupport<C, S> ribSupport, final String routeKey) {
+ if (bestPath == null) {
return Collections.emptyList();
}
- 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(), this.bestPath.isDepreferenced());
+ final MapEntryNode route = createRoute(ribSupport, routeKey);
+ final AdvertizedRoute<C, S> adv = new AdvertizedRoute<>(ribSupport, route, bestPath.getAttributes(),
+ bestPath.getPeerId(), bestPath.isDepreferenced());
LOG.trace("Selected best route {}", route);
return Collections.singletonList(adv);
}
@Override
- public List<ActualBestPathRoutes<C, S, R, I>> actualBestPaths(final RIBSupport<C, S, R, I> ribSupport,
+ public List<ActualBestPathRoutes<C, S>> actualBestPaths(final RIBSupport<C, S> ribSupport,
final RouteEntryInfo entryInfo) {
- if (this.bestPath == null) {
+ if (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(), this.bestPath.isDepreferenced()));
+ final MapEntryNode route = createRoute(ribSupport, entryInfo.getRouteKey());
+ return Collections.singletonList(new ActualBestPathRoutes<>(ribSupport, route, bestPath.getPeerId(),
+ bestPath.getAttributes(), bestPath.isDepreferenced()));
}
}
\ No newline at end of file