2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.bgpcep.bgp.topology.provider;
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.assertThrows;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.Mockito.CALLS_REAL_METHODS;
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.timeout;
21 import static org.mockito.Mockito.times;
22 import static org.mockito.Mockito.verify;
23 import static org.mockito.Mockito.withSettings;
24 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
25 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
27 import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Iterables;
29 import io.netty.buffer.Unpooled;
30 import java.nio.charset.StandardCharsets;
31 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.mockito.MockMakers;
38 import org.opendaylight.mdsal.binding.api.DataTreeModification;
39 import org.opendaylight.mdsal.binding.api.WriteTransaction;
40 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.types.rev171204.Uint24;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.AdministrativeGroup;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Identifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4RouterIdentifier;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.IsisAreaIdentifier;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateSubsequentAddressFamily;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIdsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.node._case.NodeDescriptorsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
68 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;
69 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;
70 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;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrCapabilitiesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefixBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCaseBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCaseBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
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.binding.util.BindingMap;
107 import org.opendaylight.yangtools.yang.common.Uint16;
108 import org.opendaylight.yangtools.yang.common.Uint32;
109 import org.opendaylight.yangtools.yang.common.Uint64;
110 import org.opendaylight.yangtools.yang.common.Uint8;
112 public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
114 private static final String ROUTER_1_ID = "127.0.0.1";
115 private static final String ROUTER_2_ID = "127.0.0.2";
116 private static final String NODE_1_PREFIX = "127.0.1.1/32";
117 private static final AsNumber NODE_1_AS = new AsNumber(Uint32.ONE);
118 private static final AsNumber NODE_2_AS = new AsNumber(Uint32.TWO);
119 private static final String NODE_1_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=1&router=0000.0102.0304";
120 private static final String NODE_2_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=2";
121 private static final String NODE_1_OSPF_ID = "bgpls://Ospf:1/type=node&as=1&router=0000.0102.0304";
122 private static final String NODE_2_OSPF_ID = "bgpls://Ospf:1/type=node&as=2";
123 private static final Identifier IDENTIFIER = new Identifier(Uint64.ONE);
124 private static final long LISTENER_RESTART_TIME = 20000;
125 private static final int LISTENER_ENFORCE_COUNTER = 2;
126 private static final int SRGB_START = 90000;
127 private static final int SRGB_RANGE = 16;
128 private static final int NODE_SID_INDEX = 4;
129 private static final int ADJ_SID = 24001;
131 private LinkstateTopologyBuilder linkstateTopoBuilder;
132 private InstanceIdentifier<Tables> tablePathIID;
133 private String linkstateNodeRouteKey;
134 private String linkstatePrefixRouteKey;
135 private String linkstateLinkRouteKey;
136 private InstanceIdentifier<LinkstateRoute> linkstateNodeRouteIID;
137 private InstanceIdentifier<LinkstateRoute> linkstatePrefixRouteIID;
138 private InstanceIdentifier<LinkstateRoute> linkstateLinkRouteIID;
142 public void setUp() {
144 linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
145 LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
146 linkstateTopoBuilder.start();
148 LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
150 new TablesKey(LinkstateAddressFamily.VALUE, LinkstateSubsequentAddressFamily.VALUE))
152 linkstateNodeRouteKey = getLinkstateRouteKey("node-route");
153 linkstatePrefixRouteKey = getLinkstateRouteKey("prefix-route");
154 linkstateLinkRouteKey = getLinkstateRouteKey("link-route");
155 linkstateNodeRouteIID = createLinkstateRouteIID(linkstateNodeRouteKey);
156 linkstatePrefixRouteIID = createLinkstateRouteIID(linkstatePrefixRouteKey);
157 linkstateLinkRouteIID = createLinkstateRouteIID(linkstateLinkRouteKey);
161 public void tearDown() throws Exception {
162 linkstateTopoBuilder.close();
163 checkNotPresentOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier());
167 public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
168 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
169 assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
175 public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
177 updateLinkstateRoute(linkstateNodeRouteIID,
178 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
179 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
180 assertEquals(1, topology.nonnullNode().size());
181 final Node node1 = topology.nonnullNode().values().iterator().next();
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().iterator().next().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()
189 assertEquals(ROUTER_1_ID, igpNodeAttributes1.getIsisNodeAttributes().getTed().getTeRouterIdIpv4()
191 assertEquals("47.0000.0000.0000.0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes()
192 .getNet().iterator().next().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));
202 updateLinkstateRoute(linkstateLinkRouteIID,
203 createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
204 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
205 assertEquals(1, topology.nonnullLink().size());
206 final Link link1 = topology.nonnullLink().values().iterator().next();
207 assertEquals(2, topology.nonnullNode().size());
208 assertEquals(1, Iterables.get(topology.getNode().values(), 0).getTerminationPoint().size());
209 assertEquals(1, Iterables.get(topology.getNode().values(), 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());
223 if (topology.getNode().values().iterator().next().getNodeId().getValue().contains("0000.0102.0304")) {
224 srcNode = topology.getNode().values().iterator().next();
226 srcNode = Iterables.get(topology.getNode().values(), 1);
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());
236 removeLinkstateRoute(linkstateLinkRouteIID);
239 updateLinkstateRoute(linkstateNodeRouteIID,
240 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node", NODE_1_AS, ROUTER_2_ID));
241 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
242 assertEquals(1, topology.getNode().size());
243 final IgpNodeAttributes igpNode2 = topology.getNode().values().iterator().next().augmentation(Node1.class)
244 .getIgpNodeAttributes();
245 assertEquals(ROUTER_2_ID, igpNode2.getRouterId().iterator().next().getIpv4Address().getValue());
246 assertEquals("updated-node", igpNode2.getName().getValue());
251 removeLinkstateRoute(linkstateNodeRouteIID);
252 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
253 assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
254 assertNull(topology.getNode());
255 assertNull(topology.getLink());
261 public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
263 updateLinkstateRoute(linkstateNodeRouteIID,
264 createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
265 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
266 assertEquals(1, topology.nonnullNode().size());
267 final Node node1 = topology.nonnullNode().values().iterator().next();
268 assertEquals(NODE_1_OSPF_ID, node1.getNodeId().getValue());
269 final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
270 assertEquals(ROUTER_1_ID, igpNode1.getRouterId().iterator().next().getIpv4Address().getValue());
271 assertEquals("node1", igpNode1.getName().getValue());
272 assertNull(igpNode1.augmentation(IgpNodeAttributes1.class));
273 assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
274 .yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
275 .getTeRouterIdIpv4().getValue());
276 assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
277 assertNull(node1.augmentation(
278 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
282 // update node with prefix
283 updateLinkstateRoute(linkstatePrefixRouteIID,
284 createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX, 500L, ROUTER_1_ID));
285 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
286 final Node node1 = topology.nonnullNode().values().iterator().next();
287 final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
288 assertEquals(1, igpNode1.nonnullPrefix().size());
289 final Prefix prefix = igpNode1.nonnullPrefix().values().iterator().next();
290 assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
291 assertEquals(500L, prefix.getMetric().longValue());
292 assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
293 assertEquals(1, node1.augmentation(
294 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
295 .nonnullSegments().size());
296 assertEquals(SRGB_START + NODE_SID_INDEX, node1.augmentation(
297 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
298 .nonnullSegments().values().iterator().next().getSegmentId().getValue().intValue());
303 updateLinkstateRoute(linkstateLinkRouteIID,
304 createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
305 readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
306 assertEquals(1, topology.nonnullLink().size());
307 final Link link1 = topology.nonnullLink().values().iterator().next();
308 assertEquals(2, topology.getNode().size());
309 assertEquals(1, Iterables.get(topology.getNode().values(), 0).getTerminationPoint().size());
310 assertEquals(1, Iterables.get(topology.getNode().values(), 1).getTerminationPoint().size());
311 assertEquals("bgpls://Ospf:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as=2&mt=1",
312 link1.getLinkId().getValue());
313 assertEquals(NODE_1_OSPF_ID, link1.getSource().getSourceNode().getValue());
314 assertEquals(NODE_2_OSPF_ID, link1.getDestination().getDestNode().getValue());
315 final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
316 assertEquals("link1", igpLink1.getName());
317 assertNull(igpLink1.augmentation(IgpLinkAttributes1.class));
318 assertEquals((short) 1, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
319 .ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getMultiTopologyId()
321 assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
322 .yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
323 .getSrlgValues().size());
324 assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
325 assertEquals(2, topology.getNode().size());
327 if (topology.getNode().values().iterator().next().getNodeId().getValue().contains("0000.0102.0304")) {
328 srcNode = topology.getNode().values().iterator().next();
330 srcNode = Iterables.get(topology.getNode().values(), 1);
332 assertEquals(2, srcNode.augmentation(
333 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
334 .getSegments().size());
335 assertEquals(ADJ_SID, link1.augmentation(
336 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
337 .getSegment().getValue().intValue());
343 * This test is to verify if the AbstractTopologyBuilder/LinkstateTopologyBuilder is handling exception correctly.
346 public void testRouteChangedError() throws Exception {
347 // FIXME: this is a very weird setup and does not work with inline mockmaker
348 // perhaps that is because of https://github.com/mockito/mockito/issues/2488, but we should be able to
349 // rework this test in some other way (i.e. pure mocking with real classes)?
350 final var spiedLinkstateTopologyBuilder = mock(LinkstateTopologyBuilder.class,
351 // this part is the same as spy(), but ...
352 withSettings().spiedInstance(linkstateTopoBuilder).defaultAnswer(CALLS_REAL_METHODS)
353 // ... here we use a different MockMaker
354 .mockMaker(MockMakers.SUBCLASS));
355 doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
356 // Verify throws spying
357 assertThrows(RuntimeException.class, () -> spiedLinkstateTopologyBuilder.routeChanged(null, null));
359 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
360 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
361 // first we examine if the chain is being reset when no exception is thrown
362 spiedLinkstateTopologyBuilder.onDataTreeChanged(List.of());
363 verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
364 verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
365 verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
366 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
367 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
368 // now pass some invalid data to cause onDataTreeChanged fail
369 final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
370 final List<DataTreeModification<LinkstateRoute>> changes = List.of(modification);
371 spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
372 // one restart transaction chain check in onDataTreeChanged()
373 // we are introducing some timeout here as transaction may be executed in a delay manner
374 verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
375 verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
376 assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
377 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
378 final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
379 // call again with empty change to invoke restartTransactionChainOnDemand()
380 spiedLinkstateTopologyBuilder.onDataTreeChanged(List.of());
381 verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
382 // transaction chain should be reset while listener should not
383 verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
384 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
385 // now apply a change with bad modification again
386 spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
387 verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
388 // listener scheduled again
389 verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
390 // listener timer shouldn't have changed
391 assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
392 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
393 verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
394 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
395 Thread.sleep(LISTENER_RESTART_TIME);
396 // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
397 spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
398 assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
399 + LISTENER_RESTART_TIME);
400 verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
401 verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
402 // enforce counter get increased
403 assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
404 verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
405 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
406 // sleep to let the listener restart timer times out
407 Thread.sleep(LISTENER_RESTART_TIME);
408 // apply a good modification (empty change)
409 spiedLinkstateTopologyBuilder.onDataTreeChanged(List.of());
410 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
411 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
412 verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
413 // listener restarted didn't get rescheduled again
414 verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
415 verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
416 verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
419 private static String getLinkstateRouteKey(final String routeKey) {
420 return Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(routeKey)).array().toString();
423 private InstanceIdentifier<LinkstateRoute> createLinkstateRouteIID(final String linkstateRouteKey) {
424 return tablePathIID.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
425 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey)).build();
428 private void updateLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID,
429 final LinkstateRoute data) {
430 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
431 wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID, data);
435 private void removeLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID) {
436 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
437 wTx.delete(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID);
441 private LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
442 final AsNumber asNumber, final String ipv4RouterId) {
443 return createBaseBuilder(linkstateNodeRouteKey, protocolId)
444 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
445 .rev200120.linkstate.object.type.NodeCaseBuilder()
446 .setNodeDescriptors(new NodeDescriptorsBuilder()
447 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
448 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
450 .setAsNumber(asNumber).build()).build())
451 .setAttributes(new AttributesBuilder()
452 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
453 .addAugmentation(new Attributes1Builder()
454 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
455 .setNodeAttributes(new NodeAttributesBuilder()
456 .setDynamicHostname(nodeName)
457 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
458 .setIsisAreaId(Set.of(new IsisAreaIdentifier(new byte[]{0x47})))
459 .setSrCapabilities(new SrCapabilitiesBuilder()
460 .setRangeSize(new Uint24(Uint32.valueOf(SRGB_RANGE)))
461 .setSidLabelIndex(new LocalLabelCaseBuilder()
463 new MplsLabel(Uint32.valueOf(SRGB_START)))
466 .build()).build()).build()).build()).build();
469 private LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
470 final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
471 return createBaseBuilder(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(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())
499 private LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
500 final AsNumber remoteAs, final String linkName) {
501 return createBaseBuilder(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(new Attributes1Builder()
514 .setLinkStateAttribute(new LinkAttributesCaseBuilder()
515 .setLinkAttributes(new LinkAttributesBuilder()
516 .setSharedRiskLinkGroups(ImmutableSet.of(
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(BindingMap.of(new UnreservedBandwidthBuilder()
524 .withKey(new UnreservedBandwidthKey(Uint8.ONE))
525 .setBandwidth(new Bandwidth(new byte[]{0x00, 0x00, 0x00, (byte) 0xff}))
527 .setTeMetric(new TeMetric(Uint32.valueOf(100)))
528 .setLinkName(linkName)
529 .setSrAdjIds(List.of(new SrAdjIdsBuilder()
530 .setSidLabelIndex(new LocalLabelCaseBuilder()
531 .setLocalLabel(new MplsLabel(Uint32.valueOf(ADJ_SID)))
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);