package org.opendaylight.protocol.bgp.rib.impl;
import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
+import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.ADJRIBIN_ATTRIBUTES_AID;
import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.ADJRIBIN_NID;
import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.ATTRIBUTES_NID;
import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.EFFRIBIN_NID;
+import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.LLGR_STALE_NID;
import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.ROUTES_NID;
import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.TABLES_NID;
+import static org.opendaylight.protocol.bgp.rib.spi.RIBNodeIdentifiers.UPTODATE_NID;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
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.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeListener;
-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.checkerframework.checker.lock.qual.GuardedBy;
+import org.checkerframework.checker.lock.qual.Holding;
import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.ClusteredDOMDataTreeChangeListener;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
import org.opendaylight.protocol.bgp.parser.impl.message.update.CommunityUtil;
import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
import org.opendaylight.protocol.bgp.rib.impl.spi.RibOutRefresh;
import org.opendaylight.protocol.bgp.rib.impl.state.peer.PrefixesInstalledCounters;
import org.opendaylight.protocol.bgp.rib.impl.state.peer.PrefixesReceivedCounters;
+import org.opendaylight.protocol.bgp.rib.spi.RIBNormalizedNodes;
import org.opendaylight.protocol.bgp.rib.spi.RIBSupport;
import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRibRoutingPolicy;
import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryImportParameters;
import org.opendaylight.protocol.bgp.route.targetcontrain.spi.ClientRouteTargetContrainCache;
import org.opendaylight.protocol.bgp.route.targetcontrain.spi.RouteTargetMembeshipUtil;
-import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
-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.message.rev180329.path.attributes.attributes.Communities;
+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.message.rev200120.path.attributes.attributes.Communities;
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.rib.TablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.route.target.constrain.rev180618.RouteTargetConstrainSubsequentAddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.route.target.constrain.rev180618.route.target.constrain.routes.route.target.constrain.routes.RouteTargetConstrainRoute;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv4AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.Ipv6AddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.MplsLabeledVpnSubsequentAddressFamily;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv6AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.MplsLabeledVpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.RouteTarget;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
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.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
+import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* 2) check if a route is admissible based on attributes attached to it, as well as the
* advertising peer's role
* 3) output admitting routes with edited attributes into /bgp-rib/rib/peer/effective-rib-in/tables/routes
+ *
+ * <p>
+ * This class is NOT thread-safe.
*/
-@NotThreadSafe
final class EffectiveRibInWriter implements PrefixesReceivedCounters, PrefixesInstalledCounters,
AutoCloseable, ClusteredDOMDataTreeChangeListener {
private static final Logger LOG = LoggerFactory.getLogger(EffectiveRibInWriter.class);
- private static final TablesKey IVP4_VPN_TABLE_KEY = new TablesKey(Ipv4AddressFamily.class,
- MplsLabeledVpnSubsequentAddressFamily.class);
- private static final TablesKey IVP6_VPN_TABLE_KEY = new TablesKey(Ipv6AddressFamily.class,
- MplsLabeledVpnSubsequentAddressFamily.class);
- private static final ImmutableList<Communities> STALE_LLGR_COMMUNUTIES = ImmutableList.of(
- StaleCommunities.STALE_LLGR);
+ private static final TablesKey IVP4_VPN_TABLE_KEY =
+ new TablesKey(Ipv4AddressFamily.VALUE, MplsLabeledVpnSubsequentAddressFamily.VALUE);
+ private static final TablesKey IVP6_VPN_TABLE_KEY =
+ new TablesKey(Ipv6AddressFamily.VALUE, MplsLabeledVpnSubsequentAddressFamily.VALUE);
+ private static final ImmutableList<Communities> STALE_LLGR_COMMUNUTIES =
+ ImmutableList.of(StaleCommunities.STALE_LLGR);
private static final Attributes STALE_LLGR_ATTRIBUTES = new org.opendaylight.yang.gen.v1.urn.opendaylight.params
- .xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder()
+ .xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder()
.setCommunities(STALE_LLGR_COMMUNUTIES)
.build();
private static final ChoiceNode EMPTY_ROUTES = Builders.choiceBuilder().withNodeIdentifier(ROUTES_NID).build();
final BGPTableTypeRegistryConsumer tableTypeRegistry,
final List<RouteTarget> rtMemberships,
final ClientRouteTargetContrainCache rtCache) {
- this.registry = requireNonNull(rib.getRibSupportContext());
+ registry = requireNonNull(rib.getRibSupportContext());
this.chain = requireNonNull(chain);
this.peerIId = requireNonNull(peerIId);
- this.effRibTables = this.peerIId.node(EFFRIBIN_NID);
- this.prefixesInstalled = buildPrefixesTables(tables);
- this.prefixesReceived = buildPrefixesTables(tables);
- this.ribPolicies = requireNonNull(rib.getRibPolicies());
- this.service = requireNonNull(rib.getService());
+ effRibTables = this.peerIId.node(EFFRIBIN_NID);
+ prefixesInstalled = buildPrefixesTables(tables);
+ prefixesReceived = buildPrefixesTables(tables);
+ ribPolicies = requireNonNull(rib.getRibPolicies());
+ service = requireNonNull(rib.getService());
this.tableTypeRegistry = requireNonNull(tableTypeRegistry);
- this.peerImportParameters = peer;
+ peerImportParameters = peer;
this.rtMemberships = rtMemberships;
this.rtCache = rtCache;
- this.vpnTableRefresher = rib;
+ vpnTableRefresher = rib;
}
public void init() {
final DOMDataTreeIdentifier treeId = new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL,
- this.peerIId.node(ADJRIBIN_NID).node(TABLES_NID));
- LOG.debug("Registered Effective RIB on {}", this.peerIId);
- this.reg = requireNonNull(this.service).registerDataTreeChangeListener(treeId, this);
+ peerIId.node(ADJRIBIN_NID).node(TABLES_NID));
+ LOG.debug("Registered Effective RIB on {}", peerIId);
+ reg = requireNonNull(service).registerDataTreeChangeListener(treeId, this);
}
private static Map<TablesKey, LongAdder> buildPrefixesTables(final Set<TablesKey> tables) {
}
@Override
- public synchronized void onDataTreeChanged(@Nonnull final Collection<DataTreeCandidate> changes) {
- if (this.chain == null) {
+ public synchronized void onInitialData() {
+ // FIXME: update as if root was deleted
+ }
+
+ @Override
+ public synchronized void onDataTreeChanged(final List<DataTreeCandidate> changes) {
+ if (chain == null) {
LOG.trace("Chain closed. Ignoring Changes : {}", changes);
return;
}
LOG.trace("Data changed called to effective RIB. Change : {}", changes);
- DOMDataWriteTransaction tx = null;
+ DOMDataTreeWriteTransaction tx = null;
for (final DataTreeCandidate tc : changes) {
final YangInstanceIdentifier rootPath = tc.getRootPath();
final DataTreeCandidateNode root = tc.getRootNode();
for (final DataTreeCandidateNode table : root.getChildNodes()) {
if (tx == null) {
- tx = this.chain.newWriteOnlyTransaction();
+ tx = chain.newWriteOnlyTransaction();
}
changeDataTree(tx, rootPath, root, table);
}
if (tx != null) {
final FluentFuture<? extends CommitInfo> future = tx.commit();
- this.submitted = future;
+ submitted = future;
future.addCallback(new FutureCallback<CommitInfo>() {
@Override
public void onSuccess(final CommitInfo result) {
}
//Refresh VPN Table if RT Memberships were updated
- if (this.rtMembershipsUpdated) {
- this.vpnTableRefresher.refreshTable(IVP4_VPN_TABLE_KEY, this.peerImportParameters.getFromPeerId());
- this.vpnTableRefresher.refreshTable(IVP6_VPN_TABLE_KEY, this.peerImportParameters.getFromPeerId());
- this.rtMembershipsUpdated = false;
+ if (rtMembershipsUpdated) {
+ vpnTableRefresher.refreshTable(IVP4_VPN_TABLE_KEY, peerImportParameters.getFromPeerId());
+ vpnTableRefresher.refreshTable(IVP6_VPN_TABLE_KEY, peerImportParameters.getFromPeerId());
+ rtMembershipsUpdated = false;
}
}
@Override
public synchronized void close() {
- if (this.reg != null) {
- this.reg.close();
- this.reg = null;
+ if (reg != null) {
+ reg.close();
+ reg = null;
}
- if (this.submitted != null) {
+ if (submitted != null) {
try {
- this.submitted.get();
+ submitted.get();
} catch (final InterruptedException | ExecutionException throwable) {
LOG.error("Write routes failed", throwable);
}
}
- if (this.chain != null) {
- this.chain.close();
- this.chain = null;
+ if (chain != null) {
+ chain.close();
+ chain = null;
}
- this.prefixesReceived.values().forEach(LongAdder::reset);
- this.prefixesInstalled.values().forEach(LongAdder::reset);
+ prefixesReceived.values().forEach(LongAdder::reset);
+ prefixesInstalled.values().forEach(LongAdder::reset);
}
@Override
public long getPrefixedReceivedCount(final TablesKey tablesKey) {
- final LongAdder counter = this.prefixesReceived.get(tablesKey);
+ final LongAdder counter = prefixesReceived.get(tablesKey);
if (counter == null) {
return 0;
}
@Override
public Set<TablesKey> getTableKeys() {
- return ImmutableSet.copyOf(this.prefixesReceived.keySet());
+ return ImmutableSet.copyOf(prefixesReceived.keySet());
}
@Override
public boolean isSupported(final TablesKey tablesKey) {
- return this.prefixesReceived.containsKey(tablesKey);
+ return prefixesReceived.containsKey(tablesKey);
}
@Override
public long getPrefixedInstalledCount(final TablesKey tablesKey) {
- final LongAdder counter = this.prefixesInstalled.get(tablesKey);
+ final LongAdder counter = prefixesInstalled.get(tablesKey);
if (counter == null) {
return 0;
}
@Override
public long getTotalPrefixesInstalled() {
- return this.prefixesInstalled.values().stream().mapToLong(LongAdder::longValue).sum();
+ return prefixesInstalled.values().stream().mapToLong(LongAdder::longValue).sum();
}
- @GuardedBy("this")
- private void changeDataTree(final DOMDataWriteTransaction tx, final YangInstanceIdentifier rootPath,
+ @Holding("this")
+ private void changeDataTree(final DOMDataTreeWriteTransaction tx, final YangInstanceIdentifier rootPath,
final DataTreeCandidateNode root, final DataTreeCandidateNode table) {
final PathArgument lastArg = table.getIdentifier();
verify(lastArg instanceof NodeIdentifierWithPredicates, "Unexpected type %s in path %s", lastArg.getClass(),
rootPath);
final NodeIdentifierWithPredicates tableKey = (NodeIdentifierWithPredicates) lastArg;
- final RIBSupportContext ribContext = this.registry.getRIBSupportContext(tableKey);
+ final RIBSupportContext ribContext = registry.getRIBSupportContext(tableKey);
if (ribContext == null) {
LOG.warn("Table {} is not supported, ignoring event", tableKey);
return;
}
}
- private void deleteTable(final DOMDataWriteTransaction tx, final RIBSupportContext ribContext,
+ private void deleteTable(final DOMDataTreeWriteTransaction tx, final RIBSupportContext ribContext,
final YangInstanceIdentifier effectiveTablePath, final DataTreeCandidateNode table) {
LOG.debug("Delete Effective Table {}", effectiveTablePath);
onDeleteTable(ribContext.getRibSupport(), effectiveTablePath, table.getDataBefore());
tx.delete(LogicalDatastoreType.OPERATIONAL, effectiveTablePath);
}
- private void modifyTable(final DOMDataWriteTransaction tx, final RIBSupportContext ribContext,
+ private void modifyTable(final DOMDataTreeWriteTransaction tx, final RIBSupportContext ribContext,
final YangInstanceIdentifier effectiveTablePath, final DataTreeCandidateNode table) {
LOG.debug("Modify Effective Table {}", effectiveTablePath);
- final DataTreeCandidateNode modifiedAttrs = table.getModifiedChild(ATTRIBUTES_NID);
- if (modifiedAttrs != null) {
- final Optional<NormalizedNode<?, ?>> attrsAfter = modifiedAttrs.getDataAfter();
+ final boolean wasLongLivedStale = isLongLivedStaleTable(table.getDataBefore());
+ final boolean longLivedStale = isLongLivedStaleTable(table.getDataAfter());
+ if (wasLongLivedStale != longLivedStale) {
+ LOG.debug("LLGR_STALE flag flipped {}, overwriting table {}", longLivedStale ? "ON" : "OFF",
+ effectiveTablePath);
+ writeTable(tx, ribContext, effectiveTablePath, table);
+ return;
+ }
+
+ table.getModifiedChild(ATTRIBUTES_NID).ifPresent(modifiedAttrs -> {
final YangInstanceIdentifier effAttrsPath = effectiveTablePath.node(ATTRIBUTES_NID);
- if (attrsAfter.isPresent()) {
- tx.put(LogicalDatastoreType.OPERATIONAL, effAttrsPath, attrsAfter.get());
+ final Optional<NormalizedNode> optAttrsAfter = modifiedAttrs.getDataAfter();
+ if (optAttrsAfter.isPresent()) {
+ tx.put(LogicalDatastoreType.OPERATIONAL, effAttrsPath,
+ effectiveAttributes(extractContainer(optAttrsAfter.orElseThrow())));
} else {
tx.delete(LogicalDatastoreType.OPERATIONAL, effAttrsPath);
}
- }
+ });
- final DataTreeCandidateNode modifiedRoutes = table.getModifiedChild(ROUTES_NID);
- if (modifiedRoutes != null) {
- final RIBSupport<?, ?, ?, ?> ribSupport = ribContext.getRibSupport();
+ table.getModifiedChild(ROUTES_NID).ifPresent(modifiedRoutes -> {
+ final RIBSupport<?, ?> ribSupport = ribContext.getRibSupport();
switch (modifiedRoutes.getModificationType()) {
case APPEARED:
case WRITE:
deleteRoutesBefore(tx, ribSupport, effectiveTablePath, modifiedRoutes);
// XXX: YANG Tools seems to have an issue stacking DELETE with child WRITE
tx.put(LogicalDatastoreType.OPERATIONAL, effectiveTablePath.node(ROUTES_NID), EMPTY_ROUTES);
- writeRoutesAfter(tx, ribSupport, effectiveTablePath, modifiedRoutes.getDataAfter());
+ writeRoutesAfter(tx, ribSupport, effectiveTablePath, modifiedRoutes.getDataAfter(), longLivedStale);
break;
case DELETE:
case DISAPPEARED:
break;
case SUBTREE_MODIFIED:
for (DataTreeCandidateNode modifiedRoute : ribSupport.changedRoutes(modifiedRoutes)) {
- processRoute(tx, ribSupport, effectiveTablePath, modifiedRoute);
+ processRoute(tx, ribSupport, effectiveTablePath, modifiedRoute, longLivedStale);
}
break;
case UNMODIFIED:
LOG.warn("Ignoring modified routes {}", modifiedRoutes);
break;
}
- }
+ });
}
- private void writeTable(final DOMDataWriteTransaction tx, final RIBSupportContext ribContext,
+ private void writeTable(final DOMDataTreeWriteTransaction tx, final RIBSupportContext ribContext,
final YangInstanceIdentifier effectiveTablePath, final DataTreeCandidateNode table) {
LOG.debug("Write Effective Table {}", effectiveTablePath);
onDeleteTable(ribContext.getRibSupport(), effectiveTablePath, table.getDataBefore());
- final Optional<NormalizedNode<?, ?>> maybeTableAfter = table.getDataAfter();
+ final Optional<NormalizedNode> maybeTableAfter = table.getDataAfter();
if (maybeTableAfter.isPresent()) {
- final MapEntryNode tableAfter = extractMapEntry(maybeTableAfter);
+ final NormalizedNode node = maybeTableAfter.orElseThrow();
+ verify(node instanceof MapEntryNode, "Expected MapEntryNode, got %s", node);
+ final MapEntryNode tableAfter = (MapEntryNode) node;
ribContext.createEmptyTableStructure(tx, effectiveTablePath);
- final Optional<DataContainerChild<?, ?>> maybeAttrsAfter = tableAfter.getChild(ATTRIBUTES_NID);
- if (maybeAttrsAfter.isPresent()) {
+ final DataContainerChild maybeAttrsAfter = tableAfter.childByArg(ATTRIBUTES_NID);
+ final boolean longLivedStale;
+ if (maybeAttrsAfter != null) {
final ContainerNode attrsAfter = extractContainer(maybeAttrsAfter);
- tx.put(LogicalDatastoreType.OPERATIONAL, effectiveTablePath.node(ATTRIBUTES_NID), attrsAfter);
+ longLivedStale = isLongLivedStale(attrsAfter);
+ tx.put(LogicalDatastoreType.OPERATIONAL, effectiveTablePath.node(ATTRIBUTES_NID),
+ effectiveAttributes(attrsAfter));
+ } else {
+ longLivedStale = false;
}
writeRoutesAfter(tx, ribContext.getRibSupport(), effectiveTablePath,
- NormalizedNodes.findNode(tableAfter, ROUTES_NID));
+ NormalizedNodes.findNode(tableAfter, ROUTES_NID), longLivedStale);
}
}
// Performs house-keeping when the contents of a table is deleted
- private void onDeleteTable(final RIBSupport<?, ?, ?, ?> ribSupport, final YangInstanceIdentifier effectiveTablePath,
- final Optional<NormalizedNode<?, ?>> tableBefore) {
+ private void onDeleteTable(final RIBSupport<?, ?> ribSupport, final YangInstanceIdentifier effectiveTablePath,
+ final Optional<NormalizedNode> tableBefore) {
// Routes are special in that we need to process the to keep our counters accurate
- final Optional<NormalizedNode<?, ?>> maybeRoutesBefore = findRoutesMap(ribSupport,
+ final Optional<NormalizedNode> maybeRoutesBefore = findRoutesMap(ribSupport,
NormalizedNodes.findNode(tableBefore, ROUTES_NID));
if (maybeRoutesBefore.isPresent()) {
- onRoutesDeleted(ribSupport, effectiveTablePath, extractMap(maybeRoutesBefore).getValue());
+ onRoutesDeleted(ribSupport, effectiveTablePath, extractMap(maybeRoutesBefore).body());
}
}
- private void deleteRoutesBefore(final DOMDataWriteTransaction tx, final RIBSupport<?, ?, ?, ?> ribSupport,
+ private void deleteRoutesBefore(final DOMDataTreeWriteTransaction tx, final RIBSupport<?, ?> ribSupport,
final YangInstanceIdentifier effectiveTablePath, final DataTreeCandidateNode modifiedRoutes) {
- final Optional<NormalizedNode<?, ?>> maybeRoutesBefore = NormalizedNodes.findNode(
+ final Optional<NormalizedNode> maybeRoutesBefore = NormalizedNodes.findNode(
modifiedRoutes.getDataBefore(), ribSupport.relativeRoutesPath());
if (maybeRoutesBefore.isPresent()) {
- onRoutesDeleted(ribSupport, effectiveTablePath, extractMap(maybeRoutesBefore).getValue());
+ onRoutesDeleted(ribSupport, effectiveTablePath, extractMap(maybeRoutesBefore).body());
}
}
- private void writeRoutesAfter(final DOMDataWriteTransaction tx, final RIBSupport<?, ?, ?, ?> ribSupport,
- final YangInstanceIdentifier effectiveTablePath, final Optional<NormalizedNode<?, ?>> routesAfter) {
- final Optional<NormalizedNode<?, ?>> maybeRoutesAfter = NormalizedNodes.findNode(routesAfter,
+ private void writeRoutesAfter(final DOMDataTreeWriteTransaction tx, final RIBSupport<?, ?> ribSupport,
+ final YangInstanceIdentifier effectiveTablePath, final Optional<NormalizedNode> routesAfter,
+ final boolean longLivedStale) {
+ final Optional<NormalizedNode> maybeRoutesAfter = NormalizedNodes.findNode(routesAfter,
ribSupport.relativeRoutesPath());
if (maybeRoutesAfter.isPresent()) {
final YangInstanceIdentifier routesPath = routeMapPath(ribSupport, effectiveTablePath);
- for (MapEntryNode routeAfter : extractMap(maybeRoutesAfter).getValue()) {
- writeRoute(tx, ribSupport, routesPath.node(routeAfter.getIdentifier()), Optional.empty(), routeAfter);
+ for (MapEntryNode routeAfter : extractMap(maybeRoutesAfter).body()) {
+ writeRoute(tx, ribSupport, routesPath.node(routeAfter.getIdentifier()), Optional.empty(), routeAfter,
+ longLivedStale);
}
}
}
- private void onRoutesDeleted(final RIBSupport<?, ?, ?, ?> ribSupport,
- final YangInstanceIdentifier effectiveTablePath, final Collection<MapEntryNode> deletedRoutes) {
- if (ribSupport.getSafi() == RouteTargetConstrainSubsequentAddressFamily.class) {
+ private void onRoutesDeleted(final RIBSupport<?, ?> ribSupport, final YangInstanceIdentifier effectiveTablePath,
+ final Collection<MapEntryNode> deletedRoutes) {
+ if (RouteTargetConstrainSubsequentAddressFamily.VALUE.equals(ribSupport.getTablesKey().getSafi())) {
final YangInstanceIdentifier routesPath = routeMapPath(ribSupport, effectiveTablePath);
for (final MapEntryNode routeBefore : deletedRoutes) {
deleteRouteTarget(ribSupport, routesPath.node(routeBefore.getIdentifier()), routeBefore);
}
- this.rtMembershipsUpdated = true;
+ rtMembershipsUpdated = true;
}
final TablesKey tablesKey = ribSupport.getTablesKey();
CountersUtil.add(prefixesInstalled.get(tablesKey), tablesKey, -deletedRoutes.size());
}
- private void processRoute(final DOMDataWriteTransaction tx, final RIBSupport<?, ?, ?, ?> ribSupport,
- final YangInstanceIdentifier routesPath, final DataTreeCandidateNode route) {
+ private void processRoute(final DOMDataTreeWriteTransaction tx, final RIBSupport<?, ?> ribSupport,
+ final YangInstanceIdentifier routesPath, final DataTreeCandidateNode route, final boolean longLivedStale) {
LOG.debug("Process route {}", route.getIdentifier());
final YangInstanceIdentifier routePath = ribSupport.routePath(routesPath, route.getIdentifier());
switch (route.getModificationType()) {
case APPEARED:
case SUBTREE_MODIFIED:
case WRITE:
- writeRoute(tx, ribSupport, routePath, route.getDataBefore(), route.getDataAfter().get());
+ writeRoute(tx, ribSupport, routePath, route.getDataBefore(), route.getDataAfter().orElseThrow(),
+ longLivedStale);
+ break;
default:
LOG.warn("Ignoring unhandled route {}", route);
break;
}
}
- private void deleteRoute(final DOMDataWriteTransaction tx, final RIBSupport<?, ?, ?, ?> ribSupport,
- final YangInstanceIdentifier routeIdPath, final NormalizedNode<?, ?> route) {
+ private void deleteRoute(final DOMDataTreeWriteTransaction tx, final RIBSupport<?, ?> ribSupport,
+ final YangInstanceIdentifier routeIdPath, final NormalizedNode route) {
handleRouteTarget(ModificationType.DELETE, ribSupport, routeIdPath, route);
tx.delete(LogicalDatastoreType.OPERATIONAL, routeIdPath);
LOG.debug("Route deleted. routeId={}", routeIdPath);
final TablesKey tablesKey = ribSupport.getTablesKey();
- CountersUtil.decrement(this.prefixesInstalled.get(tablesKey), tablesKey);
+ CountersUtil.decrement(prefixesInstalled.get(tablesKey), tablesKey);
}
- private void writeRoute(final DOMDataWriteTransaction tx, final RIBSupport<?, ?, ?, ?> ribSupport,
- final YangInstanceIdentifier routePath, final Optional<NormalizedNode<?, ?>> routeBefore,
- final NormalizedNode<?, ?> routeAfter) {
+ private void writeRoute(final DOMDataTreeWriteTransaction tx, final RIBSupport<?, ?> ribSupport,
+ final YangInstanceIdentifier routePath, final Optional<NormalizedNode> routeBefore,
+ final NormalizedNode routeAfter, final boolean longLivedStale) {
final TablesKey tablesKey = ribSupport.getTablesKey();
- CountersUtil.increment(this.prefixesReceived.get(tablesKey), tablesKey);
+ CountersUtil.increment(prefixesReceived.get(tablesKey), tablesKey);
// Lookup per-table attributes from RIBSupport
final ContainerNode advertisedAttrs = (ContainerNode) NormalizedNodes.findNode(routeAfter,
ribSupport.routeAttributesIdentifier()).orElse(null);
final Optional<Attributes> optEffAtt;
// In case we want to add LLGR_STALE we do not process route through policies since it may be
// considered as received with LLGR_STALE from peer which is not true.
- final boolean longLivedStale = false;
if (longLivedStale) {
// LLGR procedures are in effect. If the route is tagged with NO_LLGR, it needs to be removed.
final List<Communities> effCommunities = routeAttrs.getCommunities();
}
optEffAtt = Optional.of(wrapLongLivedStale(routeAttrs));
} else {
- final Class<? extends AfiSafiType> afiSafiType
- = tableTypeRegistry.getAfiSafiType(ribSupport.getTablesKey()).get();
- optEffAtt = this.ribPolicies
- .applyImportPolicies(this.peerImportParameters, routeAttrs, afiSafiType);
+ optEffAtt = ribPolicies.applyImportPolicies(peerImportParameters, routeAttrs,
+ verifyNotNull(tableTypeRegistry.getAfiSafiType(ribSupport.getTablesKey())));
}
- if (!optEffAtt.isPresent()) {
+ if (optEffAtt.isEmpty()) {
deleteRoute(tx, ribSupport, routePath, routeBefore.orElse(null));
return;
}
handleRouteTarget(ModificationType.WRITE, ribSupport, routePath, routeAfter);
tx.put(LogicalDatastoreType.OPERATIONAL, routePath, routeAfter);
- CountersUtil.increment(this.prefixesInstalled.get(tablesKey), tablesKey);
+ CountersUtil.increment(prefixesInstalled.get(tablesKey), tablesKey);
- final YangInstanceIdentifier attPath = routePath.node(ribSupport.routeAttributesIdentifier());
- final Attributes attToStore = optEffAtt.get();
+ final Attributes attToStore = optEffAtt.orElseThrow();
if (!attToStore.equals(routeAttrs)) {
+ final YangInstanceIdentifier attPath = routePath.node(ribSupport.routeAttributesIdentifier());
final ContainerNode finalAttribute = ribSupport.attributeToContainerNode(attPath, attToStore);
tx.put(LogicalDatastoreType.OPERATIONAL, attPath, finalAttribute);
}
private void addRouteTarget(final RouteTargetConstrainRoute rtc) {
final RouteTarget rtMembership = RouteTargetMembeshipUtil.getRT(rtc);
- if (PeerRole.Ebgp != this.peerImportParameters.getFromPeerRole()) {
- this.rtCache.cacheRoute(rtc);
+ if (PeerRole.Ebgp != peerImportParameters.getFromPeerRole()) {
+ rtCache.cacheRoute(rtc);
}
- this.rtMemberships.add(rtMembership);
+ rtMemberships.add(rtMembership);
}
- private void deleteRouteTarget(final RIBSupport<?, ?, ?, ?> ribSupport, final YangInstanceIdentifier routeIdPath,
- final NormalizedNode<?, ?> route) {
+ private void deleteRouteTarget(final RIBSupport<?, ?> ribSupport, final YangInstanceIdentifier routeIdPath,
+ final NormalizedNode route) {
deleteRouteTarget((RouteTargetConstrainRoute) ribSupport.fromNormalizedNode(routeIdPath, route));
}
private void deleteRouteTarget(final RouteTargetConstrainRoute rtc) {
final RouteTarget rtMembership = RouteTargetMembeshipUtil.getRT(rtc);
- if (PeerRole.Ebgp != this.peerImportParameters.getFromPeerRole()) {
- this.rtCache.uncacheRoute(rtc);
+ if (PeerRole.Ebgp != peerImportParameters.getFromPeerRole()) {
+ rtCache.uncacheRoute(rtc);
}
- this.rtMemberships.remove(rtMembership);
+ rtMemberships.remove(rtMembership);
}
- private void handleRouteTarget(final ModificationType modificationType, final RIBSupport<?, ?, ?, ?> ribSupport,
- final YangInstanceIdentifier routeIdPath, final NormalizedNode<?, ?> route) {
- if (ribSupport.getSafi() == RouteTargetConstrainSubsequentAddressFamily.class) {
- final RouteTargetConstrainRoute rtc =
- (RouteTargetConstrainRoute) ribSupport.fromNormalizedNode(routeIdPath, route);
+ private void handleRouteTarget(final ModificationType modificationType, final RIBSupport<?, ?> ribSupport,
+ final YangInstanceIdentifier routeIdPath, final NormalizedNode route) {
+ if (RouteTargetConstrainSubsequentAddressFamily.VALUE.equals(ribSupport.getTablesKey().getSafi())) {
+ final var rtc = (RouteTargetConstrainRoute) ribSupport.fromNormalizedNode(routeIdPath, route);
if (ModificationType.DELETE == modificationType) {
deleteRouteTarget(rtc);
} else {
addRouteTarget(rtc);
}
- this.rtMembershipsUpdated = true;
+ rtMembershipsUpdated = true;
}
}
newCommunities = STALE_LLGR_COMMUNUTIES;
}
- return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329
+ return new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120
.path.attributes.AttributesBuilder(attrs).setCommunities(newCommunities).build();
}
}
private YangInstanceIdentifier effectiveTablePath(final NodeIdentifierWithPredicates tableKey) {
- return this.effRibTables.node(TABLES_NID).node(tableKey);
+ return effRibTables.node(TABLES_NID).node(tableKey);
}
- private static YangInstanceIdentifier routeMapPath(final RIBSupport<?, ?, ?, ?> ribSupport,
+ private static YangInstanceIdentifier routeMapPath(final RIBSupport<?, ?> ribSupport,
final YangInstanceIdentifier tablePath) {
return concat(tablePath.node(ROUTES_NID), ribSupport.relativeRoutesPath());
}
- private static Optional<NormalizedNode<?, ?>> findRoutesMap(final RIBSupport<?, ?, ?, ?> ribSupport,
- final Optional<NormalizedNode<?, ?>> optRoutes) {
+ private static Optional<NormalizedNode> findRoutesMap(final RIBSupport<?, ?> ribSupport,
+ final Optional<NormalizedNode> optRoutes) {
return NormalizedNodes.findNode(optRoutes, ribSupport.relativeRoutesPath());
}
- private static ContainerNode extractContainer(final Optional<? extends NormalizedNode<?, ?>> optNode) {
- final NormalizedNode<?, ?> node = optNode.get();
+ private static ContainerNode extractContainer(final NormalizedNode node) {
verify(node instanceof ContainerNode, "Expected ContainerNode, got %s", node);
return (ContainerNode) node;
}
- private static MapNode extractMap(final Optional<? extends NormalizedNode<?, ?>> optNode) {
- final NormalizedNode<?, ?> node = optNode.get();
+ private static MapNode extractMap(final Optional<? extends NormalizedNode> optNode) {
+ final NormalizedNode node = optNode.orElseThrow();
verify(node instanceof MapNode, "Expected MapNode, got %s", node);
return (MapNode) node;
}
- private static MapEntryNode extractMapEntry(final Optional<? extends NormalizedNode<?, ?>> optNode) {
- final NormalizedNode<?, ?> node = optNode.get();
- verify(node instanceof MapEntryNode, "Expected MapEntryNode, got %s", node);
- return (MapEntryNode) node;
+ private static boolean isLongLivedStale(final ContainerNode attributes) {
+ return NormalizedNodes.findNode(attributes, ADJRIBIN_ATTRIBUTES_AID, LLGR_STALE_NID).isPresent();
+ }
+
+ private static boolean isLongLivedStaleTable(final Optional<NormalizedNode> optTable) {
+ final Optional<NormalizedNode> optAttributes = NormalizedNodes.findNode(optTable, ATTRIBUTES_NID);
+ return optAttributes.isPresent() && isLongLivedStale(extractContainer(optAttributes.orElseThrow()));
+ }
+
+ private static ContainerNode effectiveAttributes(final ContainerNode attrs) {
+ final var upToDate = attrs.childByArg(UPTODATE_NID);
+ if (upToDate != null) {
+ final Object value = upToDate.body();
+ verify(value instanceof Boolean, "Expected boolean uptodate, got %s", value);
+ if ((Boolean) value) {
+ return RIBNormalizedNodes.UPTODATE_ATTRIBUTES;
+ }
+ }
+ return RIBNormalizedNodes.NOT_UPTODATE_ATTRIBUTES;
}
}