Get rid of BestPathState FIXMEs. 13/22813/4
authorDana Kutenicsova <dkutenic@cisco.com>
Wed, 17 Jun 2015 18:29:00 +0000 (20:29 +0200)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 17 Jun 2015 21:49:19 +0000 (21:49 +0000)
Created method to parse AsPath segments
from BI to BA.

Change-Id: Ibc49da3ddfb0ba5e1bb0a8da562c00e069df3923
Signed-off-by: Dana Kutenicsova <dkutenic@cisco.com>
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BestPathState.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/BestPathSelectorTest.java

index fdefeeb4d3a71dbec42d859f2ced138a72c8a790..d77590c1d8af11e58f093e205340aa1142e8ae8b 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.protocol.bgp.rib.impl;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.common.base.Optional;
@@ -14,6 +15,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Callable;
@@ -25,15 +27,29 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDisc;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
 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;
 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.UnkeyedListEntryNode;
@@ -43,13 +59,19 @@ import org.slf4j.LoggerFactory;
 
 @NotThreadSafe
 final class BestPathState {
-    private static final class AttributesCollection {
+    private static final class NamespaceSpecificIds {
         private final Collection<PathArgument> asPath;
         private final Collection<PathArgument> locPref;
         private final Collection<PathArgument> med;
         private final Collection<PathArgument> orig;
-
-        AttributesCollection(final QName namespace) {
+        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())));
             NodeIdentifier leaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "segments")));
             this.asPath = ImmutableList.<PathArgument>of(container, leaf);
@@ -65,6 +87,13 @@ final class BestPathState {
             container = new NodeIdentifier(QName.cachedReference(QName.create(namespace, Origin.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")));
         }
 
         Collection<PathArgument> getAsPath() {
@@ -82,28 +111,52 @@ final class BestPathState {
         Collection<PathArgument> getOrig() {
             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);
-    private static final Cache<QNameModule, AttributesCollection> PATH_CACHE = CacheBuilder.newBuilder().weakKeys().weakValues().build();
+    private static final Cache<QNameModule, NamespaceSpecificIds> PATH_CACHE = CacheBuilder.newBuilder().weakKeys().weakValues().build();
 
-    private static Long peerAs = 0L;
-    private static int asPathLength = 0;
+    private long peerAs = 0L;
+    private int asPathLength = 0;
 
     private final ContainerNode attributes;
-    private final AttributesCollection collection;
+    private final NamespaceSpecificIds ids;
     private Long localPref;
     private Long multiExitDisc;
     private BgpOrigin origin;
     private boolean resolved;
 
     BestPathState(final ContainerNode attributes) {
-        final AttributesCollection col;
+        final NamespaceSpecificIds col;
         try {
-            col = PATH_CACHE.get(attributes.getNodeType().getModule(), new Callable<AttributesCollection>() {
+            col = PATH_CACHE.get(attributes.getNodeType().getModule(), new Callable<NamespaceSpecificIds>() {
                 @Override
-                public AttributesCollection call() {
-                    return new AttributesCollection(attributes.getNodeType());
+                public NamespaceSpecificIds call() {
+                    return new NamespaceSpecificIds(attributes.getNodeType());
                 }
             });
         } catch (final ExecutionException e) {
@@ -112,7 +165,7 @@ final class BestPathState {
         }
 
         this.attributes = Preconditions.checkNotNull(attributes);
-        this.collection = col;
+        this.ids = col;
     }
 
     private static BgpOrigin fromString(final String originStr) {
@@ -133,42 +186,36 @@ final class BestPathState {
             return;
         }
 
-        final Optional<NormalizedNode<?, ?>> maybeLocalPref = NormalizedNodes.findNode(this.attributes, this.collection.getLocPref());
+        final Optional<NormalizedNode<?, ?>> maybeLocalPref = NormalizedNodes.findNode(this.attributes, this.ids.getLocPref());
         if (maybeLocalPref.isPresent()) {
             this.localPref = (Long) ((LeafNode<?>)maybeLocalPref.get()).getValue();
         } else {
             this.localPref = null;
         }
 
-        final Optional<NormalizedNode<?, ?>> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, this.collection.getMed());
+        final Optional<NormalizedNode<?, ?>> maybeMultiExitDisc = NormalizedNodes.findNode(this.attributes, this.ids.getMed());
         if (maybeMultiExitDisc.isPresent()) {
             this.multiExitDisc = (Long) ((LeafNode<?>)maybeMultiExitDisc.get()).getValue();
         } else {
             this.multiExitDisc = null;
         }
 
-        final Optional<NormalizedNode<?, ?>> maybeOrigin = NormalizedNodes.findNode(this.attributes, this.collection.getOrig());
+        final Optional<NormalizedNode<?, ?>> maybeOrigin = NormalizedNodes.findNode(this.attributes, this.ids.getOrig());
         if (maybeOrigin.isPresent()) {
             this.origin = fromString((String) ((LeafNode<?>)maybeOrigin.get()).getValue());
         } else {
             this.origin = null;
         }
 
-        final Optional<NormalizedNode<?, ?>> maybeSegments = NormalizedNodes.findNode(this.attributes, this.collection.getAsPath());
+        final Optional<NormalizedNode<?, ?>> maybeSegments = NormalizedNodes.findNode(this.attributes, this.ids.getAsPath());
         if (maybeSegments.isPresent()) {
             final UnkeyedListNode segments = (UnkeyedListNode) maybeSegments.get();
-
-            if (segments.getSize() != 0) {
-                // FIXME: peer AS number
-
-                // FIXME: asPathLength = countAsPath(this.bestState.getAsPath().getSegments());
-                final boolean haveSegment;
-                for (final UnkeyedListEntryNode s : segments.getValue()) {
-
-                }
+            final List<Segments> segs = extractSegments(segments);
+            if (segs.size() != 0) {
+                this.peerAs = getPeerAs(segs).getValue();
+                this.asPathLength = countAsPath(segs);
             }
         }
-
         this.resolved = true;
     }
 
@@ -189,12 +236,12 @@ final class BestPathState {
 
     Long getPeerAs() {
         resolveValues();
-        return peerAs;
+        return this.peerAs;
     }
 
     int getAsPathLength() {
         resolveValues();
-        return asPathLength;
+        return this.asPathLength;
     }
 
     private static int countAsPath(final List<Segments> segments) {
@@ -216,11 +263,62 @@ final class BestPathState {
         if (segments.isEmpty()) {
             return null;
         }
-
         final AListCase first = (AListCase) segments.get(0).getCSegment();
         return first.getAList().getAsSequence().get(0).getAs();
     }
 
+    @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());
+        }
+        return extracted;
+    }
+
+    private CSegment extractAsSet(final DataContainerChild<? extends PathArgument, ?> container) {
+        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();
+            for (final LeafSetEntryNode<?> as : list.getValue())  {
+                ases.add(new AsNumber(Long.valueOf((String)as.getValue())));
+            }
+        }
+        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.valueOf((String)asLeaf.getValue()))).build());
+                }
+            }
+        }
+        return new AListCaseBuilder().setAList(new AListBuilder().setAsSequence(ases).build()).build();
+    }
+
     ContainerNode getAttributes() {
         return this.attributes;
     }
index bfd1c35b928b92c7d8f659065a76bea2912032b6..dfcac0ae1c42d95e1629d0a7a66c491d3d84da56 100644 (file)
@@ -9,14 +9,36 @@ package org.opendaylight.protocol.bgp.rib.impl;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import com.google.common.primitives.UnsignedInteger;
+
+import java.util.ArrayList;
+import java.util.List;
+
 import org.junit.Test;
+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.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.rib.rev130925.PeerId;
+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;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 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.impl.ImmutableContainerNodeSchemaAwareBuilder;
@@ -126,4 +148,61 @@ public class BestPathSelectorTest {
         valueBuilder.withNodeIdentifier(new NodeIdentifier(QName.create(qname, localName))).withValue(value);
         return valueBuilder;
     }
+
+    @Test
+    public void testExtractSegments() {
+        final QName asNumberQ = QName.create(this.extensionQName, "as-number");
+        final NodeIdentifier segmentsNid = new NodeIdentifier(QName.create(this.extensionQName, Segments.QNAME.getLocalName()));
+        final NodeIdentifier cSegmentsNid = new NodeIdentifier(QName.create(this.extensionQName, CSegment.QNAME.getLocalName()));
+        final NodeIdentifier asSetNid = new NodeIdentifier(QName.create(this.extensionQName, "as-set"));
+        final NodeIdentifier aSetNid = new NodeIdentifier(QName.create(this.extensionQName, ASet.QNAME.getLocalName()));
+        final NodeIdentifier aListNid = new NodeIdentifier(QName.create(this.extensionQName, AList.QNAME.getLocalName()));
+        final NodeIdentifier asSeqNid = new NodeIdentifier(QName.create(this.extensionQName, AsSequence.QNAME.getLocalName()));
+        final NodeIdentifier asNid = new NodeIdentifier(QName.create(this.extensionQName, "as"));
+        // to be extracted from
+        final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = Builders.unkeyedListBuilder();
+        builder.withNodeIdentifier(segmentsNid);
+        builder.addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(segmentsNid)
+            .addChild(Builders.choiceBuilder().withNodeIdentifier(cSegmentsNid)
+                .addChild(Builders.containerBuilder().withNodeIdentifier(aSetNid)
+                    .addChild(Builders.leafSetBuilder().withNodeIdentifier(asSetNid)
+                        .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(asNumberQ, "10")).withValue("10").build())
+                        .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(asNumberQ, "11")).withValue("11").build())
+                    .build())
+                .build())
+            .build())
+        .build());
+        builder.addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(segmentsNid)
+            .addChild(Builders.choiceBuilder().withNodeIdentifier(cSegmentsNid)
+                .addChild(Builders.containerBuilder().withNodeIdentifier(aListNid)
+                    .addChild(Builders.unkeyedListBuilder().withNodeIdentifier(asSeqNid)
+                        .addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(asSeqNid)
+                            .addChild(Builders.leafBuilder().withNodeIdentifier(asNid).withValue("1").build())
+                        .build())
+                        .addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(asSeqNid)
+                            .addChild(Builders.leafBuilder().withNodeIdentifier(asNid).withValue("2").build())
+                        .build())
+                        .addChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(asSeqNid)
+                            .addChild(Builders.leafBuilder().withNodeIdentifier(asNid).withValue("3").build())
+                        .build())
+                    .build())
+                .build())
+            .build())
+        .build());
+
+        // 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<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());
+        // 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(expected.get(1), actual.get(1));
+    }
 }