import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.PEER_NID;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.FluentFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.MoreExecutors;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.checkerframework.checker.lock.qual.GuardedBy;
import org.eclipse.jdt.annotation.Nullable;
-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.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteOperations;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
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.spi.entry.RouteEntryDependenciesContainer;
import org.opendaylight.protocol.bgp.rib.spi.entry.RouteKeyIdentifier;
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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.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.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;
-abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImportParameters, TransactionChainListener,
- Peer, PeerTransactionChain {
+abstract class AbstractPeer extends BGPPeerStateImpl implements BGPRouteEntryImportParameters, Peer,
+ PeerTransactionChain, DOMTransactionChainListener {
private static final Logger LOG = LoggerFactory.getLogger(AbstractPeer.class);
- protected final RIB rib;
- final String name;
- final PeerRole peerRole;
+
+ final RTCClientRouteCache rtCache = new RTCClientRouteCache();
+ final RIB rib;
+
private final ClusterIdentifier clusterId;
+ private final PeerRole peerRole;
private final AsNumber localAs;
+ private final String name;
+
+ // FIXME: revisit locking here to improve concurrency:
+ // -- identifiers, peerId are a shared resource
+ // -- domChain seems to really be 'ribInChain', accessed from netty thread
+ // -- ribOutChain is accessed from LocRibWriter
+ // hence we want to use the two chains concurrently. The problem is their lifecycle in response to errors,
+ // which needs figuring out.
@GuardedBy("this")
private DOMTransactionChain domChain;
@GuardedBy("this")
- BindingTransactionChain bindingChain;
- byte[] rawIdentifier;
- @GuardedBy("this")
PeerId peerId;
+
+ // These seem to be separate
+ @GuardedBy("this")
+ @VisibleForTesting
+ DOMTransactionChain ribOutChain;
+ @GuardedBy("this")
private FluentFuture<? extends CommitInfo> submitted;
- RTCClientRouteCache rtCache = new RTCClientRouteCache();
AbstractPeer(
final RIB rib,
final PeerRole role,
final @Nullable ClusterIdentifier clusterId,
final @Nullable AsNumber localAs,
- final IpAddress neighborAddress,
+ final IpAddressNoZone neighborAddress,
final Set<TablesKey> afiSafisAdvertized,
final Set<TablesKey> afiSafisGracefulAdvertized,
final Map<TablesKey, Integer> afiSafisLlGracefulAdvertized) {
this.clusterId = clusterId;
this.localAs = localAs;
this.rib = rib;
- this.domChain = this.rib.createPeerDOMChain(this);
+ createDomChain();
}
AbstractPeer(
final String peerName,
final String groupId,
final PeerRole role,
- final IpAddress neighborAddress,
+ final IpAddressNoZone neighborAddress,
final Set<TablesKey> afiSafisGracefulAdvertized) {
this(rib, peerName, groupId, role, null, null, neighborAddress,
rib.getLocalTablesKeys(), afiSafisGracefulAdvertized, Collections.emptyMap());
return CommitInfo.emptyFluentFuture();
}
LOG.info("Closed per Peer {} removed", peerPath);
- final DOMDataWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
+ final DOMDataTreeWriteTransaction tx = this.domChain.newWriteOnlyTransaction();
tx.delete(LogicalDatastoreType.OPERATIONAL, peerPath);
final FluentFuture<? extends CommitInfo> future = tx.commit();
future.addCallback(new FutureCallback<CommitInfo>() {
return this.peerRole;
}
- @Override
- public final synchronized byte[] getRawIdentifier() {
- return Arrays.copyOf(this.rawIdentifier, this.rawIdentifier.length);
- }
-
@Override
public final PeerRole getFromPeerRole() {
return getRole();
}
@Override
- public final void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
+ public final void onTransactionChainSuccessful(final DOMTransactionChain chain) {
LOG.debug("Transaction chain {} successful.", chain);
}
}
@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 initializeRibOut(final RouteEntryDependenciesContainer entryDep,
- final List<ActualBestPathRoutes<C, S, R, I>> routesToStore) {
- if (this.bindingChain == null) {
+ public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+ void initializeRibOut(final RouteEntryDependenciesContainer entryDep,
+ final List<ActualBestPathRoutes<C, S>> routesToStore) {
+ if (this.ribOutChain == 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 RIBSupport<C, S> ribSupport = entryDep.getRIBSupport();
+ final YangInstanceIdentifier tableRibout = getRibOutIId(ribSupport.tablesKey());
+ final boolean addPathSupported = supportsAddPathSupported(ribSupport.getTablesKey());
- final WriteTransaction tx = this.bindingChain.newWriteOnlyTransaction();
- for (final ActualBestPathRoutes<C, S, R, I> initializingRoute : routesToStore) {
- if (!supportsLLGR() && initializingRoute.isDepreferenced()) {
+ final DOMDataTreeWriteTransaction tx = this.ribOutChain.newWriteOnlyTransaction();
+ for (final ActualBestPathRoutes<C, S> initRoute : routesToStore) {
+ if (!supportsLLGR() && initRoute.isDepreferenced()) {
// Stale Long-lived Graceful Restart routes should not be propagated
continue;
}
- final PeerId fromPeerId = initializingRoute.getFromPeerId();
+ final PeerId fromPeerId = initRoute.getFromPeerId();
if (!filterRoutes(fromPeerId, ribSupport.getTablesKey())) {
continue;
}
- final R route = initializingRoute.getRoute();
+ final MapEntryNode route = initRoute.getRoute();
final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
if (fromPeer == null) {
- LOG.debug("Failed to acquire peer structure for {}, ignoring route {}", fromPeerId, initializingRoute);
+ LOG.debug("Failed to acquire peer structure for {}, ignoring route {}", fromPeerId, initRoute);
continue;
}
- final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
- this, route.getRouteKey(), this.rtCache);
-
- final Optional<Attributes> effAttr = entryDep.getRoutingPolicies()
- .applyExportPolicies(routeEntry, initializingRoute.getAttributes(), entryDep.getAfiSafType());
- final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
-
- effAttr.ifPresent(attributes
- -> storeRoute(ribSupport, addPathSupported, tableRibout, initializingRoute, route, attributes, tx));
+ final YangInstanceIdentifier routePath = createRoutePath(ribSupport, tableRibout, initRoute,
+ addPathSupported);
+ applyExportPolicy(entryDep, fromPeerId, route, routePath, initRoute.getAttributes()).ifPresent(
+ attributes -> storeRoute(ribSupport, initRoute, route, routePath, attributes, tx));
}
final FluentFuture<? extends CommitInfo> future = tx.commit();
}
@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, final List<AdvertizedRoute<C, S, R, I>> newRoutes) {
- if (this.bindingChain == null) {
+ public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+ void refreshRibOut(final RouteEntryDependenciesContainer entryDep,
+ final List<StaleBestPathRoute> staleRoutes, final List<AdvertizedRoute<C, S>> newRoutes) {
+ if (this.ribOutChain == 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();
+ final DOMDataTreeWriteTransaction tx = this.ribOutChain.newWriteOnlyTransaction();
+ final RIBSupport<C, S> ribSupport = entryDep.getRIBSupport();
deleteRouteRibOut(ribSupport, staleRoutes, tx);
installRouteRibOut(entryDep, newRoutes, tx);
}
@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 reEvaluateAdvertizement(
- final RouteEntryDependenciesContainer entryDep,
- final List<ActualBestPathRoutes<C, S, R, I>> routesToStore) {
- if (this.bindingChain == null) {
+ public final synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+ void reEvaluateAdvertizement(final RouteEntryDependenciesContainer entryDep,
+ final List<ActualBestPathRoutes<C, S>> routesToStore) {
+ if (this.ribOutChain == 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 RIBSupport<C, S> ribSupport = entryDep.getRIBSupport();
+ final NodeIdentifierWithPredicates tk = ribSupport.tablesKey();
+ final boolean addPathSupported = supportsAddPathSupported(ribSupport.getTablesKey());
- final WriteTransaction tx = this.bindingChain.newWriteOnlyTransaction();
- for (final ActualBestPathRoutes<C, S, R, I> actualBestRoute : routesToStore) {
+ final DOMDataTreeWriteTransaction tx = this.ribOutChain.newWriteOnlyTransaction();
+ for (final ActualBestPathRoutes<C, S> actualBestRoute : routesToStore) {
final PeerId fromPeerId = actualBestRoute.getFromPeerId();
if (!filterRoutes(fromPeerId, ribSupport.getTablesKey())) {
continue;
}
- final R route = actualBestRoute.getRoute();
- final Optional<Attributes> effAttr;
+ final YangInstanceIdentifier tableRibout = getRibOutIId(tk);
+ // Stale Long-lived Graceful Restart routes should not be propagated
if (supportsLLGR() || !actualBestRoute.isDepreferenced()) {
- final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
- final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
- this, route.getRouteKey(), this.rtCache);
- effAttr = entryDep.getRoutingPolicies()
- .applyExportPolicies(routeEntry, actualBestRoute.getAttributes(), entryDep.getAfiSafType());
- } else {
- // Stale Long-lived Graceful Restart routes should not be propagated
- effAttr = Optional.empty();
+ final YangInstanceIdentifier routePath = createRoutePath(ribSupport, tableRibout, actualBestRoute,
+ addPathSupported);
+ final MapEntryNode route = actualBestRoute.getRoute();
+ final Optional<ContainerNode> effAttr = applyExportPolicy(entryDep, fromPeerId, route, routePath,
+ actualBestRoute.getAttributes());
+ if (effAttr.isPresent()) {
+ storeRoute(ribSupport, actualBestRoute, route, routePath, effAttr.get(), tx);
+ continue;
+ }
}
- final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
- if (effAttr.isPresent()) {
- storeRoute(ribSupport, addPathSupported, tableRibout, actualBestRoute, route, effAttr.get(), tx);
- } else {
- deleteRoute(ribSupport, addPathSupported, tableRibout, actualBestRoute, tx);
- }
+ deleteRoute(ribSupport, addPathSupported, tableRibout, actualBestRoute, tx);
}
final FluentFuture<? extends CommitInfo> future = tx.commit();
}, 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();
+ private Optional<ContainerNode> applyExportPolicy(final RouteEntryDependenciesContainer entryDep,
+ final PeerId fromPeerId, final MapEntryNode route, final YangInstanceIdentifier routePath,
+ final ContainerNode attrs) {
+ final Peer fromPeer = entryDep.getPeerTracker().getPeer(fromPeerId);
+ final RIBSupport<?, ?> ribSupport = entryDep.getRIBSupport();
+ final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer, this,
+ ribSupport.extractRouteKey(route.getIdentifier()), this.rtCache);
+
+ final Attributes bindingAttrs = ribSupport.attributeFromContainerNode(attrs);
+ final Optional<Attributes> optExportAttrs = entryDep.getRoutingPolicies().applyExportPolicies(routeEntry,
+ bindingAttrs, entryDep.getAfiSafType());
+ if (optExportAttrs.isEmpty()) {
+ // Discards route
+ return Optional.empty();
+ }
+ final Attributes exportAttrs = optExportAttrs.orElseThrow();
+
+ // If the same object is returned we can just reuse 'attrs' instead. Since we are in control of lifecycle here,
+ // we use identity comparison, as equality is too costly for the common case -- assuming export policy will not
+ // churn objects when it does not have to
+ return Optional.of(exportAttrs == bindingAttrs ? attrs
+ : ribSupport.attributeToContainerNode(routePath.node(ribSupport.routeAttributesIdentifier()), exportAttrs));
+ }
+
+ private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>> void installRouteRibOut(
+ final RouteEntryDependenciesContainer entryDep, final List<AdvertizedRoute<C, S>> routes,
+ final DOMDataTreeWriteOperations tx) {
+ final RIBSupport<C, S> ribSupport = entryDep.getRIBSupport();
+ final TablesKey tk = ribSupport.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);
- final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout = getRibOutIId(tk);
+ final YangInstanceIdentifier tableRibout = getRibOutIId(ribSupport.tablesKey());
- for (final AdvertizedRoute<C, S, R, I> advRoute : routes) {
+ for (final AdvertizedRoute<C, S> advRoute : routes) {
final PeerId fromPeerId = advRoute.getFromPeerId();
if (!filterRoutes(fromPeerId, tk) || !advRoute.isFirstBestPath() && !addPathSupported) {
continue;
continue;
}
- final R route = advRoute.getRoute();
- Optional<Attributes> effAttr = Optional.empty();
final Peer fromPeer = peerTracker.getPeer(fromPeerId);
- final Attributes attributes = advRoute.getAttributes();
+ final ContainerNode attributes = advRoute.getAttributes();
if (fromPeer != null && attributes != null) {
- final BGPRouteEntryExportParameters routeEntry = new BGPRouteEntryExportParametersImpl(fromPeer,
- this, route.getRouteKey(), this.rtCache);
- effAttr = routingPolicies.applyExportPolicies(routeEntry, attributes, entryDep.getAfiSafType());
+ final YangInstanceIdentifier routePath = createRoutePath(ribSupport, tableRibout, advRoute,
+ addPathSupported);
+ final MapEntryNode route = advRoute.getRoute();
+ applyExportPolicy(entryDep, fromPeerId, route, routePath, attributes).ifPresent(
+ attrs -> storeRoute(ribSupport, advRoute, route, routePath, attrs, tx));
}
- effAttr.ifPresent(attributes1
- -> storeRoute(ribSupport, addPathSupported, tableRibout, advRoute, route, attributes1, tx));
}
}
- 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);
+ private static YangInstanceIdentifier createRoutePath(final RIBSupport<?, ?> ribSupport,
+ final YangInstanceIdentifier tableRibout, final RouteKeyIdentifier advRoute, final boolean withAddPath) {
+ return ribSupport.createRouteIdentifier(tableRibout,
+ withAddPath ? advRoute.getAddPathRouteKeyIdentifier() : advRoute.getNonAddPathRouteKeyIdentifier());
+ }
+
+ private synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+ void deleteRouteRibOut(final RIBSupport<C, S> ribSupport, final List<StaleBestPathRoute> staleRoutesIid,
+ final DOMDataTreeWriteOperations tx) {
+ final YangInstanceIdentifier tableRibout = getRibOutIId(ribSupport.tablesKey());
+ final boolean addPathSupported = supportsAddPathSupported(ribSupport.getTablesKey());
staleRoutesIid.forEach(staleRouteIid
-> removeRoute(ribSupport, addPathSupported, tableRibout, staleRouteIid, tx));
}
- private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
- R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>> void storeRoute(
- final RIBSupport<C, S, R, I> ribSupport, final boolean addPathSupported,
- final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout,
- final RouteKeyIdentifier<R, I> advRoute, final R route, final Attributes effAttr,
- final WriteTransaction tx) {
- final InstanceIdentifier<R> ribOut;
- final I newKey;
- if (!addPathSupported) {
- ribOut = ribSupport.createRouteIdentifier(tableRibout, advRoute.getNonAddPathRouteKeyIdentifier());
- newKey = ribSupport.createRouteListKey(route.getRouteKey());
- } else {
- ribOut = ribSupport.createRouteIdentifier(tableRibout, advRoute.getAddPathRouteKeyIdentifier());
- newKey = ribSupport.createRouteListKey(route.getPathId(), route.getRouteKey());
- }
-
- final R newRoute = ribSupport.createRoute(route, newKey, effAttr);
+ private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>> void storeRoute(
+ final RIBSupport<C, S> ribSupport, final RouteKeyIdentifier advRoute, final MapEntryNode route,
+ final YangInstanceIdentifier routePath, final ContainerNode effAttr, final DOMDataTreeWriteOperations tx) {
LOG.debug("Write advRoute {} to peer AdjRibsOut {}", advRoute, getPeerId());
- tx.put(LogicalDatastoreType.OPERATIONAL, ribOut, newRoute);
+ tx.put(LogicalDatastoreType.OPERATIONAL, routePath, ribSupport.createRoute(route,
+ (NodeIdentifierWithPredicates) routePath.getLastPathArgument(), effAttr));
}
- 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 removeRoute(final RIBSupport<C, S, R, I> ribSupport,
- final boolean addPathSupported, final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout,
- final StaleBestPathRoute<C, S, R, I> staleRouteIid, final WriteTransaction tx) {
+ private synchronized <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>>
+ void removeRoute(final RIBSupport<C, S> ribSupport, final boolean addPathSupported,
+ final YangInstanceIdentifier tableRibout, final StaleBestPathRoute staleRouteIid,
+ final DOMDataTreeWriteOperations tx) {
if (addPathSupported) {
- List<I> staleRoutesIId = staleRouteIid.getAddPathRouteKeyIdentifiers();
- for (final I id : staleRoutesIId) {
- final InstanceIdentifier<R> ribOutTarget = ribSupport.createRouteIdentifier(tableRibout, id);
+ List<NodeIdentifierWithPredicates> staleRoutesIId = staleRouteIid.getAddPathRouteKeyIdentifiers();
+ for (final NodeIdentifierWithPredicates id : staleRoutesIId) {
+ final YangInstanceIdentifier ribOutTarget = ribSupport.createRouteIdentifier(tableRibout, id);
LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, getPeerId());
tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
}
if (!staleRouteIid.isNonAddPathBestPathNew()) {
return;
}
- final InstanceIdentifier<R> ribOutTarget = ribSupport.createRouteIdentifier(tableRibout,
+ final YangInstanceIdentifier ribOutTarget = ribSupport.createRouteIdentifier(tableRibout,
staleRouteIid.getNonAddPathRouteKeyIdentifier());
LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, getPeerId());
tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
}
// FIXME: why is this different from removeRoute()?
- private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>,
- R extends Route & ChildOf<? super S> & Identifiable<I>, I extends Identifier<R>> void deleteRoute(
- final RIBSupport<C, S, R, I> ribSupport, final boolean addPathSupported,
- final KeyedInstanceIdentifier<Tables, TablesKey> tableRibout,
- final AbstractAdvertizedRoute<C, S , R, I> advRoute, final WriteTransaction tx) {
- final InstanceIdentifier<R> ribOutTarget = ribSupport.createRouteIdentifier(tableRibout,
+ private <C extends Routes & DataObject & ChoiceIn<Tables>, S extends ChildOf<? super C>> void deleteRoute(
+ final RIBSupport<C, S> ribSupport, final boolean addPathSupported,
+ final YangInstanceIdentifier tableRibout, final AbstractAdvertizedRoute<C, S> advRoute,
+ final DOMDataTreeWriteOperations tx) {
+ final YangInstanceIdentifier ribOutTarget = ribSupport.createRouteIdentifier(tableRibout,
addPathSupported ? advRoute.getAddPathRouteKeyIdentifier() : advRoute.getNonAddPathRouteKeyIdentifier());
LOG.trace("Removing {} from transaction for peer {}", ribOutTarget, getPeerId());
tx.delete(LogicalDatastoreType.OPERATIONAL, ribOutTarget);
}
- final synchronized void releaseBindingChain() {
- if (this.submitted != null) {
- try {
- this.submitted.get();
- } catch (final InterruptedException | ExecutionException throwable) {
- LOG.error("Write routes failed", throwable);
+ final synchronized void releaseRibOutChain(final boolean isWaitForSubmitted) {
+ if (isWaitForSubmitted) {
+ 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) {
+ if (this.ribOutChain != null) {
LOG.info("Closing peer chain {}", getPeerId());
- this.bindingChain.close();
- this.bindingChain = null;
+ this.ribOutChain.close();
+ this.ribOutChain = null;
+ }
+ }
+
+ final synchronized void createDomChain() {
+ if (this.domChain == null) {
+ LOG.info("Creating DOM peer chain {}", getPeerId());
+ this.domChain = this.rib.createPeerDOMChain(this);
}
}