Propogate SR SID info from BGP-LS routes in RIB to link-state topology
[bgpcep.git] / bgp / topology-provider / src / test / java / org / opendaylight / bgpcep / bgp / topology / provider / LinkstateTopologyBuilderTest.java
1 /*
2  * Copyright (c) 2014 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.bgpcep.bgp.topology.provider;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
15 import static org.mockito.ArgumentMatchers.any;
16 import static org.mockito.Mockito.RETURNS_SMART_NULLS;
17 import static org.mockito.Mockito.doThrow;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.never;
20 import static org.mockito.Mockito.spy;
21 import static org.mockito.Mockito.timeout;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
25 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
26
27 import com.google.common.collect.Lists;
28 import io.netty.buffer.Unpooled;
29 import java.nio.charset.StandardCharsets;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.concurrent.ExecutionException;
34 import org.junit.After;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.opendaylight.mdsal.binding.api.DataTreeModification;
38 import org.opendaylight.mdsal.binding.api.WriteTransaction;
39 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.AdministrativeGroup;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Identifier;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4RouterIdentifier;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.IsisAreaIdentifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateSubsequentAddressFamily;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIdsBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptorsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.node._case.NodeDescriptorsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributesBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributesBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrCapabilitiesBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefixBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCaseBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCaseBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.uint24.rev200104.Uint24;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpLinkAttributes1;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpNodeAttributes1;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Link1;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Node1;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.link.attributes.IgpLinkAttributes;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.IgpNodeAttributes;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.Prefix;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
106 import org.opendaylight.yangtools.yang.common.Uint16;
107 import org.opendaylight.yangtools.yang.common.Uint32;
108 import org.opendaylight.yangtools.yang.common.Uint64;
109 import org.opendaylight.yangtools.yang.common.Uint8;
110
111 public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
112
113     private static final String ROUTER_1_ID = "127.0.0.1";
114     private static final String ROUTER_2_ID = "127.0.0.2";
115     private static final String NODE_1_PREFIX = "127.0.1.1/32";
116     private static final AsNumber NODE_1_AS = new AsNumber(Uint32.ONE);
117     private static final AsNumber NODE_2_AS = new AsNumber(Uint32.TWO);
118     private static final String NODE_1_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=1&router=0000.0102.0304";
119     private static final String NODE_2_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=2";
120     private static final String NODE_1_OSPF_ID = "bgpls://Ospf:1/type=node&as=1&router=0000.0102.0304";
121     private static final String NODE_2_OSPF_ID = "bgpls://Ospf:1/type=node&as=2";
122     private static final Identifier IDENTIFIER = new Identifier(Uint64.ONE);
123     private static final long LISTENER_RESTART_TIME = 20000;
124     private static final int LISTENER_ENFORCE_COUNTER = 2;
125     private static final int SRGB_START = 90000;
126     private static final int SRGB_RANGE = 16;
127     private static final int NODE_SID_INDEX = 4;
128     private static final int ADJ_SID = 24001;
129
130     private LinkstateTopologyBuilder linkstateTopoBuilder;
131     private InstanceIdentifier<Tables> tablePathIID;
132     private String linkstateNodeRouteKey;
133     private String linkstatePrefixRouteKey;
134     private String linkstateLinkRouteKey;
135     private InstanceIdentifier<LinkstateRoute> linkstateNodeRouteIID;
136     private InstanceIdentifier<LinkstateRoute> linkstatePrefixRouteIID;
137     private InstanceIdentifier<LinkstateRoute> linkstateLinkRouteIID;
138
139     @Before
140     @Override
141     public void setUp() {
142         super.setUp();
143         this.linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
144             LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
145         this.linkstateTopoBuilder.start();
146         this.tablePathIID =
147                 LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
148                         .child(Tables.class,
149                                 new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))
150                         .build();
151         this.linkstateNodeRouteKey = getLinkstateRouteKey("node-route");
152         this.linkstatePrefixRouteKey = getLinkstateRouteKey("prefix-route");
153         this.linkstateLinkRouteKey = getLinkstateRouteKey("link-route");
154         this.linkstateNodeRouteIID = createLinkstateRouteIID(this.linkstateNodeRouteKey);
155         this.linkstatePrefixRouteIID = createLinkstateRouteIID(this.linkstatePrefixRouteKey);
156         this.linkstateLinkRouteIID = createLinkstateRouteIID(this.linkstateLinkRouteKey);
157     }
158
159     @After
160     public void tearDown() throws Exception {
161         this.linkstateTopoBuilder.close();
162         checkNotPresentOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier());
163     }
164
165     @Test
166     public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
167         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
168             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
169             return topology;
170         });
171     }
172
173     @Test
174     @SuppressWarnings("checkstyle:LineLength")
175     public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
176         // create node
177         updateLinkstateRoute(this.linkstateNodeRouteIID,
178                 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
179         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
180             assertEquals(1, topology.getNode().size());
181             final Node node1 = topology.getNode().get(0);
182             assertEquals(NODE_1_ISIS_ID, node1.getNodeId().getValue());
183             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
184             assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
185             assertEquals("node1", igpNode1.getName().getValue());
186             final IgpNodeAttributes1 igpNodeAttributes1 = igpNode1.augmentation(IgpNodeAttributes1.class);
187             assertEquals("0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId()
188                     .getValue());
189             assertEquals(ROUTER_1_ID, igpNodeAttributes1.getIsisNodeAttributes().getTed().getTeRouterIdIpv4()
190                     .getValue());
191             assertEquals("47.0000.0000.0000.0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes()
192                     .getNet().get(0).getValue());
193             assertNull(igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
194                     .topology.rev131021.IgpNodeAttributes1.class));
195             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
196             assertNull(node1.augmentation(
197                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
198             return topology;
199         });
200
201         // create link
202         updateLinkstateRoute(this.linkstateLinkRouteIID,
203                 createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
204         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
205             assertEquals(1, topology.getLink().size());
206             final Link link1 = topology.getLink().get(0);
207             assertEquals(2, topology.getNode().size());
208             assertEquals(1, topology.getNode().get(0).getTerminationPoint().size());
209             assertEquals(1, topology.getNode().get(1).getTerminationPoint().size());
210             assertEquals("bgpls://IsisLevel2:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as"
211                     + "=2&mt=1", link1.getLinkId().getValue());
212             assertEquals(NODE_1_ISIS_ID, link1.getSource().getSourceNode().getValue());
213             assertEquals(NODE_2_ISIS_ID, link1.getDestination().getDestNode().getValue());
214             final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
215             assertEquals("link1", igpLink1.getName());
216             assertEquals((short) 1, igpLink1.augmentation(IgpLinkAttributes1.class).getIsisLinkAttributes()
217                     .getMultiTopologyId().shortValue());
218             assertNull(igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
219                     .topology.rev131021.IgpLinkAttributes1.class));
220             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
221             assertEquals(2, topology.getNode().size());
222             final Node srcNode;
223             if (topology.getNode().get(0).getNodeId().getValue().contains("0000.0102.0304")) {
224                 srcNode = topology.getNode().get(0);
225             } else {
226                 srcNode = topology.getNode().get(1);
227             }
228             assertEquals(1, srcNode.augmentation(
229                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
230                     .getSegments().size());
231             assertEquals(ADJ_SID, link1.augmentation(
232                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
233                     .getSegment().getValue().intValue());
234             return topology;
235         });
236         removeLinkstateRoute(this.linkstateLinkRouteIID);
237
238         // update node
239         updateLinkstateRoute(this.linkstateNodeRouteIID,
240                 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node", NODE_1_AS, ROUTER_2_ID));
241         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
242             assertEquals(1, topology.getNode().size());
243             final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
244                     .getIgpNodeAttributes();
245             assertEquals(ROUTER_2_ID, igpNode2.getRouterId().get(0).getIpv4Address().getValue());
246             assertEquals("updated-node", igpNode2.getName().getValue());
247             return topology;
248         });
249
250         // remove
251         removeLinkstateRoute(this.linkstateNodeRouteIID);
252         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
253             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
254             assertNull(topology.getNode());
255             assertNull(topology.getLink());
256             return topology;
257         });
258     }
259
260     @Test
261     @SuppressWarnings("checkstyle:LineLength")
262     public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
263         // create node
264         updateLinkstateRoute(this.linkstateNodeRouteIID,
265                 createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
266         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
267             assertEquals(1, topology.getNode().size());
268             final Node node1 = topology.getNode().get(0);
269             assertEquals(NODE_1_OSPF_ID, node1.getNodeId().getValue());
270             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
271             assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
272             assertEquals("node1", igpNode1.getName().getValue());
273             assertNull(igpNode1.augmentation(IgpNodeAttributes1.class));
274             assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
275                     .yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
276                     .getTeRouterIdIpv4().getValue());
277             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
278             assertNull(node1.augmentation(
279                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
280             return topology;
281         });
282
283         // update node with prefix
284         updateLinkstateRoute(this.linkstatePrefixRouteIID,
285                 createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX, 500L, ROUTER_1_ID));
286         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
287             final Node node1 = topology.getNode().get(0);
288             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
289             assertEquals(1, igpNode1.getPrefix().size());
290             final Prefix prefix = igpNode1.getPrefix().get(0);
291             assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
292             assertEquals(500L, prefix.getMetric().longValue());
293             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
294             assertEquals(1, node1.augmentation(
295                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
296                     .getSegments().size());
297             assertEquals(SRGB_START + NODE_SID_INDEX, node1.augmentation(
298                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
299                     .getSegments().get(0).getSegmentId().getValue().intValue());
300             return topology;
301         });
302
303         // create link
304         updateLinkstateRoute(this.linkstateLinkRouteIID,
305                 createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
306         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
307             assertEquals(1, topology.getLink().size());
308             final Link link1 = topology.getLink().get(0);
309             assertEquals(2, topology.getNode().size());
310             assertEquals(1, topology.getNode().get(0).getTerminationPoint().size());
311             assertEquals(1, topology.getNode().get(1).getTerminationPoint().size());
312             assertEquals("bgpls://Ospf:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as=2&mt=1",
313                     link1.getLinkId().getValue());
314             assertEquals(NODE_1_OSPF_ID, link1.getSource().getSourceNode().getValue());
315             assertEquals(NODE_2_OSPF_ID, link1.getDestination().getDestNode().getValue());
316             final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
317             assertEquals("link1", igpLink1.getName());
318             assertNull(igpLink1.augmentation(IgpLinkAttributes1.class));
319             assertEquals((short) 1, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
320                     .ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getMultiTopologyId()
321                     .shortValue());
322             assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
323                     .yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
324                     .getSrlgValues().size());
325             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
326             assertEquals(2, topology.getNode().size());
327             final Node srcNode;
328             if (topology.getNode().get(0).getNodeId().getValue().contains("0000.0102.0304")) {
329                 srcNode = topology.getNode().get(0);
330             } else {
331                 srcNode = topology.getNode().get(1);
332             }
333             assertEquals(2, srcNode.augmentation(
334                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
335                     .getSegments().size());
336             assertEquals(ADJ_SID, link1.augmentation(
337                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
338                     .getSegment().getValue().intValue());
339             return topology;
340         });
341     }
342
343     /**
344      * This test is to verify if the AbstractTopologyBuilder/LinkstateTopologyBuilder is handling exception correctly.
345      */
346     @Test
347     @SuppressWarnings("checkstyle:IllegalCatch")
348     public void testRouteChangedError() throws Exception {
349         final LinkstateTopologyBuilder spiedLinkstateTopologyBuilder = spy(this.linkstateTopoBuilder);
350         doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
351         try {
352             spiedLinkstateTopologyBuilder.routeChanged(null, null);
353             fail("Mockito failed to spy routeChanged() method");
354         } catch (final Exception e) {
355             assertTrue(e instanceof RuntimeException);
356         }
357         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
358         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
359         // first we examine if the chain is being reset when no exception is thrown
360         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
361         verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
362         verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
363         verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
364         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
365         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
366         // now pass some invalid data to cause onDataTreeChanged fail
367         final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
368         final List<DataTreeModification<LinkstateRoute>> changes = new ArrayList<>();
369         changes.add(modification);
370         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
371         // one restart transaction chain check in onDataTreeChanged()
372         // we are introducing some timeout here as transaction may be executed in a delay manner
373         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
374         verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
375         assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
376         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
377         final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
378         // call again with empty change to invoke restartTransactionChainOnDemand()
379         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
380         verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
381         // transaction chain should be reset while listener should not
382         verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
383         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
384         // now apply a change with bad modification again
385         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
386         verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
387         // listener scheduled again
388         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
389         // listener timer shouldn't have changed
390         assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
391         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
392         verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
393         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
394         Thread.sleep(LISTENER_RESTART_TIME);
395         // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
396         spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
397         assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
398                 + LISTENER_RESTART_TIME);
399         verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
400         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
401         // enforce counter get increased
402         assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
403         verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
404         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
405         // sleep to let the listener restart timer times out
406         Thread.sleep(LISTENER_RESTART_TIME);
407         // apply a good modification (empty change)
408         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
409         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
410         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
411         verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
412         // listener restarted didn't get rescheduled again
413         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
414         verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
415         verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
416     }
417
418     private static String getLinkstateRouteKey(final String routeKey) {
419         return Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(routeKey)).array().toString();
420     }
421
422     private InstanceIdentifier<LinkstateRoute> createLinkstateRouteIID(final String linkstateRouteKey) {
423         return this.tablePathIID.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
424                 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey)).build();
425     }
426
427     private void updateLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID,
428             final LinkstateRoute data) {
429         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
430         wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID, data);
431         wTx.commit();
432     }
433
434     private void removeLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID) {
435         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
436         wTx.delete(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID);
437         wTx.commit();
438     }
439
440     private LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
441             final AsNumber asNumber, final String ipv4RouterId) {
442         return createBaseBuilder(this.linkstateNodeRouteKey, protocolId)
443                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
444                         .rev200120.linkstate.object.type.NodeCaseBuilder()
445                         .setNodeDescriptors(new NodeDescriptorsBuilder()
446                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
447                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
448                                         .build())
449                                 .setAsNumber(asNumber).build()).build())
450                 .setAttributes(new AttributesBuilder()
451                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
452                         .addAugmentation(Attributes1.class, new Attributes1Builder()
453                                 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
454                                         .setNodeAttributes(new NodeAttributesBuilder()
455                                                 .setDynamicHostname(nodeName)
456                                                 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
457                                                 .setIsisAreaId(Collections.singletonList(
458                                                         new IsisAreaIdentifier(new byte[]{0x47})))
459                                                 .setSrCapabilities(new SrCapabilitiesBuilder()
460                                                         .setRangeSize(new Uint24(Uint32.valueOf(SRGB_RANGE)))
461                                                         .setSidLabelIndex(new LocalLabelCaseBuilder()
462                                                                 .setLocalLabel(
463                                                                         new MplsLabel(Uint32.valueOf(SRGB_START)))
464                                                                 .build())
465                                                         .build())
466                                                 .build()).build()).build()).build()).build();
467     }
468
469     private LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
470             final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
471         return createBaseBuilder(this.linkstatePrefixRouteKey, protocolId)
472             .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
473                     .linkstate.object.type.PrefixCaseBuilder()
474                 .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder()
475                         .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
476                                 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
477                                 .build()).setAsNumber(asNumber).build())
478                 .setPrefixDescriptors(new PrefixDescriptorsBuilder()
479                         .setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
480             .setAttributes(new AttributesBuilder()
481                 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
482                 .addAugmentation(Attributes1.class, new Attributes1Builder()
483                         .setLinkStateAttribute(new PrefixAttributesCaseBuilder()
484                             .setPrefixAttributes(new PrefixAttributesBuilder()
485                                 .setOspfForwardingAddress(new IpAddressNoZone(new Ipv4AddressNoZone(ospfFwdAddress)))
486                                 .setPrefixMetric(new IgpMetric(Uint32.valueOf(igpMetric)))
487                                 .setSrPrefix(new SrPrefixBuilder()
488                                         .setAlgorithm(Algorithm.ShortestPathFirst)
489                                         .setSidLabelIndex(new SidCaseBuilder()
490                                                 .setSid(Uint32.valueOf(NODE_SID_INDEX)).build())
491                                         .build())
492                                 .build())
493                             .build())
494                         .build())
495                 .build())
496             .build();
497     }
498
499     private LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
500             final AsNumber remoteAs, final String linkName) {
501         return createBaseBuilder(this.linkstateLinkRouteKey, protocolId)
502                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
503                         .rev200120.linkstate.object.type.LinkCaseBuilder()
504                         .setLocalNodeDescriptors(new LocalNodeDescriptorsBuilder().setAsNumber(localAs)
505                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
506                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4}))
507                                         .build()).build()).build())
508                         .setRemoteNodeDescriptors(new RemoteNodeDescriptorsBuilder().setAsNumber(remoteAs).build())
509                         .setLinkDescriptors(new LinkDescriptorsBuilder()
510                                 .setMultiTopologyId(new TopologyIdentifier(Uint16.ONE)).build()).build())
511                 .setAttributes(new AttributesBuilder()
512                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
513                         .addAugmentation(Attributes1.class, new Attributes1Builder()
514                                 .setLinkStateAttribute(new LinkAttributesCaseBuilder()
515                                     .setLinkAttributes(new LinkAttributesBuilder()
516                                         .setSharedRiskLinkGroups(Lists.newArrayList(
517                                             new SrlgId(Uint32.valueOf(5)), new SrlgId(Uint32.valueOf(15))))
518                                         .setAdminGroup(new AdministrativeGroup(Uint32.ZERO))
519                                         .setMaxLinkBandwidth(
520                                                 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0xff}))
521                                         .setMaxReservableBandwidth(
522                                                 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0x1f}))
523                                         .setUnreservedBandwidth(Lists.newArrayList(new UnreservedBandwidthBuilder()
524                                                 .withKey(new UnreservedBandwidthKey(Uint8.ONE))
525                                                 .setBandwidth(new Bandwidth(new byte[]{0x00, 0x00, 0x00, (byte) 0xff}))
526                                                 .build()))
527                                         .setTeMetric(new TeMetric(Uint32.valueOf(100)))
528                                         .setLinkName(linkName)
529                                         .setSrAdjIds(Collections.singletonList(new SrAdjIdsBuilder()
530                                                 .setSidLabelIndex(new LocalLabelCaseBuilder()
531                                                         .setLocalLabel(new MplsLabel(Uint32.valueOf(ADJ_SID)))
532                                                         .build())
533                                                 .build()))
534                                         .build())
535                                     .build())
536                                 .build())
537                         .build())
538                 .build();
539     }
540
541     private static LinkstateRouteBuilder createBaseBuilder(final String linkstateRouteKey,
542             final ProtocolId protocolId) {
543         return new LinkstateRouteBuilder()
544             .setIdentifier(IDENTIFIER)
545             .withKey(new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey))
546             .setRouteKey(linkstateRouteKey)
547             .setProtocolId(protocolId);
548     }
549 }