BUG-2823: Simplify AS_PATH encoding
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / protocol / bgp / rib / impl / AttributeOperationsTest.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertTrue;
13 import java.util.Collection;
14 import java.util.Iterator;
15 import org.junit.Test;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AtomicAggregate;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.ClusterId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.OriginatorId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
28 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
30 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
32 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
33 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
34 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
35 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
36
37 public class AttributeOperationsTest {
38
39     static final NodeIdentifier ORIGIN_NID = new NodeIdentifier(QName.cachedReference(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, Origin.QNAME.getLocalName())));
40     static final NodeIdentifier ORIGIN_VALUE_NID = new NodeIdentifier(QName.cachedReference(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, "value")));
41     static final NodeIdentifier AS_PATH_NID = new NodeIdentifier(QName.cachedReference(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, AsPath.QNAME.getLocalName())));
42     static final NodeIdentifier ATOMIC_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, AtomicAggregate.QNAME.getLocalName()));
43     static final NodeIdentifier CLUSTER_C_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, ClusterId.QNAME.getLocalName()));
44     static final NodeIdentifier CLUSTER_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, "cluster"));
45     static final NodeIdentifier ORIGINATOR_C_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, OriginatorId.QNAME.getLocalName()));
46     static final NodeIdentifier ORIGINATOR_NID = new NodeIdentifier(QName.create(BestPathSelectorTest.ATTRS_EXTENSION_Q, "originator"));
47
48     @Test
49     public void testExportedAttributesSetFirst() {
50         final Long ourAs = 72L;
51         final ContainerNode attributesSetBefore = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BestPathSelectorTest.ATTRS_EXTENSION_Q))
52             .addChild(Builders.containerBuilder().withNodeIdentifier(AS_PATH_NID)
53                 .addChild(Builders.unkeyedListBuilder().withNodeIdentifier(BestPathSelectorTest.SEGMENTS_NID)
54                     .addChild(BestPathSelectorTest.SET_SEGMENT)
55                     .addChild(BestPathSelectorTest.SEQ_SEGMENT)
56                     .build())
57             .build())
58             .build();
59         final AttributeOperations operations  = AttributeOperations.getInstance(attributesSetBefore);
60         final ContainerNode exportedAttributes = operations.exportedAttributes(attributesSetBefore, ourAs);
61
62         // make sure our AS is prepended to the list (as the AS-PATH starts with AS-SET)
63         final LeafSetNode<?> list = checkFirstLeafList(exportedAttributes);
64         assertEquals(ourAs, list.getValue().iterator().next().getValue());
65     }
66
67     @Test
68     public void testExportedAttributesListFirst() {
69         final Long ourAs = 72L;
70         final ContainerNode attributesListBefore = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BestPathSelectorTest.ATTRS_EXTENSION_Q))
71             .addChild(Builders.containerBuilder().withNodeIdentifier(AS_PATH_NID)
72                 .addChild(Builders.unkeyedListBuilder().withNodeIdentifier(BestPathSelectorTest.SEGMENTS_NID)
73                     .addChild(BestPathSelectorTest.SEQ_SEGMENT)
74                     .addChild(BestPathSelectorTest.SET_SEGMENT)
75                     .build())
76             .build())
77             .build();
78         final AttributeOperations operations  = AttributeOperations.getInstance(attributesListBefore);
79         final ContainerNode exportedAttributes = operations.exportedAttributes(attributesListBefore, ourAs);
80
81         // make sure our AS is appended to the a-list (as the AS-PATH starts with A-LIST)
82         final LeafSetNode<?> list = checkFirstLeafList(exportedAttributes);
83         final Iterator<?> iter = list.getValue().iterator();
84         assertEquals(ourAs, ((LeafSetEntryNode<?>)iter.next()).getValue());
85         assertEquals(1L, ((LeafSetEntryNode<?>)iter.next()).getValue());
86         assertEquals(2L, ((LeafSetEntryNode<?>)iter.next()).getValue());
87         assertEquals(3L, ((LeafSetEntryNode<?>)iter.next()).getValue());
88     }
89
90     @Test
91     public void testExportedAttributesEmptyWithTransitive() {
92         final Long ourAs = 72L;
93         final ContainerNode attributesSetBefore = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BestPathSelectorTest.ATTRS_EXTENSION_Q))
94             .addChild(Builders.containerBuilder().withNodeIdentifier(ORIGIN_NID)
95                 .addChild(Builders.leafBuilder().withNodeIdentifier(ORIGIN_VALUE_NID).withValue(BgpOrigin.Egp).build())
96             .build())
97             .addChild(Builders.containerBuilder().withNodeIdentifier(AS_PATH_NID)
98                 .addChild(Builders.unkeyedListBuilder().withNodeIdentifier(BestPathSelectorTest.SEGMENTS_NID).build())
99             .build())
100             .addChild(Builders.containerBuilder().withNodeIdentifier(ATOMIC_NID).build())
101             .build();
102         final AttributeOperations operations  = AttributeOperations.getInstance(attributesSetBefore);
103         final ContainerNode exportedAttributes = operations.exportedAttributes(attributesSetBefore, ourAs);
104
105         // Origin should be within exportedAttributes as it is Transitive
106         assertTrue(exportedAttributes.getChild(ORIGIN_NID).isPresent());
107
108         // AS-PATH should also be there with our AS
109         final LeafSetNode<?> list = checkFirstLeafList(exportedAttributes);
110         assertEquals(1, list.getValue().size());
111         assertEquals(ourAs, list.getValue().iterator().next().getValue());
112
113         // Atomic Aggregate should be filtered out
114         assertFalse(exportedAttributes.getChild(ATOMIC_NID).isPresent());
115     }
116
117     private LeafSetNode<?> checkFirstLeafList(final ContainerNode exportedAttributes) {
118         assertTrue(NormalizedNodes.findNode(exportedAttributes, AS_PATH_NID, BestPathSelectorTest.SEGMENTS_NID).isPresent());
119         final UnkeyedListNode segments = (UnkeyedListNode) NormalizedNodes.findNode(exportedAttributes, AS_PATH_NID, BestPathSelectorTest.SEGMENTS_NID).get();
120         final UnkeyedListEntryNode seg = segments.getValue().iterator().next();
121         final DataContainerChild<? extends PathArgument, ?> firstLeafList = seg.getValue().iterator().next();
122         return (LeafSetNode<?>) firstLeafList;
123     }
124
125     @Test
126     public void testReflectedAttributesOriginatorAndClusterNotPresent() {
127         final Ipv4Address originatorId = new Ipv4Address("127.0.0.2");
128         final ClusterIdentifier clusterId = new ClusterIdentifier("10.10.10.10");
129         final ContainerNode attributes = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BestPathSelectorTest.ATTRS_EXTENSION_Q))
130             .addChild(Builders.containerBuilder().withNodeIdentifier(ORIGIN_NID)
131                 .addChild(Builders.leafBuilder().withNodeIdentifier(ORIGIN_VALUE_NID).withValue(BgpOrigin.Egp).build())
132             .build())
133             .build();
134         final AttributeOperations operations  = AttributeOperations.getInstance(attributes);
135         final ContainerNode reflectedAttributes = operations.reflectedAttributes(attributes, originatorId, clusterId);
136
137         // Origin should be within reflectedAttributes as part of original attributes
138         assertTrue(reflectedAttributes.getChild(ORIGIN_NID).isPresent());
139
140         // ClusterIdentifier should be prepended
141         final Collection<?> clusters = checkCluster(reflectedAttributes).getValue();
142         assertEquals(1, clusters.size());
143         assertEquals(clusterId, ((LeafSetEntryNode<?>)clusters.iterator().next()).getValue());
144
145         // OriginatorId should be added
146         assertTrue(reflectedAttributes.getChild(ORIGINATOR_C_NID).isPresent());
147         assertEquals(originatorId.getValue(), ((ContainerNode)reflectedAttributes.getChild(ORIGINATOR_C_NID).get()).getChild(ORIGINATOR_NID).get().getValue());
148     }
149
150     @Test
151     public void testReflectedAttributesOriginatorAndClusterPresent() {
152         final Ipv4Address originatorId = new Ipv4Address("127.0.0.2");
153         final ClusterIdentifier ourClusterId = new ClusterIdentifier("1.1.1.1");
154         final ClusterIdentifier clusterId1 = new ClusterIdentifier("10.10.10.10");
155         final ClusterIdentifier clusterId2 = new ClusterIdentifier("11.11.11.11");
156         final ContainerNode attributes = Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(BestPathSelectorTest.ATTRS_EXTENSION_Q))
157             .addChild(Builders.containerBuilder().withNodeIdentifier(ORIGINATOR_C_NID)
158                 .addChild(Builders.leafBuilder().withNodeIdentifier(ORIGINATOR_NID).withValue("127.0.0.2").build())
159             .build())
160             .addChild(Builders.containerBuilder().withNodeIdentifier(CLUSTER_C_NID)
161                 .addChild(Builders.orderedLeafSetBuilder().withNodeIdentifier(CLUSTER_NID)
162                     .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(CLUSTER_NID.getNodeType(), clusterId1)).withValue(clusterId1).build())
163                     .addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(CLUSTER_NID.getNodeType(), clusterId2)).withValue(clusterId2).build())
164                 .build())
165             .build())
166             .build();
167         final AttributeOperations operations  = AttributeOperations.getInstance(attributes);
168         final ContainerNode reflectedAttributes = operations.reflectedAttributes(attributes, originatorId, ourClusterId);
169
170         // ClusterIdentifier should be prepended and other entries should be preserved
171         final Collection<?> clusters = checkCluster(reflectedAttributes).getValue();
172         assertEquals(3, clusters.size());
173         final Iterator<?> cl = clusters.iterator();
174
175         final LeafSetEntryNode<?> c1 = (LeafSetEntryNode<?>) cl.next();
176         assertEquals(ourClusterId, c1.getValue());
177
178         final LeafSetEntryNode<?> c2 = (LeafSetEntryNode<?>) cl.next();
179         assertEquals(clusterId1, c2.getValue());
180
181         final LeafSetEntryNode<?> c3 = (LeafSetEntryNode<?>) cl.next();
182         assertEquals(clusterId2, c3.getValue());
183
184         // OriginatorId should be the same
185         assertTrue(reflectedAttributes.getChild(ORIGINATOR_C_NID).isPresent());
186         assertEquals(originatorId.getValue(), ((ContainerNode)reflectedAttributes.getChild(ORIGINATOR_C_NID).get()).getChild(ORIGINATOR_NID).get().getValue());
187     }
188
189     private LeafSetNode<?> checkCluster(final ContainerNode reflectedAttributes) {
190         assertTrue(reflectedAttributes.getChild(CLUSTER_C_NID).isPresent());
191         final ContainerNode clusterContainer = (ContainerNode) reflectedAttributes.getChild(CLUSTER_C_NID).get();
192         final LeafSetNode<?> clusters = (LeafSetNode<?>) clusterContainer.getChild(CLUSTER_NID).get();
193         return clusters;
194     }
195 }