grouping as-path-segment {
reference "http://tools.ietf.org/html/rfc4271#section-5.1.2";
choice c-segment {
+ description "This model is obsolete and please use just leaf-lists as-sequence and as-set nested directly under as-path-segment.";
+ status obsolete;
case a-set-case {
container a-set {
leaf-list as-set {
}
}
}
+ leaf-list as-sequence {
+ type inet:as-number;
+ ordered-by user;
+ max-elements "255";
+ }
+ leaf-list as-set {
+ type inet:as-number;
+ }
}
}
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPathBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.SegmentsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASetBuilder;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
}
final int count = buffer.readUnsignedByte();
+ final List<AsNumber> asList = AsPathSegmentParser.parseAsSegment(refCache, count, buffer.readSlice(count * AsPathSegmentParser.AS_NUMBER_LENGTH));
if (segmentType == SegmentType.AS_SEQUENCE) {
- final List<AsSequence> numbers = AsPathSegmentParser.parseAsSequence(refCache, count, buffer.readSlice(count * AsPathSegmentParser.AS_NUMBER_LENGTH));
- ases.add(new SegmentsBuilder().setCSegment(
- new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(numbers).build()).build()).build());
+ ases.add(new SegmentsBuilder().setAsSequence(asList).build());
isSequence = true;
} else {
- final List<AsNumber> list = AsPathSegmentParser.parseAsSet(refCache, count, buffer.readSlice(count * AsPathSegmentParser.AS_NUMBER_LENGTH));
- ases.add(new SegmentsBuilder().setCSegment(new ASetCaseBuilder().setASet(new ASetBuilder().setAsSet(list).build()).build()).build());
+ ases.add(new SegmentsBuilder().setAsSet(asList).build());
}
}
if (!isSequence) {
final ByteBuf segmentsBuffer = Unpooled.buffer();
if (asPath.getSegments() != null) {
for (final Segments segments : asPath.getSegments()) {
- if (segments.getCSegment() instanceof AListCase) {
- final AListCase listCase = (AListCase) segments.getCSegment();
- AsPathSegmentParser.serializeAsSequence(listCase, segmentsBuffer);
- } else if (segments.getCSegment() instanceof ASetCase) {
- final ASetCase set = (ASetCase) segments.getCSegment();
- AsPathSegmentParser.serializeAsSet(set, segmentsBuffer);
+ if (segments.getAsSequence() != null) {
+ AsPathSegmentParser.serializeAsList(segments.getAsSequence(), SegmentType.AS_SEQUENCE, segmentsBuffer);
+ } else if (segments.getAsSet() != null) {
+ AsPathSegmentParser.serializeAsList(segments.getAsSet(), SegmentType.AS_SET, segmentsBuffer);
} else {
- LOG.warn("Segment class is neither AListCase nor ASetCase.");
+ LOG.warn("Segment doesn't have AsSequence nor AsSet list.");
}
}
}
import static org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType.AS_SEQUENCE;
import static org.opendaylight.protocol.bgp.parser.impl.message.update.AsPathSegmentParser.SegmentType.AS_SET;
-
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.opendaylight.protocol.util.ReferenceCache;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequenceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASet;
/**
* Representation of one AS Path Segment. It is, in fact, a TLV, but the length field is representing the count of AS
}
}
- static List<AsSequence> parseAsSequence(final ReferenceCache refCache, final int count, final ByteBuf buffer) {
- final List<AsSequence> coll = new ArrayList<>(count);
- for (int i = 0; i < count; i++) {
- coll.add(refCache.getSharedReference(new AsSequenceBuilder().setAs(refCache.getSharedReference(new AsNumber(buffer.readUnsignedInt()))).build()));
- }
- return (coll.isEmpty()) ? Collections.<AsSequence>emptyList() : coll;
- }
-
- static List<AsNumber> parseAsSet(final ReferenceCache refCache, final int count, final ByteBuf buffer) {
+ static List<AsNumber> parseAsSegment(final ReferenceCache refCache, final int count, final ByteBuf buffer) {
final List<AsNumber> coll = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
coll.add(refCache.getSharedReference(new AsNumber(buffer.readUnsignedInt())));
return (coll.isEmpty()) ? Collections.<AsNumber>emptyList() : coll;
}
- static void serializeAsSet(final ASetCase aSetCase, final ByteBuf byteAggregator) {
- final ASet aset = aSetCase.getASet();
- if (aset == null || aset.getAsSet() == null) {
- return;
- }
- byteAggregator.writeByte(serializeType(AS_SET));
- byteAggregator.writeByte(aset.getAsSet().size());
- for (final AsNumber asNumber : aset.getAsSet()) {
- byteAggregator.writeInt(asNumber.getValue().intValue());
- }
- }
-
- static void serializeAsSequence(final AListCase aListCase, final ByteBuf byteAggregator) {
- final AList alist = aListCase.getAList();
- if (alist == null || alist.getAsSequence() == null) {
+ static void serializeAsList(final List<AsNumber> asList, final SegmentType type, final ByteBuf byteAggregator) {
+ if (asList == null) {
return;
}
- byteAggregator.writeByte(serializeType(AS_SEQUENCE));
- byteAggregator.writeByte(alist.getAsSequence().size());
- for (final AsSequence value : alist.getAsSequence()) {
- byteAggregator.writeInt(value.getAs().getValue().intValue());
+ byteAggregator.writeByte(serializeType(type));
+ byteAggregator.writeByte(asList.size());
+ for (final AsNumber asNumber : asList) {
+ byteAggregator.writeInt( asNumber.getValue().intValue());
}
}
}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv6AddressFamily;
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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequenceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASetBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.Inet4SpecificExtendedCommunityCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.extended.community.extended.community.inet4.specific.extended.community._case.Inet4SpecificExtendedCommunityBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCase;
assertNull(message.getWithdrawnRoutes());
// attributes
-
- final List<AsSequence> asnums = Lists.newArrayList(new AsSequenceBuilder().setAs(new AsNumber(65002L)).build());
+ final List<AsNumber> asNumbers = new ArrayList<AsNumber>();
+ asNumbers.add(new AsNumber(65002L));
final List<Segments> asPath = Lists.newArrayList();
- asPath.add(new SegmentsBuilder().setCSegment(
- new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(asnums).build()).build()).build());
+ asPath.add(new SegmentsBuilder().setAsSequence(asNumbers).build());
final Ipv4NextHopCase nextHop = new Ipv4NextHopCaseBuilder().setIpv4NextHop(
new Ipv4NextHopBuilder().setGlobal(new Ipv4Address("10.0.0.2")).build()).build();
assertNull(message.getNlri());
// attributes
-
- final List<AsSequence> asnums = Lists.newArrayList(new AsSequenceBuilder().setAs(new AsNumber(65001L)).build());
+ final List<AsNumber> asNumbers = new ArrayList<AsNumber>();
+ asNumbers.add(new AsNumber(65001L));
final List<Segments> asPath = Lists.newArrayList();
- asPath.add(new SegmentsBuilder().setCSegment(
- new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(asnums).build()).build()).build());
+ asPath.add(new SegmentsBuilder().setAsSequence(asNumbers).build());
final Ipv6NextHopCase nextHop = new Ipv6NextHopCaseBuilder().setIpv6NextHop(
new Ipv6NextHopBuilder().setGlobal(new Ipv6Address("2001:db8::1")).setLinkLocal(new Ipv6Address("fe80::c001:bff:fe7e:0")).build()).build();
assertNull(message.getWithdrawnRoutes());
// attributes
- final List<AsSequence> asnums = Lists.newArrayList(new AsSequenceBuilder().setAs(new AsNumber(30L)).build());
+ final List<AsNumber> asNumbers = new ArrayList<AsNumber>();
+ asNumbers.add(new AsNumber(30L));
final List<Segments> asPath = Lists.newArrayList();
- asPath.add(new SegmentsBuilder().setCSegment(
- new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(asnums).build()).build()).build());
- asPath.add(new SegmentsBuilder().setCSegment(
- new ASetCaseBuilder().setASet(new ASetBuilder().setAsSet(Lists.newArrayList(new AsNumber(10L), new AsNumber(20L))).build()).build()).build());
+ asPath.add(new SegmentsBuilder().setAsSequence(asNumbers).build());
+ final List<AsNumber> asSet = Lists.newArrayList(new AsNumber(10L), new AsNumber(20L));
+ asPath.add(new SegmentsBuilder().setAsSet(asSet).build());
final Aggregator aggregator = new AggregatorBuilder().setAsNumber(new AsNumber((long) 30)).setNetworkAddress(
new Ipv4Address("10.0.0.9")).build();
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
-import java.util.Collection;
import java.util.Iterator;
import org.opendaylight.protocol.util.Values;
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.message.rev130919.path.attributes.attributes.UnrecognizedAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments;
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.as.path.segment.CSegment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
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.api.ListNodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final NodeIdentifier clusterListLeaf;
private final NodeIdentifier asPathContainer;
private final NodeIdentifier asPathSegments;
- private final NodeIdentifier asPathChoice;
- private final NodeIdentifier asPathList;
private final NodeIdentifier asPathSequence;
- private final NodeIdentifier asPathId;
+ private final QName asNumberQname;
private final NodeIdentifier transitiveLeaf;
private AttributeOperations(final QNameModule namespace) {
this.asPathContainer = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsPath.QNAME.getLocalName())));
this.asPathSegments = new NodeIdentifier(QName.cachedReference(QName.create(namespace, Segments.QNAME.getLocalName())));
- this.asPathChoice = new NodeIdentifier(QName.cachedReference(QName.create(namespace, CSegment.QNAME.getLocalName())));
- this.asPathList = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AList.QNAME.getLocalName())));
- this.asPathSequence = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsSequence.QNAME.getLocalName())));
- this.asPathId = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "as")));
+ this.asPathSequence = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "as-sequence")));
+ this.asNumberQname = QName.cachedReference(QName.create(namespace, "as-number"));
this.clusterListContainer = new NodeIdentifier(QName.cachedReference(QName.create(namespace, ClusterId.QNAME.getLocalName())));
this.clusterListLeaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "cluster")));
return ATTRIBUTES_CACHE.getUnchecked(attributes.getNodeType().getModule());
}
- private Collection<UnkeyedListEntryNode> reusableSequence(final UnkeyedListEntryNode segment) {
- final Optional<NormalizedNode<?, ?>> maybeAsSequence = NormalizedNodes.findNode(segment, this.asPathChoice, this.asPathList, this.asPathSequence);
+ private LeafSetNode<?> reusableSegment(final UnkeyedListEntryNode segment) {
+ final Optional<NormalizedNode<?, ?>> maybeAsSequence = NormalizedNodes.findNode(segment, this.asPathSequence);
if (maybeAsSequence.isPresent()) {
- final UnkeyedListNode asList = (UnkeyedListNode) maybeAsSequence.get();
- if (asList.getSize() < Values.UNSIGNED_BYTE_MAX_VALUE) {
- return asList.getValue();
+ final LeafSetNode<?> asList = (LeafSetNode<?>) maybeAsSequence.get();
+ if (asList.getValue().size() < Values.UNSIGNED_BYTE_MAX_VALUE) {
+ return asList;
}
}
-
return null;
}
ContainerNode exportedAttributes(final ContainerNode attributes, final Long localAs) {
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
- b.withNodeIdentifier(attributes.getIdentifier());
+ final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder = Builders.containerBuilder();
+ containerBuilder.withNodeIdentifier(attributes.getIdentifier());
// First filter out non-transitive attributes
// FIXME: removes MULTI_EXIT_DISC, too.
- spliceTransitives(b, attributes);
+ spliceTransitives(containerBuilder, attributes);
- /*
- * This is very ugly, as our AS_PATH model is needlessly complex. The top-level container contains a list
- * of segments, each of which is a choice containing another list. Both are unkeyed lists, so we need to
- * perform a wholesale replace.
- */
- final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> sb = Builders.unkeyedListBuilder();
- sb.withNodeIdentifier(this.asPathSegments);
+ final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> segmentsBuilder = Builders.unkeyedListBuilder();
+ segmentsBuilder.withNodeIdentifier(this.asPathSegments);
final Optional<NormalizedNode<?, ?>> maybeOldAsSegments = NormalizedNodes.findNode(attributes, this.asPathContainer, this.asPathSegments);
if (maybeOldAsSegments.isPresent() && !((UnkeyedListNode) maybeOldAsSegments.get()).getValue().isEmpty()) {
- // Builder of inner list
- final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> ilb = Builders.unkeyedListBuilder();
- ilb.withNodeIdentifier(this.asPathSequence);
- ilb.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSequence).withChild(ImmutableNodes.leafNode(this.asPathId, localAs)).build());
/*
- * We need to check the first entry in the outer list, to check if the choice is a-list. If it is and its
- * total number of elements is less than 255, we need to modify that one. Otherwise we need to create a
- * new entry.
+ * We need to check the first segment.
+ * If it has as-set then new as-sequence with local AS is prepended.
+ * If it has as-sequence, we may add local AS when it has less than 255 elements.
+ * Otherwise we need to create new as-sequence for local AS.
*/
+
+ final ListNodeBuilder<Object,LeafSetEntryNode<Object>> asSequenceBuilder = Builders.orderedLeafSetBuilder();
+ // add local AS
+ asSequenceBuilder.withNodeIdentifier(this.asPathSequence).addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.asNumberQname, localAs)).withValue(localAs).build());
+
final Iterator<UnkeyedListEntryNode> oldAsSegments = ((UnkeyedListNode) maybeOldAsSegments.get()).getValue().iterator();
final UnkeyedListEntryNode firstSegment = oldAsSegments.next();
- final Collection<UnkeyedListEntryNode> reusable = reusableSequence(firstSegment);
- if (reusable != null) {
- for (final UnkeyedListEntryNode child : reusable) {
- ilb.withChild(child);
+ final LeafSetNode<?> reusableAsSeq = reusableSegment(firstSegment);
+ // first segment contains as-sequence with less then 255 elements and it's append to local AS
+ if (reusableAsSeq != null) {
+ for (final LeafSetEntryNode<?> child : reusableAsSeq.getValue()) {
+ asSequenceBuilder.withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.asNumberQname, child.getValue())).withValue(child.getValue()).build());
}
}
-
- // Builder of inner container
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> icb = Builders.containerBuilder();
- icb.withNodeIdentifier(this.asPathList);
- icb.withChild(ilb.build());
-
- // Choice inside the outer list
- final DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> ocb = Builders.choiceBuilder();
- ocb.withNodeIdentifier(this.asPathChoice);
- ocb.withChild(icb.build());
-
// Add the new first segment
- sb.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(ocb.build()).build());
+ segmentsBuilder.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(asSequenceBuilder.build()).build());
- // If we did not merge into the original segment, add it
- if (reusable == null) {
- sb.withChild(firstSegment);
+ // When first segment contains as-set or full as-sequence, append it
+ if (reusableAsSeq == null) {
+ segmentsBuilder.withChild(firstSegment);
}
// Add all subsequent segments
while (oldAsSegments.hasNext()) {
- sb.withChild(oldAsSegments.next());
+ segmentsBuilder.withChild(oldAsSegments.next());
}
} else {
// Segments are completely empty, create a completely new AS_PATH container with
// a single entry
- sb.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(
- Builders.choiceBuilder().withNodeIdentifier(this.asPathChoice).withChild(
- Builders.containerBuilder().withNodeIdentifier(this.asPathList).withChild(
- Builders.unkeyedListBuilder().withNodeIdentifier(this.asPathSequence).withChild(
- Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSequence).withChild(
- ImmutableNodes.leafNode(this.asPathId, localAs)).build()).build()).build()).build()).build());
-
+ segmentsBuilder.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(
+ Builders.orderedLeafSetBuilder().withNodeIdentifier(this.asPathSequence).addChild(
+ Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.asNumberQname, localAs)).withValue(localAs).build()).build()).build());
}
- b.withChild(Builders.containerBuilder().withNodeIdentifier(this.asPathContainer).withChild(sb.build()).build());
- return b.build();
+ containerBuilder.withChild(Builders.containerBuilder().withNodeIdentifier(this.asPathContainer).withChild(segmentsBuilder.build()).build());
+ return containerBuilder.build();
}
// Attributes when reflecting a route
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.SegmentsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.CSegment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequenceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASet;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASetBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
private final Collection<PathArgument> locPref;
private final Collection<PathArgument> med;
private final Collection<PathArgument> orig;
- private final NodeIdentifier cSegmentNid;
- private final NodeIdentifier aSetNid;
private final NodeIdentifier asSetNid;
- private final NodeIdentifier aListNid;
private final NodeIdentifier asSeqNid;
- private final NodeIdentifier asNid;
NamespaceSpecificIds(final QName namespace) {
NodeIdentifier container = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsPath.QNAME.getLocalName())));
leaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "value")));
this.orig = ImmutableList.<PathArgument>of(container, leaf);
- this.cSegmentNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, CSegment.QNAME.getLocalName())));
- this.aSetNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, ASet.QNAME.getLocalName())));
this.asSetNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "as-set")));
- this.aListNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AList.QNAME.getLocalName())));
- this.asSeqNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsSequence.QNAME.getLocalName())));
- this.asNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "as")));
+ this.asSeqNid = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "as-sequence")));
}
Collection<PathArgument> getAsPath() {
return this.orig;
}
- NodeIdentifier getCSegment() {
- return this.cSegmentNid;
- }
-
- NodeIdentifier getASet() {
- return this.aSetNid;
- }
-
NodeIdentifier getAsSet() {
return this.asSetNid;
}
- NodeIdentifier getAList() {
- return this.aListNid;
- }
-
NodeIdentifier getAsSeq() {
return this.asSeqNid;
}
-
- NodeIdentifier getAs() {
- return this.asNid;
- }
}
private static final Logger LOG = LoggerFactory.getLogger(BestPathState.class);
int count = 0;
boolean setPresent = false;
for (final Segments s : segments) {
- if (s.getCSegment() instanceof ASetCase) {
+ if (s.getAsSet() != null && !setPresent) {
setPresent = true;
- } else {
- final AListCase list = (AListCase) s.getCSegment();
- count += list.getAList().getAsSequence().size();
+ count++;
+ } else if (s.getAsSequence() != null) {
+ count += s.getAsSequence().size();
}
}
- return (setPresent) ? count + 1 : count;
+ return count;
}
private static AsNumber getPeerAs(final List<Segments> segments) {
if (segments.isEmpty()) {
- return null;
+ return new AsNumber(0L);
}
- final AListCase first = (AListCase) segments.get(0).getCSegment();
- return first.getAList().getAsSequence().get(0).getAs();
+ for (final Segments seg : segments) {
+ if (seg.getAsSequence() != null && !seg.getAsSequence().isEmpty()) {
+ return segments.get(0).getAsSequence().get(0);
+ }
+ }
+ return new AsNumber(0L);
}
@VisibleForTesting
public List<Segments> extractSegments(final UnkeyedListNode segments) {
// list segments
final List<Segments> extracted = new ArrayList<>();
- for (final UnkeyedListEntryNode seg : segments.getValue()) {
- CSegment cs = null;
- // choice c-segment
- final ChoiceNode segmentType = (ChoiceNode) seg.getChild(this.ids.getCSegment()).get();
- if (segmentType.getChild(this.ids.getASet()).isPresent()) {
- // container a-set
- cs = extractAsSet(segmentType.getChild(this.ids.getASet()).get());
- } else if (segmentType.getChild(this.ids.getAList()).isPresent()) {
- // container a-list
- cs = extractAsSequence(segmentType.getChild(this.ids.getAList()).get());
- }
- extracted.add(new SegmentsBuilder().setCSegment(cs).build());
+ for (final UnkeyedListEntryNode segment : segments.getValue()) {
+ final SegmentsBuilder sb = new SegmentsBuilder();
+ // We are expecting that segment contains either as-sequence or as-set, so just one of them will be set, other would be null
+ sb.setAsSequence(extractAsList(segment, this.ids.getAsSeq())).setAsSet(extractAsList(segment, this.ids.getAsSet()));
+ extracted.add(sb.build());
}
return extracted;
}
- private CSegment extractAsSet(final DataContainerChild<? extends PathArgument, ?> container) {
+ private List<AsNumber> extractAsList(final UnkeyedListEntryNode segment, final NodeIdentifier nid) {
final List<AsNumber> ases = new ArrayList<>();
- // leaf-list a-set
- final Optional<NormalizedNode<?, ?>> maybeSet = NormalizedNodes.findNode(container, this.ids.getAsSet());
- if (maybeSet.isPresent()) {
- final LeafSetNode<?> list = (LeafSetNode<?>)maybeSet.get();
+ final Optional<NormalizedNode<?, ?>> maybeAsList = NormalizedNodes.findNode(segment, nid);
+ if (maybeAsList.isPresent()) {
+ final LeafSetNode<?> list = (LeafSetNode<?>)maybeAsList.get();
for (final LeafSetEntryNode<?> as : list.getValue()) {
ases.add(new AsNumber((Long)as.getValue()));
}
+ return ases;
}
- return new ASetCaseBuilder().setASet(new ASetBuilder().setAsSet(ases).build()).build();
- }
-
- private CSegment extractAsSequence(final DataContainerChild<? extends PathArgument, ?> container) {
- final List<AsSequence> ases = new ArrayList<>();
- // list as-sequence
- final Optional<NormalizedNode<?, ?>> maybeSet = NormalizedNodes.findNode(container, this.ids.getAsSeq());
- if (maybeSet.isPresent()) {
- final UnkeyedListNode list = (UnkeyedListNode)maybeSet.get();
- // as-sequence
- for (final UnkeyedListEntryNode as : list.getValue()) {
- // as
- final Optional<NormalizedNode<?, ?>> maybeAsSeq = NormalizedNodes.findNode(as, this.ids.getAs());
- if (maybeAsSeq.isPresent()) {
- final LeafNode<?> asLeaf = (LeafNode<?>)maybeAsSeq.get();
- ases.add(new AsSequenceBuilder().setAs(new AsNumber((Long)asLeaf.getValue())).build());
- }
- }
- }
- return new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(ases).build()).build();
+ return null;
}
ContainerNode getAttributes() {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-
import java.util.Collection;
import java.util.Iterator;
-
import org.junit.Test;
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.message.rev130919.path.attributes.attributes.AsPath;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
static final NodeIdentifier ORIGINATOR_C_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, OriginatorId.QNAME.getLocalName()));
static final NodeIdentifier ORIGINATOR_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, "originator"));
-
@Test
public void testExportedAttributesSetFirst() {
final Long ourAs = 72L;
.addChild(Builders.containerBuilder().withNodeIdentifier(AS_PATH_NID)
.addChild(Builders.unkeyedListBuilder().withNodeIdentifier(BestPathSelectorTest.SEGMENTS_NID)
.addChild(BestPathSelectorTest.SET_SEGMENT)
- .addChild(BestPathSelectorTest.LIST_SEGMENT)
+ .addChild(BestPathSelectorTest.SEQ_SEGMENT)
.build())
.build())
.build();
final ContainerNode exportedAttributes = operations.exportedAttributes(attributesSetBefore, ourAs);
// make sure our AS is prepended to the list (as the AS-PATH starts with AS-SET)
- final UnkeyedListEntryNode as = checkAsList(exportedAttributes).getValue().iterator().next();
- assertTrue(as.getChild(BestPathSelectorTest.AS_NID).isPresent());
- assertEquals(ourAs, as.getChild(BestPathSelectorTest.AS_NID).get().getValue());
+ final LeafSetNode<?> list = checkFirstLeafList(exportedAttributes);
+ assertEquals(ourAs, list.getValue().iterator().next().getValue());
}
@Test
final ContainerNode attributesListBefore = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BestPathSelectorTest.ATTRS_EXTENSION_Q))
.addChild(Builders.containerBuilder().withNodeIdentifier(AS_PATH_NID)
.addChild(Builders.unkeyedListBuilder().withNodeIdentifier(BestPathSelectorTest.SEGMENTS_NID)
- .addChild(BestPathSelectorTest.LIST_SEGMENT)
+ .addChild(BestPathSelectorTest.SEQ_SEGMENT)
.addChild(BestPathSelectorTest.SET_SEGMENT)
.build())
.build())
final ContainerNode exportedAttributes = operations.exportedAttributes(attributesListBefore, ourAs);
// make sure our AS is appended to the a-list (as the AS-PATH starts with A-LIST)
- final Iterator<UnkeyedListEntryNode> as = checkAsList(exportedAttributes).getValue().iterator();
-
- final UnkeyedListEntryNode a1 = as.next();
- assertTrue(a1.getChild(BestPathSelectorTest.AS_NID).isPresent());
- assertEquals(ourAs, a1.getChild(BestPathSelectorTest.AS_NID).get().getValue());
-
- final UnkeyedListEntryNode a2 = as.next();
- assertTrue(a2.getChild(BestPathSelectorTest.AS_NID).isPresent());
- assertEquals(new Long(1), a2.getChild(BestPathSelectorTest.AS_NID).get().getValue());
-
- final UnkeyedListEntryNode a3 = as.next();
- assertTrue(a3.getChild(BestPathSelectorTest.AS_NID).isPresent());
- assertEquals(new Long(2), a3.getChild(BestPathSelectorTest.AS_NID).get().getValue());
-
- final UnkeyedListEntryNode a4 = as.next();
- assertTrue(a4.getChild(BestPathSelectorTest.AS_NID).isPresent());
- assertEquals(new Long(3), a4.getChild(BestPathSelectorTest.AS_NID).get().getValue());
+ final LeafSetNode<?> list = checkFirstLeafList(exportedAttributes);
+ final Iterator<?> iter = list.getValue().iterator();
+ assertEquals(ourAs, ((LeafSetEntryNode<?>)iter.next()).getValue());
+ assertEquals(1L, ((LeafSetEntryNode<?>)iter.next()).getValue());
+ assertEquals(2L, ((LeafSetEntryNode<?>)iter.next()).getValue());
+ assertEquals(3L, ((LeafSetEntryNode<?>)iter.next()).getValue());
}
@Test
assertTrue(exportedAttributes.getChild(ORIGIN_NID).isPresent());
// AS-PATH should also be there with our AS
- final Collection<UnkeyedListEntryNode> asList = checkAsList(exportedAttributes).getValue();
- assertEquals(1, asList.size());
- final UnkeyedListEntryNode as = asList.iterator().next();
- assertTrue(as.getChild(BestPathSelectorTest.AS_NID).isPresent());
- assertEquals(ourAs, as.getChild(BestPathSelectorTest.AS_NID).get().getValue());
+ final LeafSetNode<?> list = checkFirstLeafList(exportedAttributes);
+ assertEquals(1, list.getValue().size());
+ assertEquals(ourAs, list.getValue().iterator().next().getValue());
// Atomic Aggregate should be filtered out
assertFalse(exportedAttributes.getChild(ATOMIC_NID).isPresent());
}
- private UnkeyedListNode checkAsList(final ContainerNode exportedAttributes) {
+ private LeafSetNode<?> checkFirstLeafList(final ContainerNode exportedAttributes) {
assertTrue(NormalizedNodes.findNode(exportedAttributes, AS_PATH_NID, BestPathSelectorTest.SEGMENTS_NID).isPresent());
final UnkeyedListNode segments = (UnkeyedListNode) NormalizedNodes.findNode(exportedAttributes, AS_PATH_NID, BestPathSelectorTest.SEGMENTS_NID).get();
final UnkeyedListEntryNode seg = segments.getValue().iterator().next();
- assertTrue(NormalizedNodes.findNode(seg, BestPathSelectorTest.C_SEGMENTS_NID, BestPathSelectorTest.A_LIST_NID, BestPathSelectorTest.AS_SEQ_NID).isPresent());
- final UnkeyedListNode list = (UnkeyedListNode) NormalizedNodes.findNode(seg, BestPathSelectorTest.C_SEGMENTS_NID, BestPathSelectorTest.A_LIST_NID, BestPathSelectorTest.AS_SEQ_NID).get();
- return list;
+ final DataContainerChild<? extends PathArgument, ?> firstLeafList = seg.getValue().iterator().next();
+ return (LeafSetNode<?>) firstLeafList;
}
@Test
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.SegmentsBuilder;
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.types.rev130919.BgpOrigin;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.CSegment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.AListCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.ASetCaseBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequenceBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASet;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.set._case.ASetBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
static final QName AS_NUMBER_Q = QName.create(ATTRS_EXTENSION_Q, "as-number");
static final NodeIdentifier SEGMENTS_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, Segments.QNAME.getLocalName()));
- static final NodeIdentifier C_SEGMENTS_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, CSegment.QNAME.getLocalName()));
- static final NodeIdentifier AS_SET_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, "as-set"));
- static final NodeIdentifier A_SET_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, ASet.QNAME.getLocalName()));
- static final NodeIdentifier A_LIST_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, AList.QNAME.getLocalName()));
- static final NodeIdentifier AS_SEQ_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, AsSequence.QNAME.getLocalName()));
- static final NodeIdentifier AS_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, "as"));
+ static final NodeIdentifier SET_LEAFLIST_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, "as-set"));
+ static final NodeIdentifier SEQ_LEAFLIST_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q, "as-sequence"));
static final UnkeyedListEntryNode SET_SEGMENT = Builders.unkeyedListEntryBuilder().withNodeIdentifier(SEGMENTS_NID)
- .addChild(Builders.choiceBuilder().withNodeIdentifier(C_SEGMENTS_NID)
- .addChild(Builders.containerBuilder().withNodeIdentifier(A_SET_NID)
- .addChild(Builders.leafSetBuilder().withNodeIdentifier(AS_SET_NID)
- .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 10L)).withValue(10L).build())
- .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 11L)).withValue(11L).build())
- .build())
- .build())
- .build())
- .build();
-
- static final UnkeyedListEntryNode LIST_SEGMENT = Builders.unkeyedListEntryBuilder().withNodeIdentifier(SEGMENTS_NID)
- .addChild(Builders.choiceBuilder().withNodeIdentifier(C_SEGMENTS_NID)
- .addChild(Builders.containerBuilder().withNodeIdentifier(A_LIST_NID)
- .addChild(Builders.unkeyedListBuilder().withNodeIdentifier(AS_SEQ_NID)
- .addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(AS_SEQ_NID)
- .addChild(Builders.leafBuilder().withNodeIdentifier(AS_NID).withValue(1L).build())
- .build())
- .addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(AS_SEQ_NID)
- .addChild(Builders.leafBuilder().withNodeIdentifier(AS_NID).withValue(2L).build())
- .build())
- .addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(AS_SEQ_NID)
- .addChild(Builders.leafBuilder().withNodeIdentifier(AS_NID).withValue(3L).build())
- .build())
- .build())
- .build())
- .build())
- .build();
+ .addChild(Builders.leafSetBuilder().withNodeIdentifier(SET_LEAFLIST_NID)
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 10L)).withValue(10L).build())
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 11L)).withValue(11L).build())
+ .build()).build();
+
+ static final UnkeyedListEntryNode SEQ_SEGMENT = Builders.unkeyedListEntryBuilder().withNodeIdentifier(SEGMENTS_NID)
+ .addChild(Builders.orderedLeafSetBuilder().withNodeIdentifier(SEQ_LEAFLIST_NID)
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 1L)).withValue(1L).build())
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 2L)).withValue(2L).build())
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 3L)).withValue(3L).build())
+ .build()).build();
+
+ static final UnkeyedListEntryNode SEQ_SEGMENT2 = Builders.unkeyedListEntryBuilder().withNodeIdentifier(SEGMENTS_NID)
+ .addChild(Builders.orderedLeafSetBuilder().withNodeIdentifier(SEQ_LEAFLIST_NID)
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 20L)).withValue(20L).build())
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 2L)).withValue(2L).build())
+ .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(AS_NUMBER_Q, 3L)).withValue(3L).build())
+ .build()).build();
@Test
public void testBestPathForEquality() {
final BestPath processedPath = this.selector.result();
assertEquals(this.originBestPath.getRouterId(), processedPath.getRouterId());
- assertEquals(this.originBestPath.getState().getAsPathLength(), processedPath.getState().getAsPathLength());
assertEquals(this.originBestPath.getState().getLocalPref(), processedPath.getState().getLocalPref());
assertEquals(this.originBestPath.getState().getMultiExitDisc(), processedPath.getState().getMultiExitDisc());
assertEquals(this.originBestPath.getState().getOrigin(), processedPath.getState().getOrigin());
assertEquals(this.originBestPath.getState().getPeerAs(), processedPath.getState().getPeerAs());
+ assertEquals(this.originBestPath.getState().getAsPathLength(), processedPath.getState().getAsPathLength());
}
@Test
processedPath = this.selector.result();
assertEquals(321L, processedPath.getState().getLocalPref().longValue());
- this.selector.processPath(this.ROUTER_ID2, createStateFromPrefMedOrigin()); // local-pref 123
+ addLowerLocalRef(); // prefer path with higher LOCAL_PREF
+ this.selector.processPath(this.ROUTER_ID2, this.dataContBuilder.build());
processedPath = this.selector.result();
assertEquals(321L, processedPath.getState().getLocalPref().longValue());
}
+ @Test
+ public void testBestPathSelectionOptions() {
+ this.selector.processPath(this.ROUTER_ID2, createStateFromPrefMedOriginASPath());
+ BestPath processedPath = this.selector.result();
+ assertEquals(1, processedPath.getState().getOrigin().getIntValue());
+
+ addIgpOrigin(); // prefer the path with the lowest origin type
+ this.selector.processPath(this.ROUTER_ID2, this.dataContBuilder.build());
+ processedPath = this.selector.result();
+ assertEquals(0, processedPath.getState().getOrigin().getIntValue());
+
+ addEgpOrigin();
+ this.selector.processPath(this.ROUTER_ID2, this.dataContBuilder.build());
+ processedPath = this.selector.result();
+ assertEquals(0, processedPath.getState().getOrigin().getIntValue());
+
+ // prefer the path with the lowest multi-exit discriminator (MED)
+ assertEquals(4321L, (long) processedPath.getState().getMultiExitDisc());
+ addIgpOrigin();
+ addLowerMultiExitDisc();
+ this.selector.processPath(this.ROUTER_ID2, this.dataContBuilder.build());
+ processedPath = this.selector.result();
+ assertEquals(1234L, (long) processedPath.getState().getMultiExitDisc());
+
+ addHigherMultiExitDisc();
+ this.selector.processPath(this.ROUTER_ID2, this.dataContBuilder.build());
+ processedPath = this.selector.result();
+ assertEquals(1234L, (long) processedPath.getState().getMultiExitDisc());
+
+ addLowerMultiExitDisc();
+ addAsPath(SEQ_SEGMENT2);
+ assertEquals(1L, (long) processedPath.getState().getPeerAs());
+ assertEquals(3, processedPath.getState().getAsPathLength());
+ this.selector.processPath(this.ROUTER_ID2, this.dataContBuilder.build());
+ processedPath = this.selector.result();
+ assertEquals(1L, (long) processedPath.getState().getPeerAs());
+ assertEquals(3, processedPath.getState().getAsPathLength());
+ }
+
@Test
public void testBestPathForNonEquality() {
this.selector.processPath(this.ROUTER_ID3, createStateFromPrefMedOrigin());
addHigherLocalRef();
addHigherMultiExitDisc();
addEgpOrigin();
- addAsPath(LIST_SEGMENT);
+ addAsPath(SEQ_SEGMENT);
return this.dataContBuilder.build();
}
this.dataContBuilder.addChild(asPathContBuilder.build());
}
+
private static DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createContBuilder(final QName qname) {
return ImmutableContainerNodeSchemaAwareBuilder.create().withNodeIdentifier(new NodeIdentifier(qname));
}
final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = Builders.unkeyedListBuilder();
builder.withNodeIdentifier(SEGMENTS_NID);
builder.addChild(SET_SEGMENT);
- builder.addChild(LIST_SEGMENT).build();
+ builder.addChild(SEQ_SEGMENT);
// expected
- final List<AsSequence> sequences = new ArrayList<>();
- sequences.add(new AsSequenceBuilder().setAs(new AsNumber(1L)).build());
- sequences.add(new AsSequenceBuilder().setAs(new AsNumber(2L)).build());
- sequences.add(new AsSequenceBuilder().setAs(new AsNumber(3L)).build());
+ final List<AsNumber> sequences = new ArrayList<>();
+ sequences.add(new AsNumber(1L));
+ sequences.add(new AsNumber(2L));
+ sequences.add(new AsNumber(3L));
final List<Segments> expected = new ArrayList<>();
- expected.add(new SegmentsBuilder().setCSegment(new ASetCaseBuilder().setASet(new ASetBuilder().setAsSet(Lists.newArrayList(new AsNumber(11L), new AsNumber(10L))).build()).build()).build());
- expected.add(new SegmentsBuilder().setCSegment(new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(sequences).build()).build()).build());
+ expected.add(new SegmentsBuilder().setAsSet(Lists.newArrayList(new AsNumber(11L), new AsNumber(10L))).build());
+ expected.add(new SegmentsBuilder().setAsSequence(sequences).build());
// test
final List<Segments> actual = this.state.extractSegments(builder.build());
assertEquals(expected.size(), actual.size());
assertEquals(Sets.newHashSet(1,2,3), Sets.newHashSet(1,3,2));
- assertEquals(Sets.newHashSet(((ASetCase)expected.get(0).getCSegment()).getASet().getAsSet()), Sets.newHashSet(((ASetCase)actual.get(0).getCSegment()).getASet().getAsSet()));
+ assertEquals(Sets.newHashSet(expected.get(0).getAsSet()), Sets.newHashSet(actual.get(0).getAsSet()));
assertEquals(expected.get(1), actual.get(1));
}