29155d79d4c4b6a9984d9277ec42b2029449e107
[bgpcep.git] / pcep / tunnel / tunnel-provider / src / test / java / org / opendaylight / bgpcep / pcep / tunnel / provider / TunnelProgrammingTest.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.pcep.tunnel.provider;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.doReturn;
16
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.Executor;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.mockito.ArgumentMatchers;
26 import org.mockito.Mock;
27 import org.mockito.Mockito;
28 import org.mockito.junit.MockitoJUnitRunner;
29 import org.opendaylight.bgpcep.programming.spi.Instruction;
30 import org.opendaylight.bgpcep.programming.spi.InstructionScheduler;
31 import org.opendaylight.bgpcep.programming.spi.SchedulerException;
32 import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
33 import org.opendaylight.mdsal.binding.api.RpcProviderService;
34 import org.opendaylight.mdsal.binding.api.WriteTransaction;
35 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
36 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
37 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.topology.rev140113.NetworkTopologyRef;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.AdministrativeStatus;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.PcepCreateP2pTunnelInput1Builder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev200720.PcepUpdateTunnelInput1Builder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.ClassType;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.Ipv4Case;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.endpoints.address.family.ipv4._case.Ipv4;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.ero.Subobject;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev150720.InstructionStatus;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.programming.rev150720.SubmitInstructionInput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLsp;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.AddLspOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLsp;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.RemoveLspOutput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLsp;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.UpdateLspOutput;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.add.lsp.args.Arguments;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.p2p.rev130819.tunnel.p2p.path.cfg.attributes.ExplicitHops;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.p2p.rev130819.tunnel.p2p.path.cfg.attributes.ExplicitHopsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.PcepCreateP2pTunnelInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.PcepDestroyTunnelInputBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.PcepUpdateTunnelInputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.ExplicitHops1Builder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.Link1Builder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.SupportingNode1Builder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.tunnel.pcep.supporting.node.attributes.PathComputationClientBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.create.p2p.tunnel.input.DestinationBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.create.p2p.tunnel.input.SourceBuilder;
77 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
78 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
87 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
88 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
92 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1Builder;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.IgpTerminationPointAttributesBuilder;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.termination.point.type.IpBuilder;
95 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
96 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
97 import org.opendaylight.yangtools.yang.common.RpcResult;
98 import org.opendaylight.yangtools.yang.common.Uint32;
99 import org.opendaylight.yangtools.yang.common.Uint8;
100 import org.osgi.framework.BundleContext;
101
102 @RunWith(MockitoJUnitRunner.StrictStubs.class)
103 public class TunnelProgrammingTest extends AbstractConcurrentDataBrokerTest {
104
105     private static final TopologyId TOPOLOGY_ID = new TopologyId("tunnel-topo");
106     private static final InstanceIdentifier<Topology> TOPO_IID = InstanceIdentifier.builder(NetworkTopology.class)
107             .child(Topology.class, new TopologyKey(TOPOLOGY_ID)).build();
108
109     private static final String NODE1_IPV4 = "127.0.0.1";
110     private static final NodeId NODE1_ID = new NodeId("pcc://" + NODE1_IPV4);
111     private static final TpId TP1_ID = new TpId(NODE1_IPV4);
112
113     private static final String NODE2_IPV4 = "127.0.0.10";
114     private static final NodeId NODE2_ID = new NodeId("pcc://" + NODE2_IPV4);
115     private static final TpId TP2_ID = new TpId(NODE2_IPV4);
116
117     private static final LinkId LINK1_ID = new LinkId("link1");
118
119     private static final String IPV4_PREFIX1 = "195.20.160.40/32";
120     private static final String IPV4_PREFIX2 = "201.20.160.43/32";
121
122     @Mock
123     private InstructionScheduler scheduler;
124     @Mock
125     private ListenableFuture<Instruction> instructionFuture;
126     @Mock
127     private Instruction instruction;
128     @Mock
129     private ClusterSingletonServiceProvider cssp;
130     @Mock
131     private RpcProviderService rpr;
132     @Mock
133     private RpcConsumerRegistry rpcs;
134     @Mock
135     private BundleContext bundleContext;
136
137     private TunnelProgramming tunnelProgramming;
138
139     private AddLspInput addLspInput;
140     private UpdateLspInput updateLspInput;
141     private RemoveLspInput removeLspInput;
142
143     @Mock
144     private ListenableFuture<RpcResult<AddLspOutput>> futureAddLspOutput;
145     @Mock
146     private ListenableFuture<RpcResult<UpdateLspOutput>> futureUpdateLspOutput;
147     @Mock
148     private ListenableFuture<RpcResult<RemoveLspOutput>> futureRemoveLspOutput;
149     @Mock
150     private AddLsp addLsp;
151     @Mock
152     private UpdateLsp updateLsp;
153     @Mock
154     private RemoveLsp removeLsp;
155
156     private static Node createNode(final NodeId nodeId, final TpId tpId, final String ipv4Address) {
157         return new NodeBuilder()
158             .setNodeId(nodeId)
159             .setTerminationPoint(BindingMap.of(new TerminationPointBuilder()
160                 .setTpId(tpId)
161                 .addAugmentation(new TerminationPoint1Builder()
162                     .setIgpTerminationPointAttributes(new IgpTerminationPointAttributesBuilder()
163                         .setTerminationPointType(new IpBuilder()
164                             .setIpAddress(Set.of(new IpAddress(new Ipv4Address(ipv4Address))))
165                             .build())
166                         .build())
167                     .build())
168                 .build()))
169             .setSupportingNode(BindingMap.of(new SupportingNodeBuilder()
170                 .setTopologyRef(new TopologyId("dummy"))
171                 .setNodeRef(nodeId)
172                 .addAugmentation(new SupportingNode1Builder()
173                     .setPathComputationClient(new PathComputationClientBuilder().setControlling(true).build())
174                     .build())
175                 .build()))
176             .build();
177     }
178
179     private static ExplicitHops createExplicitHop(final String ipv4Prefix, final Uint32 order) {
180         return new ExplicitHopsBuilder()
181                 .setOrder(order)
182                 .addAugmentation(new ExplicitHops1Builder()
183                     .setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder()
184                         .setIpPrefix(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
185                     .build())
186                 .build();
187     }
188
189     @Before
190     public void setUp() throws SchedulerException, InterruptedException, ExecutionException {
191         doReturn(true).when(instruction).checkedExecutionStart();
192         doNothing().when(instruction).executionCompleted(InstructionStatus.Failed, null);
193         doAnswer(invocation -> {
194             invocation.getArgument(0, Runnable.class).run();
195             return null;
196         }).when(instructionFuture).addListener(ArgumentMatchers.any(Runnable.class), Mockito.any(Executor.class));
197         doReturn(false).when(futureAddLspOutput).isCancelled();
198         doAnswer(invocation -> {
199             invocation.getArgument(0, Runnable.class).run();
200             return null;
201         }).when(futureAddLspOutput).addListener(any(Runnable.class), any(Executor.class));
202         doReturn(false).when(futureUpdateLspOutput).isCancelled();
203         doAnswer(invocation -> {
204             invocation.getArgument(0, Runnable.class).run();
205             return null;
206         }).when(futureUpdateLspOutput).addListener(any(Runnable.class), any(Executor.class));
207         doReturn(false).when(futureRemoveLspOutput).isCancelled();
208         doAnswer(invocation -> {
209             invocation.getArgument(0, Runnable.class).run();
210             return null;
211         }).when(futureRemoveLspOutput).addListener(any(Runnable.class), any(Executor.class));
212         doAnswer(invocation -> {
213             addLspInput = invocation.getArgument(0);
214             return futureAddLspOutput;
215         }).when(addLsp).invoke(any(AddLspInput.class));
216         doAnswer(invocation -> {
217             updateLspInput = invocation.getArgument(0);
218             return futureUpdateLspOutput;
219         }).when(updateLsp).invoke(any(UpdateLspInput.class));
220         doAnswer(invocation -> {
221             removeLspInput = invocation.getArgument(0);
222             return futureRemoveLspOutput;
223         }).when(removeLsp).invoke(any(RemoveLspInput.class));
224         doReturn(instruction).when(instructionFuture).get();
225         doReturn(true).when(instructionFuture).isDone();
226         doReturn(instructionFuture).when(scheduler)
227                 .scheduleInstruction(any(SubmitInstructionInput.class));
228
229         doReturn(addLsp).when(rpcs).getRpc(AddLsp.class);
230         doReturn(updateLsp).when(rpcs).getRpc(UpdateLsp.class);
231         doReturn(removeLsp).when(rpcs).getRpc(RemoveLsp.class);
232
233         createInitialTopology();
234         tunnelProgramming = new TunnelProgramming(scheduler,
235             new TunnelProviderDependencies(getDataBroker(), cssp, rpr, rpcs, bundleContext));
236     }
237
238     @Test
239     public void testTunnelProgramming() throws InterruptedException, ExecutionException {
240         final Bandwidth bwd = new Bandwidth(new byte[] { 0x00, 0x00, 0x00, (byte) 0xff });
241         final ClassType classType = new ClassType(Uint8.ONE);
242         final String tunnelName = "create-tunnel";
243         final NetworkTopologyRef topologyRef = new NetworkTopologyRef(TOPO_IID);
244         // create tunnel
245         tunnelProgramming.pcepCreateP2pTunnel(new PcepCreateP2pTunnelInputBuilder()
246             .setDestination(new DestinationBuilder().setNode(NODE2_ID).setTp(TP2_ID).build())
247             .setSource(new SourceBuilder().setNode(NODE1_ID).setTp(TP1_ID).build())
248             .setNetworkTopologyRef(topologyRef)
249             .setBandwidth(bwd)
250             .setClassType(classType)
251             .setSymbolicPathName(tunnelName)
252             .addAugmentation(new PcepCreateP2pTunnelInput1Builder()
253                 .setAdministrativeStatus(AdministrativeStatus.Active)
254                 .build())
255             .build());
256         //check add-lsp input
257         assertNotNull(addLspInput);
258         assertEquals(tunnelName, addLspInput.getName());
259         final Arguments agrs = addLspInput.getArguments();
260         assertNotNull(agrs);
261         assertEquals(bwd, agrs.getBandwidth().getBandwidth());
262         assertEquals(classType, agrs.getClassType().getClassType());
263         final Ipv4 ipv4Endpoints = ((Ipv4Case) agrs.getEndpointsObj().getAddressFamily()).getIpv4();
264         assertEquals(NODE1_IPV4, ipv4Endpoints.getSourceIpv4Address().getValue());
265         assertEquals(NODE2_IPV4, ipv4Endpoints.getDestinationIpv4Address().getValue());
266         assertEquals(NODE1_ID.getValue(), addLspInput.getNode().getValue());
267         createLink();
268
269         // update tunnel
270         tunnelProgramming.pcepUpdateTunnel(new PcepUpdateTunnelInputBuilder()
271             .setNetworkTopologyRef(topologyRef)
272             .setBandwidth(bwd)
273             .setClassType(classType)
274             // We assert on explicit order
275             .setExplicitHops(BindingMap.ordered(
276                 createExplicitHop(IPV4_PREFIX1, Uint32.ONE),
277                 createExplicitHop(IPV4_PREFIX2, Uint32.TWO)))
278             .setLinkId(LINK1_ID)
279             .addAugmentation(new PcepUpdateTunnelInput1Builder()
280                 .setAdministrativeStatus(AdministrativeStatus.Active)
281                 .build())
282             .build());
283         //check update-lsp input
284         assertNotNull(updateLspInput);
285         assertEquals(LINK1_ID.getValue(), updateLspInput.getName());
286         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev220730.update.lsp
287                 .args.Arguments updArgs = updateLspInput.getArguments();
288         assertEquals(2, updArgs.getEro().nonnullSubobject().size());
289         final List<Subobject> subObjects = updArgs.getEro().nonnullSubobject();
290         final IpPrefixCase prefix1 = (IpPrefixCase) subObjects.get(0).getSubobjectType();
291         final IpPrefixCase prefix2 = (IpPrefixCase) subObjects.get(1).getSubobjectType();
292         assertEquals(IPV4_PREFIX1, prefix1.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue());
293         assertEquals(IPV4_PREFIX2, prefix2.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue());
294
295         // delete tunnel
296         final PcepDestroyTunnelInputBuilder destroyInputBuilder = new PcepDestroyTunnelInputBuilder();
297         destroyInputBuilder.setLinkId(LINK1_ID);
298         destroyInputBuilder.setNetworkTopologyRef(topologyRef);
299         tunnelProgramming.pcepDestroyTunnel(destroyInputBuilder.build());
300         assertNotNull(removeLspInput);
301         assertEquals(LINK1_ID.getValue(), removeLspInput.getName());
302         assertEquals(NODE1_ID, removeLspInput.getNode());
303     }
304
305     private void createInitialTopology() throws InterruptedException, ExecutionException {
306         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
307         wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, TOPO_IID, new TopologyBuilder()
308             .setTopologyId(TOPOLOGY_ID)
309             .setServerProvided(true)
310             .setTopologyId(TOPOLOGY_ID)
311             .setNode(BindingMap.of(createNode(NODE1_ID, TP1_ID, NODE1_IPV4), createNode(NODE2_ID, TP2_ID, NODE2_IPV4)))
312             .build());
313         wTx.commit().get();
314     }
315
316     private void createLink() throws InterruptedException, ExecutionException {
317         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
318         wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL,
319             TOPO_IID.child(Link.class, new LinkKey(LINK1_ID)),
320             new LinkBuilder()
321                 .setSource(new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
322                     .link.attributes.SourceBuilder().setSourceNode(NODE1_ID).setSourceTp(TP1_ID).build())
323                 .setDestination(new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
324                     .link.attributes.DestinationBuilder().setDestNode(NODE2_ID).setDestTp(TP2_ID).build())
325                 .setLinkId(LINK1_ID)
326                 .addAugmentation(new Link1Builder().setSymbolicPathName(LINK1_ID.getValue()).build())
327                 .build());
328         wTx.commit().get();
329     }
330 }