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.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.RETURNS_SMART_NULLS;
18 import static org.mockito.Mockito.doThrow;
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.never;
21 import static org.mockito.Mockito.spy;
22 import static org.mockito.Mockito.timeout;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
26 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
28 import com.google.common.collect.Lists;
29 import io.netty.buffer.Unpooled;
30 import java.math.BigInteger;
31 import java.nio.charset.StandardCharsets;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.concurrent.ExecutionException;
36 import org.junit.After;
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.opendaylight.mdsal.binding.api.DataTreeModification;
40 import org.opendaylight.mdsal.binding.api.WriteTransaction;
41 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.AdministrativeGroup;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.Identifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.Ipv4RouterIdentifier;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.IsisAreaIdentifier;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.LinkstateAddressFamily;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.LinkstateSubsequentAddressFamily;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.ProtocolId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.TopologyIdentifier;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.attribute.UnreservedBandwidthBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.attribute.UnreservedBandwidthKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.LinkDescriptorsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.node._case.NodeDescriptorsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributesBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.LinkstateRoutes;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.LinkstateRoute;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.LinkstateRouteBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.LinkstateRouteKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.linkstate.route.Attributes1;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.PathId;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.OriginBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.BgpOrigin;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpLinkAttributes1;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpNodeAttributes1;
92 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Link1;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Node1;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.link.attributes.IgpLinkAttributes;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.IgpNodeAttributes;
98 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;
99 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
101 public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
103 private static final String LINKSTATE_ROUTE_KEY = Unpooled.wrappedBuffer(
104 StandardCharsets.UTF_8.encode("linkstate-route")).array().toString();
105 private static final String ROUTER_1_ID = "127.0.0.1";
106 private static final String ROUTER_2_ID = "127.0.0.2";
107 private static final String NODE_1_PREFIX = "127.0.1.1/32";
108 private static final AsNumber NODE_1_AS = new AsNumber(1L);
109 private static final AsNumber NODE_2_AS = new AsNumber(2L);
110 private static final String NODE_1_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=1&router=0000.0102.0304";
111 private static final String NODE_2_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=2";
112 private static final String NODE_1_OSPF_ID = "bgpls://Ospf:1/type=node&as=1&router=0000.0102.0304";
113 private static final String NODE_2_OSPF_ID = "bgpls://Ospf:1/type=node&as=2";
114 private static final Identifier IDENTIFIER = new Identifier(new BigInteger("1"));
115 private static final long LISTENER_RESTART_TIME = 20000;
116 private static final int LISTENER_ENFORCE_COUNTER = 2;
118 private LinkstateTopologyBuilder linkstateTopoBuilder;
119 private InstanceIdentifier<LinkstateRoute> linkstateRouteIID;
123 public void setUp() {
125 this.linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
126 LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
127 this.linkstateTopoBuilder.start();
128 final InstanceIdentifier<Tables> path = LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
129 .child(Tables.class, new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))
131 this.linkstateRouteIID = path.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
132 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(0L), LINKSTATE_ROUTE_KEY))
138 public void tearDown() throws Exception {
139 this.linkstateTopoBuilder.close();
140 checkNotPresentOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier());
144 public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
145 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
146 assertNotNull(topology.getTopologyTypes().augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight
147 .params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1.class));
148 assertNotNull(topology.getTopologyTypes().augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight
149 .params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1.class)
150 .getBgpLinkstateTopology());
156 public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
158 updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
159 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
160 assertEquals(1, topology.getNode().size());
161 final Node node1 = topology.getNode().get(0);
162 assertEquals(NODE_1_ISIS_ID, node1.getNodeId().getValue());
163 final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
164 assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
165 assertEquals("node1", igpNode1.getName().getValue());
166 final IgpNodeAttributes1 igpNodeAttributes1 = igpNode1.augmentation(IgpNodeAttributes1.class);
167 assertEquals("0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId()
169 assertEquals(ROUTER_1_ID, igpNodeAttributes1.getIsisNodeAttributes().getTed().getTeRouterIdIpv4()
171 assertEquals("47.0000.0000.0000.0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes()
172 .getNet().get(0).getValue());
173 assertNull(igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
174 .topology.rev131021.IgpNodeAttributes1.class));
180 updateLinkstateRoute(createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
181 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
182 assertEquals(1, topology.getLink().size());
183 final Link link1 = topology.getLink().get(0);
184 assertEquals(2, topology.getNode().size());
185 assertEquals(1, topology.getNode().get(0).getTerminationPoint().size());
186 assertEquals(1, topology.getNode().get(1).getTerminationPoint().size());
187 assertEquals("bgpls://IsisLevel2:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as"
188 + "=2&mt=1", link1.getLinkId().getValue());
189 assertEquals(NODE_1_ISIS_ID, link1.getSource().getSourceNode().getValue());
190 assertEquals(NODE_2_ISIS_ID, link1.getDestination().getDestNode().getValue());
191 final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
192 assertEquals("link1", igpLink1.getName());
193 assertEquals((short) 1, igpLink1.augmentation(IgpLinkAttributes1.class).getIsisLinkAttributes()
194 .getMultiTopologyId().shortValue());
195 assertNull(igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
196 .topology.rev131021.IgpLinkAttributes1.class));
202 updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node",
203 NODE_1_AS, ROUTER_2_ID));
204 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
205 assertEquals(1, topology.getNode().size());
206 final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
207 .getIgpNodeAttributes();
208 assertEquals(ROUTER_2_ID, igpNode2.getRouterId().get(0).getIpv4Address().getValue());
209 assertEquals("updated-node", igpNode2.getName().getValue());
214 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
215 wTx.delete(LogicalDatastoreType.OPERATIONAL, this.linkstateRouteIID);
217 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
218 assertNull(topology.getNode());
219 assertNull(topology.getLink());
225 public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
227 updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
228 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
229 assertEquals(1, topology.getNode().size());
230 final Node node1 = topology.getNode().get(0);
231 assertEquals(NODE_1_OSPF_ID, node1.getNodeId().getValue());
232 final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
233 assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
234 assertEquals("node1", igpNode1.getName().getValue());
235 assertNull(igpNode1.augmentation(IgpNodeAttributes1.class));
236 assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
237 .yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
238 .getTeRouterIdIpv4().getValue());
242 // update node with prefix
243 updateLinkstateRoute(createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX,
245 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
246 final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
247 .getIgpNodeAttributes();
248 assertEquals(1, igpNode2.getPrefix().size());
249 final Prefix prefix = igpNode2.getPrefix().get(0);
250 assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
251 assertEquals(500L, prefix.getMetric().longValue());
257 updateLinkstateRoute(createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
258 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
259 assertEquals(1, topology.getLink().size());
260 final Link link1 = topology.getLink().get(0);
261 assertEquals(2, topology.getNode().size());
262 assertEquals(1, topology.getNode().get(0).getTerminationPoint().size());
263 assertEquals(1, topology.getNode().get(1).getTerminationPoint().size());
264 assertEquals("bgpls://Ospf:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as=2&mt=1",
265 link1.getLinkId().getValue());
266 assertEquals(NODE_1_OSPF_ID, link1.getSource().getSourceNode().getValue());
267 assertEquals(NODE_2_OSPF_ID, link1.getDestination().getDestNode().getValue());
268 final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
269 assertEquals("link1", igpLink1.getName());
270 assertNull(igpLink1.augmentation(IgpLinkAttributes1.class));
271 assertEquals((short) 1, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
272 .ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getMultiTopologyId()
274 assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
275 .yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
276 .getSrlgValues().size());
284 * This test is to verify if the AbstractTopologyBuilder/LinkstateTopologyBuilder is handling exception correctly.
287 @SuppressWarnings("checkstyle:IllegalCatch")
288 public void testRouteChangedError() throws Exception {
289 final LinkstateTopologyBuilder spiedLinkstateTopologyBuilder = spy(this.linkstateTopoBuilder);
290 doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
292 spiedLinkstateTopologyBuilder.routeChanged(null, null);
293 fail("Mockito failed to spy routeChanged() method");
294 } catch (final Exception e) {
295 assertTrue(e instanceof RuntimeException);
297 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
298 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
299 // first we examine if the chain is being reset when no exception is thrown
300 spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
301 verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
302 verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
303 verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
304 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
305 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
306 // now pass some invalid data to cause onDataTreeChanged fail
307 final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
308 final List<DataTreeModification<LinkstateRoute>> changes = new ArrayList<>();
309 changes.add(modification);
310 spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
311 // one restart transaction chain check in onDataTreeChanged()
312 // we are introducing some timeout here as transaction may be executed in a delay manner
313 verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
314 verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
315 assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
316 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
317 final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
318 // call again with empty change to invoke restartTransactionChainOnDemand()
319 spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
320 verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
321 // transaction chain should be reset while listener should not
322 verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
323 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
324 // now apply a change with bad modification again
325 spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
326 verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
327 // listener scheduled again
328 verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
329 // listener timer shouldn't have changed
330 assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
331 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
332 verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
333 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
334 Thread.sleep(LISTENER_RESTART_TIME);
335 // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
336 spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
337 assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
338 + LISTENER_RESTART_TIME);
339 verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
340 verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
341 // enforce counter get increased
342 assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
343 verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
344 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
345 // sleep to let the listener restart timer times out
346 Thread.sleep(LISTENER_RESTART_TIME);
347 // apply a good modification (empty change)
348 spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
349 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
350 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
351 verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
352 // listener restarted didn't get rescheduled again
353 verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
354 verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
355 verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
358 private void updateLinkstateRoute(final LinkstateRoute data) {
359 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
360 wTx.put(LogicalDatastoreType.OPERATIONAL, this.linkstateRouteIID, data, true);
364 private static LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
365 final AsNumber asNumber, final String ipv4RouterId) {
366 return createBaseBuilder(protocolId)
367 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
368 .rev180329.linkstate.object.type.NodeCaseBuilder()
369 .setNodeDescriptors(new NodeDescriptorsBuilder()
370 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
371 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
373 .setAsNumber(asNumber).build()).build())
374 .setAttributes(new AttributesBuilder()
375 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
376 .addAugmentation(Attributes1.class, new Attributes1Builder()
377 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
378 .setNodeAttributes(new NodeAttributesBuilder()
379 .setDynamicHostname(nodeName)
380 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
381 .setIsisAreaId(Collections.singletonList(
382 new IsisAreaIdentifier(new byte[]{0x47})))
383 .build()).build()).build()).build()).build();
386 private static LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
387 final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
388 return createBaseBuilder(protocolId)
389 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329
390 .linkstate.object.type.PrefixCaseBuilder()
391 .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder().setAsNumber(asNumber).build())
392 .setPrefixDescriptors(new PrefixDescriptorsBuilder()
393 .setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
394 .setAttributes(new AttributesBuilder()
395 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
396 .addAugmentation(Attributes1.class, new Attributes1Builder()
397 .setLinkStateAttribute(new PrefixAttributesCaseBuilder().setPrefixAttributes(
398 new PrefixAttributesBuilder().setOspfForwardingAddress(new IpAddress(
399 new Ipv4Address(ospfFwdAddress))).setPrefixMetric(new IgpMetric(igpMetric))
400 .build()).build()).build()).build()).build();
403 private static LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
404 final AsNumber remoteAs, final String linkName) {
405 return createBaseBuilder(protocolId)
406 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
407 .rev180329.linkstate.object.type.LinkCaseBuilder()
408 .setLocalNodeDescriptors(new LocalNodeDescriptorsBuilder().setAsNumber(localAs)
409 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
410 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4}))
411 .build()).build()).build())
412 .setRemoteNodeDescriptors(new RemoteNodeDescriptorsBuilder().setAsNumber(remoteAs).build())
413 .setLinkDescriptors(new LinkDescriptorsBuilder()
414 .setMultiTopologyId(new TopologyIdentifier(1)).build()).build())
415 .setAttributes(new AttributesBuilder()
416 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
417 .addAugmentation(Attributes1.class, new Attributes1Builder()
418 .setLinkStateAttribute(new LinkAttributesCaseBuilder().setLinkAttributes(
419 new LinkAttributesBuilder().setSharedRiskLinkGroups(
420 Lists.newArrayList(new SrlgId(5L), new SrlgId(15L)))
421 .setAdminGroup(new AdministrativeGroup(0L))
422 .setMaxLinkBandwidth(
423 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0xff}))
424 .setMaxReservableBandwidth(
425 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0x1f}))
426 .setUnreservedBandwidth(Lists.newArrayList(new UnreservedBandwidthBuilder()
427 .withKey(new UnreservedBandwidthKey((short) 1))
428 .setBandwidth(new Bandwidth(new byte[]{0x00, 0x00, 0x00, (byte) 0xff}))
430 .setTeMetric(new TeMetric(100L)).setLinkName(linkName).build()).build())
436 private static LinkstateRouteBuilder createBaseBuilder(final ProtocolId protocolId) {
437 return new LinkstateRouteBuilder()
438 .setIdentifier(IDENTIFIER)
439 .withKey(new LinkstateRouteKey(new PathId(0L), LINKSTATE_ROUTE_KEY))
440 .setRouteKey(LINKSTATE_ROUTE_KEY)
441 .setProtocolId(protocolId);