type peer-role;
mandatory true;
}
-
+ list supported-tables {
+ key "afi safi";
+ uses bgp-mp:bgp-table-type;
+ }
container adj-rib-in {
description "Routes as we have received them from the peer.";
uses rib;
import javax.annotation.Nullable;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
}
static final NodeIdentifier PEER_ROLE_NID = new NodeIdentifier(QName.cachedReference(QName.create(Peer.QNAME, "peer-role")));
+ static final NodeIdentifier PEER_TABLES = new NodeIdentifier(SupportedTables.QNAME);
protected AbstractPeerRoleTracker() {
}
*/
package org.opendaylight.protocol.bgp.rib.impl;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibOut;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@NotThreadSafe
final class AdjRibInWriter {
private static final Logger LOG = LoggerFactory.getLogger(AdjRibInWriter.class);
-
- private static final LeafNode<Boolean> ATTRIBUTES_UPTODATE_FALSE = ImmutableNodes.leafNode(QName.create(Attributes.QNAME, "uptodate"), Boolean.FALSE);
+ @VisibleForTesting
+ static final LeafNode<Boolean> ATTRIBUTES_UPTODATE_FALSE = ImmutableNodes.leafNode(QName.create(Attributes.QNAME, "uptodate"), Boolean.FALSE);
private static final LeafNode<Boolean> ATTRIBUTES_UPTODATE_TRUE = ImmutableNodes.leafNode(ATTRIBUTES_UPTODATE_FALSE.getNodeType(), Boolean.TRUE);
- private static final QName PEER_ID_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "peer-id"));
+ @VisibleForTesting
+ static final QName PEER_ID_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "peer-id"));
private static final QName PEER_ROLE_QNAME = QName.cachedReference(QName.create(Peer.QNAME, "peer-role"));
private static final NodeIdentifier ADJRIBIN = new NodeIdentifier(AdjRibIn.QNAME);
private static final NodeIdentifier ADJRIBOUT = new NodeIdentifier(AdjRibOut.QNAME);
private static final NodeIdentifier EFFRIBIN = new NodeIdentifier(EffectiveRibIn.QNAME);
private static final NodeIdentifier PEER_ID = new NodeIdentifier(PEER_ID_QNAME);
private static final NodeIdentifier PEER_ROLE = new NodeIdentifier(PEER_ROLE_QNAME);
+ private static final NodeIdentifier PEER_TABLES = new NodeIdentifier(SupportedTables.QNAME);
private static final NodeIdentifier TABLES = new NodeIdentifier(Tables.QNAME);
// FIXME: is there a utility method to construct this?
final YangInstanceIdentifier newPeerPath;
if (!newPeerId.equals(this.peerId)) {
- newPeerPath = this.createEmptyPeerStructure(newPeerId, isAppPeer, tx);
+ newPeerPath = createEmptyPeerStructure(newPeerId, isAppPeer, tx);
} else {
newPeerPath = this.peerPath;
}
// install tables for adj-ribs-out (we do not need TableContext for that
if (!isAppPeer) {
+ final NodeIdentifierWithPredicates supTablesKey = RibSupportUtils.toYangKey(SupportedTables.QNAME, k);
+ final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> tt = Builders.mapEntryBuilder().withNodeIdentifier(supTablesKey);
+ for (final Entry<QName, Object> e : supTablesKey.getKeyValues().entrySet()) {
+ tt.withChild(ImmutableNodes.leafNode(e.getKey(), e.getValue()));
+ }
+ tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath.node(PEER_TABLES).node(supTablesKey), tt.build());
rs.clearTable(tx, newPeerPath.node(EMPTY_ADJRIBOUT.getIdentifier()).node(TABLES).node(key));
}
-
// We will use table keys very often, make sure they are optimized
final InstanceIdentifierBuilder idb = YangInstanceIdentifier.builder(newPeerPath.node(EMPTY_ADJRIBIN.getIdentifier()).node(TABLES));
idb.nodeWithKey(key.getNodeType(), key.getKeyValues());
final NodeIdentifierWithPredicates peerKey = IdentifierUtils.domPeerId(newPeerId);
final YangInstanceIdentifier newPeerPath = this.ribPath.node(Peer.QNAME).node(peerKey);
+ tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath, peerSkeleton(peerKey, newPeerId.getValue(), isAppPeer));
+ LOG.debug("New peer {} structure installed.", newPeerPath);
+ return newPeerPath;
+ }
+
+ @VisibleForTesting
+ MapEntryNode peerSkeleton(final NodeIdentifierWithPredicates peerKey, final String peerId, final boolean isAppPeer) {
final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> pb = Builders.mapEntryBuilder();
pb.withNodeIdentifier(peerKey);
- pb.withChild(ImmutableNodes.leafNode(PEER_ID, newPeerId.getValue()));
+ pb.withChild(ImmutableNodes.leafNode(PEER_ID, peerId));
pb.withChild(ImmutableNodes.leafNode(PEER_ROLE, this.role));
+ pb.withChild(ImmutableMapNodeBuilder.create().withNodeIdentifier(PEER_TABLES).build());
pb.withChild(EMPTY_ADJRIBIN);
pb.withChild(EMPTY_EFFRIBIN);
if (!isAppPeer) {
pb.withChild(EMPTY_ADJRIBOUT);
}
- tx.put(LogicalDatastoreType.OPERATIONAL, newPeerPath, pb.build());
- LOG.debug("New peer {} structure installed.", newPeerPath);
- return newPeerPath;
+ return pb.build();
}
/**
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
import java.util.Map.Entry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
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.tree.DataTreeCandidateNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
};
private final Map<YangInstanceIdentifier, PeerRole> peerRoles = new HashMap<>();
+ private final HashMultimap<PeerId, NodeIdentifierWithPredicates> peerTables = HashMultimap.create();
private volatile Map<PeerRole, PeerExportGroup> groups = Collections.emptyMap();
private final PolicyDatabase policyDatabase;
PeerExportGroup getPeerGroup(final PeerRole role) {
return this.groups.get(Preconditions.checkNotNull(role));
}
+
+ void onTablesChanged(final DataTreeCandidateNode change, final YangInstanceIdentifier peerPath) {
+ final PeerId peerId = IdentifierUtils.peerId((NodeIdentifierWithPredicates) peerPath.getLastPathArgument());
+ for (final DataTreeCandidateNode node : change.getChildNodes()) {
+ if (node.getDataAfter().isPresent()) {
+ final NodeIdentifierWithPredicates value = (NodeIdentifierWithPredicates) node.getDataAfter().get().getIdentifier();
+ final boolean added = this.peerTables.put(peerId, value);
+ if (added) {
+ LOG.debug("Supported table {} added to peer {}", value, peerId);
+ }
+ } else {
+ LOG.debug("Removed tables {} from peer {}", this.peerTables.removeAll(peerId), peerId);
+ }
+ }
+ }
+
+ boolean isTableSupported(final PeerId peerId, final TablesKey tablesKey) {
+ return this.peerTables.get(peerId).contains(tablesKey);
+ }
}
\ No newline at end of file
*/
package org.opendaylight.protocol.bgp.rib.impl;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.primitives.UnsignedInteger;
private final Long ourAs;
private final RIBSupport ribSupport;
private final NodeIdentifierWithPredicates tableKey;
+ private final TablesKey localTablesKey;
private final RIBSupportContextRegistry registry;
private final ListenerRegistration<LocRibWriter> reg;
final DOMDataTreeChangeService service, final PolicyDatabase pd, final TablesKey tablesKey) {
this.chain = Preconditions.checkNotNull(chain);
this.tableKey = RibSupportUtils.toYangTablesKey(tablesKey);
+ this.localTablesKey = tablesKey;
this.locRibTarget = YangInstanceIdentifier.create(target.node(LocRib.QNAME).node(Tables.QNAME).node(this.tableKey).getPathArguments());
this.ourAs = Preconditions.checkNotNull(ourAs);
this.registry = registry;
this.chain.close();
}
- @Nonnull private AbstractRouteEntry createEntry(final PathArgument routeId) {
+ @Nonnull
+ private AbstractRouteEntry createEntry(final PathArgument routeId) {
final AbstractRouteEntry ret = this.ribSupport.isComplexRoute() ? new ComplexRouteEntry() : new SimpleRouteEntry();
-
this.routeEntries.put(routeId, ret);
LOG.trace("Created new entry for {}", routeId);
return ret;
@Override
public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
- LOG.trace("Received data change to LocRib {}", changes);
+ LOG.trace("Received data change {} to LocRib {}", changes, this);
final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
try {
for (final DataTreeCandidate tc : changes) {
final YangInstanceIdentifier rootPath = tc.getRootPath();
final DataTreeCandidateNode rootNode = tc.getRootNode();
+ // filter out changes to supported tables
+ final DataTreeCandidateNode tablesChange = rootNode.getModifiedChild(AbstractPeerRoleTracker.PEER_TABLES);
+ if (tablesChange != null) {
+ this.peerPolicyTracker.onTablesChanged(tablesChange, IdentifierUtils.peerPath(rootPath));
+ }
+ // filter out peer role
final DataTreeCandidateNode roleChange = rootNode.getModifiedChild(AbstractPeerRoleTracker.PEER_ROLE_NID);
if (roleChange != null) {
this.peerPolicyTracker.onDataTreeChanged(roleChange, IdentifierUtils.peerPath(rootPath));
}
}
- private void fillAdjRibsOut(final DOMDataWriteTransaction tx, final AbstractRouteEntry entry, final NormalizedNode<?, ?> value, final RouteUpdateKey key) {
+ @VisibleForTesting
+ void fillAdjRibsOut(final DOMDataWriteTransaction tx, final AbstractRouteEntry entry, final NormalizedNode<?, ?> value, final RouteUpdateKey key) {
/*
* 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
if (peerGroup != null) {
final ContainerNode attributes = entry == null ? null : entry.attributes();
final PeerId peerId = key.getPeerId();
+ if (!this.peerPolicyTracker.isTableSupported(peerId, this.localTablesKey)) {
+ LOG.trace("Route rejected, peer {} does not support this table type {}", peerId, this.tableKey);
+ continue;
+ }
final ContainerNode effectiveAttributes = peerGroup.effectiveAttributes(peerId, attributes);
for (final Entry<PeerId, YangInstanceIdentifier> pid : peerGroup.getPeers()) {
final YangInstanceIdentifier routeTarget = this.ribSupport.routePath(pid.getValue().node(AdjRibOut.QNAME).node(Tables.QNAME).node(this.tableKey).node(ROUTES_IDENTIFIER), key.getRouteId());
--- /dev/null
+/*
+ * Copyright (c) 2015 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.rib.impl;
+
+import static org.junit.Assert.assertNotNull;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+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.protocol.bgp.rib.impl.spi.RIBSupportContext;
+import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Rib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class AdjRibsInWriterTest {
+
+ @Mock
+ private DOMTransactionChain chain;
+
+ @Mock
+ private DOMDataWriteTransaction tx;
+
+ @Mock
+ private RIBSupportContextRegistry registry;
+
+ @Mock
+ private RIBSupportContext context;
+
+ private AdjRibInWriter writer;
+
+ private static final TablesKey k4 = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
+ private final Set<TablesKey> tableTypes = Sets.newHashSet(k4);
+ private final String peerIp = "12.34.56.78";
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ this.writer = AdjRibInWriter.create(YangInstanceIdentifier.of(Rib.QNAME), PeerRole.Ebgp, this.chain);
+ assertNotNull(this.writer);
+ Mockito.doReturn("MockedTrans").when(this.tx).toString();
+ Mockito.doReturn(this.tx).when(this.chain).newWriteOnlyTransaction();
+ Mockito.doReturn(Mockito.mock(CheckedFuture.class)).when(this.tx).submit();
+ }
+
+ @Test
+ public void testTransform() {
+ final YangInstanceIdentifier peerPath = YangInstanceIdentifier.builder().node(Rib.QNAME).node(Peer.QNAME).nodeWithKey(Peer.QNAME, AdjRibInWriter.PEER_ID_QNAME, this.peerIp).build();
+ Mockito.doNothing().when(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
+ Mockito.doNothing().when(this.tx).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
+ Mockito.doReturn(this.context).when(this.registry).getRIBSupportContext(Mockito.any(TablesKey.class));
+ Mockito.doNothing().when(this.context).clearTable(Mockito.eq(this.tx), Mockito.any(YangInstanceIdentifier.class));
+
+ this.writer.transform(new PeerId(this.peerIp), this.registry, this.tableTypes, false);
+
+ // verify peer skeleton was inserted correctly
+ Mockito.verify(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(peerPath), Mockito.eq(this.writer.peerSkeleton(IdentifierUtils.peerKey(peerPath), this.peerIp, false)));
+ // verify supported tables were inserted for ipv4
+ Mockito.verify(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(peerPath.node(SupportedTables.QNAME).node(RibSupportUtils.toYangKey(SupportedTables.QNAME, k4))), Mockito.any(NormalizedNode.class));
+ // verify uptodate set to false
+ final YangInstanceIdentifier path = peerPath.node(AdjRibIn.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(k4)).node(Attributes.QNAME).node(AdjRibInWriter.ATTRIBUTES_UPTODATE_FALSE.getNodeType());
+ Mockito.verify(this.tx).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(path), Mockito.eq(AdjRibInWriter.ATTRIBUTES_UPTODATE_FALSE));
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.rib.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener;
+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.protocol.bgp.rib.impl.spi.RIBSupportContext;
+import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
+import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.Ipv4Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4Route;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.Peer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.EffectiveRibIn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class LocRibWriterTest {
+
+ @Mock
+ DOMDataWriteTransaction domTransWrite;
+
+ private final PolicyDatabase pd = new PolicyDatabase((long) 35, new Ipv4Address("10.25.2.9"), new ClusterIdentifier(new Ipv4Address("10.25.2.9")));
+
+ @Mock
+ private RIBSupportContextRegistry registry;
+
+ @Mock
+ private DOMTransactionChain chain;
+
+ @Mock
+ private DOMDataTreeChangeService service;
+
+ @Mock
+ private RIBSupportContext context;
+
+ @Mock
+ private AbstractIPRIBSupport ribSupport;
+
+ @Mock
+ CheckedFuture<?, ?> future;
+
+ private LocRibWriter locRibWriter;
+
+ private final List<YangInstanceIdentifier> routes = new ArrayList<>();
+ private final TablesKey tablesKey = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ Mockito.doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ final Object[] args = invocation.getArguments();
+ final NormalizedNode<?, ?> node = (NormalizedNode<?, ?>) args[2];
+ if (node.getNodeType().equals(Ipv4Route.QNAME) || node.getNodeType().equals(IPv4RIBSupport.PREFIX_QNAME)) {
+ LocRibWriterTest.this.routes.add((YangInstanceIdentifier) args[1]);
+ }
+ return args[1];
+ }
+ }).when(this.domTransWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
+ Mockito.doAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ final Object[] args = invocation.getArguments();
+ final NormalizedNode<?, ?> node = (NormalizedNode<?, ?>) args[2];
+ if (node.getNodeType().equals(Ipv4Route.QNAME) || node.getNodeType().equals(IPv4RIBSupport.PREFIX_QNAME)) {
+ LocRibWriterTest.this.routes.add((YangInstanceIdentifier) args[1]);
+ }
+ return args[1];
+ }
+ }).when(this.domTransWrite).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
+ Mockito.doAnswer(new Answer<Object>() {
+
+ @Override
+ public Object answer(final InvocationOnMock invocation) throws Throwable {
+ final Object[] args = invocation.getArguments();
+ LocRibWriterTest.this.routes.remove(args[1]);
+ return args[1];
+ }
+ }).when(this.domTransWrite).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class));
+ Mockito.doReturn(this.context).when(this.registry).getRIBSupportContext(this.tablesKey);
+ Mockito.doReturn(this.ribSupport).when(this.context).getRibSupport();
+ Mockito.doReturn(this.domTransWrite).when(this.chain).newWriteOnlyTransaction();
+ Mockito.doReturn(this.future).when(this.domTransWrite).submit();
+ Mockito.doReturn(null).when(this.service).registerDataTreeChangeListener(Mockito.any(DOMDataTreeIdentifier.class), Mockito.any(DOMDataTreeChangeListener.class));
+ Mockito.doReturn(Builders.choiceBuilder().withNodeIdentifier(new NodeIdentifier(Routes.QNAME)).addChild(Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(Ipv4Routes.QNAME)).withChild(ImmutableNodes.mapNodeBuilder(Ipv4Route.QNAME).build()).build()).build()).when(this.ribSupport).emptyRoutes();
+ this.locRibWriter = LocRibWriter.create(this.registry, this.tablesKey, this.chain, YangInstanceIdentifier.of(BgpRib.QNAME), new AsNumber((long) 35), this.service, this.pd);
+ }
+
+ private DataTreeCandidate prepareUpdate() {
+ final DataTreeCandidate candidate = Mockito.mock(DataTreeCandidate.class);
+ Mockito.doReturn("candidate").when(candidate).toString();
+ final YangInstanceIdentifier rootPath = YangInstanceIdentifier.builder().node(BgpRib.QNAME).node(Peer.QNAME).nodeWithKey(Peer.QNAME, AdjRibInWriter.PEER_ID_QNAME, "12.12.12.12").build();
+ Mockito.doReturn(rootPath).when(candidate).getRootPath();
+ return candidate;
+ }
+
+ @Test
+ public void testUpdateSupportedTables() {
+ final DataTreeCandidate candidate = prepareUpdate();
+ final DataTreeCandidateNode node = Mockito.mock(DataTreeCandidateNode.class);
+ Mockito.doReturn("node").when(node).toString();
+ final DataTreeCandidateNode tableChange = Mockito.mock(DataTreeCandidateNode.class);
+ // add
+ final DataTreeCandidateNode table = Mockito.mock(DataTreeCandidateNode.class);
+ final NormalizedNode<?, ?> dataAfter = Mockito.mock(NormalizedNode.class);
+ Mockito.doReturn(RibSupportUtils.toYangTablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class)).when(dataAfter).getIdentifier();
+ Mockito.doReturn(Optional.of(dataAfter)).when(table).getDataAfter();
+ Mockito.doReturn(Lists.newArrayList(table)).when(tableChange).getChildNodes();
+ Mockito.doReturn("table change").when(tableChange).toString();
+ Mockito.doReturn(tableChange).when(node).getModifiedChild(YangInstanceIdentifier.of(SupportedTables.QNAME).getLastPathArgument());
+ Mockito.doReturn(null).when(node).getModifiedChild(AbstractPeerRoleTracker.PEER_ROLE_NID);
+ Mockito.doReturn(null).when(node).getModifiedChild(YangInstanceIdentifier.of(EffectiveRibIn.QNAME).getLastPathArgument());
+ Mockito.doReturn(node).when(candidate).getRootNode();
+ this.locRibWriter.onDataTreeChanged(Lists.newArrayList(candidate));
+ // delete
+ final DataTreeCandidateNode tableDelete = Mockito.mock(DataTreeCandidateNode.class);
+ Mockito.doReturn(Optional.absent()).when(tableDelete).getDataAfter();
+ Mockito.doReturn(Lists.newArrayList(tableDelete)).when(tableChange).getChildNodes();
+ Mockito.doReturn("table change").when(tableChange).toString();
+ Mockito.doReturn(node).when(candidate).getRootNode();
+ this.locRibWriter.onDataTreeChanged(Lists.newArrayList(candidate));
+ Mockito.verify(node, Mockito.times(2)).getModifiedChild(YangInstanceIdentifier.of(SupportedTables.QNAME).getLastPathArgument());
+ }
+}
*/
public static NodeIdentifierWithPredicates toYangTablesKey(final Class<? extends AddressFamily> afi,
final Class<? extends SubsequentAddressFamily> safi) {
+ return toYangKey(Tables.QNAME, afi, safi);
+ }
+
+ /**
+ * Creates Yang Instance Identifier path argument from supplied AFI and SAFI
+ *
+ * @param id QNAME representing node
+ * @param afi Class representing AFI
+ * @param safi Class representing SAFI
+ * @return NodeIdentifierWithPredicates of 'id' for specified AFI, SAFI combination.
+ */
+ public static NodeIdentifierWithPredicates toYangKey(final QName id, final Class<? extends AddressFamily> afi, final Class<? extends SubsequentAddressFamily> safi) {
final ImmutableMap<QName, Object> keyValues = ImmutableMap.<QName, Object>of(
AFI_QNAME, BindingReflections.findQName(afi),
SAFI_QNAME, BindingReflections.findQName(safi));
- return new NodeIdentifierWithPredicates(Tables.QNAME, keyValues);
+ return new NodeIdentifierWithPredicates(id, keyValues);
+ }
+
+ /**
+ * Creates Yang Instance Identifier path argument from supplied {@link TablesKey}
+ *
+ * @param id QNAME representing node
+ * @param k Tables key representing table.
+ * @return NodeIdentifierWithPredicates of 'id' for specified AFI, SAFI combination.
+ */
+ public static NodeIdentifierWithPredicates toYangKey(final QName id, final TablesKey k) {
+ return toYangKey(id, k.getAfi(), k.getSafi());
}
/**
package org.opendaylight.protocol.bgp.rib.spi;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.SupportedTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
import org.opendaylight.yangtools.yang.common.QName;
}
@Test
- public void test() {
- final Class afi = Ipv4AddressFamily.class;
- final Class safi = UnicastSubsequentAddressFamily.class;
+ public void testYangTablesKey() {
+ final Class<? extends AddressFamily> afi = Ipv4AddressFamily.class;
+ final Class<? extends SubsequentAddressFamily> safi = UnicastSubsequentAddressFamily.class;
final TablesKey k = new TablesKey(afi, safi);
final NodeIdentifierWithPredicates p = RibSupportUtils.toYangTablesKey(k);
final Map<QName, Object> m = p.getKeyValues();
assertFalse(m.isEmpty());
+ assertEquals(Tables.QNAME, p.getNodeType());
+ assertTrue(m.containsValue(BindingReflections.findQName(afi)));
+ assertTrue(m.containsValue(BindingReflections.findQName(safi)));
+ }
+
+ @Test
+ public void testYangKey() {
+ final Class<? extends AddressFamily> afi = Ipv4AddressFamily.class;
+ final Class<? extends SubsequentAddressFamily> safi = UnicastSubsequentAddressFamily.class;
+ final TablesKey k = new TablesKey(afi, safi);
+ final NodeIdentifierWithPredicates p = RibSupportUtils.toYangKey(SupportedTables.QNAME, k);
+ final Map<QName, Object> m = p.getKeyValues();
+ assertFalse(m.isEmpty());
+ assertEquals(SupportedTables.QNAME, p.getNodeType());
assertTrue(m.containsValue(BindingReflections.findQName(afi)));
assertTrue(m.containsValue(BindingReflections.findQName(safi)));
}