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.pcep.tunnel.provider;
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;
17 import com.google.common.util.concurrent.ListenableFuture;
18 import java.util.Collections;
19 import java.util.List;
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.rev200120.AddLspInput;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.AddLspOutput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.NetworkTopologyPcepService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspInput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.RemoveLspOutput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspInput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.UpdateLspOutput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.add.lsp.args.Arguments;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.p2p.rev130819.tunnel.p2p.path.cfg.attributes.ExplicitHops;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.p2p.rev130819.tunnel.p2p.path.cfg.attributes.ExplicitHopsBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.PcepCreateP2pTunnelInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.PcepDestroyTunnelInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.programming.rev181109.PcepUpdateTunnelInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.ExplicitHops1Builder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.Link1Builder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.SupportingNode1Builder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev181109.tunnel.pcep.supporting.node.attributes.PathComputationClientBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.create.p2p.tunnel.input.DestinationBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.programming.rev130930.create.p2p.tunnel.input.SourceBuilder;
75 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
76 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
77 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
78 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
80 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
82 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
83 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
87 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
88 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1Builder;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.IgpTerminationPointAttributesBuilder;
92 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;
93 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
94 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
95 import org.opendaylight.yangtools.yang.common.RpcResult;
96 import org.opendaylight.yangtools.yang.common.Uint32;
97 import org.opendaylight.yangtools.yang.common.Uint8;
98 import org.osgi.framework.BundleContext;
100 @RunWith(MockitoJUnitRunner.StrictStubs.class)
101 public class TunnelProgrammingTest extends AbstractConcurrentDataBrokerTest {
103 private static final TopologyId TOPOLOGY_ID = new TopologyId("tunnel-topo");
104 private static final InstanceIdentifier<Topology> TOPO_IID = InstanceIdentifier.builder(NetworkTopology.class)
105 .child(Topology.class, new TopologyKey(TOPOLOGY_ID)).build();
107 private static final String NODE1_IPV4 = "127.0.0.1";
108 private static final NodeId NODE1_ID = new NodeId("pcc://" + NODE1_IPV4);
109 private static final TpId TP1_ID = new TpId(NODE1_IPV4);
111 private static final String NODE2_IPV4 = "127.0.0.10";
112 private static final NodeId NODE2_ID = new NodeId("pcc://" + NODE2_IPV4);
113 private static final TpId TP2_ID = new TpId(NODE2_IPV4);
115 private static final LinkId LINK1_ID = new LinkId("link1");
117 private static final String IPV4_PREFIX1 = "195.20.160.40/32";
118 private static final String IPV4_PREFIX2 = "201.20.160.43/32";
121 private NetworkTopologyPcepService topologyService;
123 private InstructionScheduler scheduler;
125 private ListenableFuture<Instruction> instructionFuture;
127 private Instruction instruction;
129 private ClusterSingletonServiceProvider cssp;
131 private RpcProviderService rpr;
133 private RpcConsumerRegistry rpcs;
135 private BundleContext bundleContext;
137 private TunnelProgramming tunnelProgramming;
139 private AddLspInput addLspInput;
140 private UpdateLspInput updateLspInput;
141 private RemoveLspInput removeLspInput;
144 private ListenableFuture<RpcResult<AddLspOutput>> futureAddLspOutput;
146 private ListenableFuture<RpcResult<UpdateLspOutput>> futureUpdateLspOutput;
148 private ListenableFuture<RpcResult<RemoveLspOutput>> futureRemoveLspOutput;
150 private static Node createNode(final NodeId nodeId, final TpId tpId, final String ipv4Address) {
151 return new NodeBuilder()
153 .setTerminationPoint(BindingMap.of(new TerminationPointBuilder()
155 .addAugmentation(new TerminationPoint1Builder()
156 .setIgpTerminationPointAttributes(new IgpTerminationPointAttributesBuilder()
157 .setTerminationPointType(new IpBuilder()
158 .setIpAddress(Collections.singletonList(new IpAddress(new Ipv4Address(ipv4Address))))
163 .setSupportingNode(BindingMap.of(new SupportingNodeBuilder()
164 .setTopologyRef(new TopologyId("dummy"))
166 .addAugmentation(new SupportingNode1Builder()
167 .setPathComputationClient(new PathComputationClientBuilder().setControlling(true).build())
173 private static ExplicitHops createExplicitHop(final String ipv4Prefix, final Uint32 order) {
174 return new ExplicitHopsBuilder()
176 .addAugmentation(new ExplicitHops1Builder()
177 .setSubobjectType(new IpPrefixCaseBuilder().setIpPrefix(new IpPrefixBuilder()
178 .setIpPrefix(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
184 public void setUp() throws SchedulerException, InterruptedException, ExecutionException {
185 doReturn(true).when(instruction).checkedExecutionStart();
186 doNothing().when(instruction).executionCompleted(InstructionStatus.Failed, null);
187 doAnswer(invocation -> {
188 invocation.getArgument(0, Runnable.class).run();
190 }).when(instructionFuture).addListener(ArgumentMatchers.any(Runnable.class), Mockito.any(Executor.class));
191 doReturn(false).when(futureAddLspOutput).isCancelled();
192 doAnswer(invocation -> {
193 invocation.getArgument(0, Runnable.class).run();
195 }).when(futureAddLspOutput).addListener(any(Runnable.class), any(Executor.class));
196 doReturn(false).when(futureUpdateLspOutput).isCancelled();
197 doAnswer(invocation -> {
198 invocation.getArgument(0, Runnable.class).run();
200 }).when(futureUpdateLspOutput).addListener(any(Runnable.class), any(Executor.class));
201 doReturn(false).when(futureRemoveLspOutput).isCancelled();
202 doAnswer(invocation -> {
203 invocation.getArgument(0, Runnable.class).run();
205 }).when(futureRemoveLspOutput).addListener(any(Runnable.class), any(Executor.class));
206 doAnswer(invocation -> {
207 addLspInput = invocation.getArgument(0);
208 return futureAddLspOutput;
209 }).when(topologyService).addLsp(any(AddLspInput.class));
210 doAnswer(invocation -> {
211 updateLspInput = invocation.getArgument(0);
212 return futureUpdateLspOutput;
213 }).when(topologyService).updateLsp(any(UpdateLspInput.class));
214 doAnswer(invocation -> {
215 removeLspInput = invocation.getArgument(0);
216 return futureRemoveLspOutput;
217 }).when(topologyService).removeLsp(any(RemoveLspInput.class));
218 doReturn(instruction).when(instructionFuture).get();
219 doReturn(true).when(instructionFuture).isDone();
220 doReturn(instructionFuture).when(scheduler)
221 .scheduleInstruction(any(SubmitInstructionInput.class));
223 doReturn(topologyService).when(rpcs)
224 .getRpcService(NetworkTopologyPcepService.class);
226 createInitialTopology();
227 tunnelProgramming = new TunnelProgramming(scheduler,
228 new TunnelProviderDependencies(getDataBroker(), cssp, rpr, rpcs, bundleContext));
232 public void testTunnelProgramming() throws InterruptedException, ExecutionException {
233 final Bandwidth bwd = new Bandwidth(new byte[] { 0x00, 0x00, 0x00, (byte) 0xff });
234 final ClassType classType = new ClassType(Uint8.ONE);
235 final String tunnelName = "create-tunnel";
236 final NetworkTopologyRef topologyRef = new NetworkTopologyRef(TOPO_IID);
238 tunnelProgramming.pcepCreateP2pTunnel(new PcepCreateP2pTunnelInputBuilder()
239 .setDestination(new DestinationBuilder().setNode(NODE2_ID).setTp(TP2_ID).build())
240 .setSource(new SourceBuilder().setNode(NODE1_ID).setTp(TP1_ID).build())
241 .setNetworkTopologyRef(topologyRef)
243 .setClassType(classType)
244 .setSymbolicPathName(tunnelName)
245 .addAugmentation(new PcepCreateP2pTunnelInput1Builder()
246 .setAdministrativeStatus(AdministrativeStatus.Active)
249 //check add-lsp input
250 assertNotNull(addLspInput);
251 assertEquals(tunnelName, addLspInput.getName());
252 final Arguments agrs = addLspInput.getArguments();
254 assertEquals(bwd, agrs.getBandwidth().getBandwidth());
255 assertEquals(classType, agrs.getClassType().getClassType());
256 final Ipv4 ipv4Endpoints = ((Ipv4Case) agrs.getEndpointsObj().getAddressFamily()).getIpv4();
257 assertEquals(NODE1_IPV4, ipv4Endpoints.getSourceIpv4Address().getValue());
258 assertEquals(NODE2_IPV4, ipv4Endpoints.getDestinationIpv4Address().getValue());
259 assertEquals(NODE1_ID.getValue(), addLspInput.getNode().getValue());
263 tunnelProgramming.pcepUpdateTunnel(new PcepUpdateTunnelInputBuilder()
264 .setNetworkTopologyRef(topologyRef)
266 .setClassType(classType)
267 // We assert on explicit order
268 .setExplicitHops(BindingMap.ordered(
269 createExplicitHop(IPV4_PREFIX1, Uint32.ONE),
270 createExplicitHop(IPV4_PREFIX2, Uint32.TWO)))
272 .addAugmentation(new PcepUpdateTunnelInput1Builder()
273 .setAdministrativeStatus(AdministrativeStatus.Active)
276 //check update-lsp input
277 assertNotNull(updateLspInput);
278 assertEquals(LINK1_ID.getValue(), updateLspInput.getName());
279 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev200120.update.lsp
280 .args.Arguments updArgs = updateLspInput.getArguments();
281 assertEquals(2, updArgs.getEro().nonnullSubobject().size());
282 final List<Subobject> subObjects = updArgs.getEro().nonnullSubobject();
283 final IpPrefixCase prefix1 = (IpPrefixCase) subObjects.get(0).getSubobjectType();
284 final IpPrefixCase prefix2 = (IpPrefixCase) subObjects.get(1).getSubobjectType();
285 assertEquals(IPV4_PREFIX1, prefix1.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue());
286 assertEquals(IPV4_PREFIX2, prefix2.getIpPrefix().getIpPrefix().getIpv4Prefix().getValue());
289 final PcepDestroyTunnelInputBuilder destroyInputBuilder = new PcepDestroyTunnelInputBuilder();
290 destroyInputBuilder.setLinkId(LINK1_ID);
291 destroyInputBuilder.setNetworkTopologyRef(topologyRef);
292 tunnelProgramming.pcepDestroyTunnel(destroyInputBuilder.build());
293 assertNotNull(removeLspInput);
294 assertEquals(LINK1_ID.getValue(), removeLspInput.getName());
295 assertEquals(NODE1_ID, removeLspInput.getNode());
298 private void createInitialTopology() throws InterruptedException, ExecutionException {
299 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
300 wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, TOPO_IID, new TopologyBuilder()
301 .setTopologyId(TOPOLOGY_ID)
302 .setServerProvided(true)
303 .setTopologyId(TOPOLOGY_ID)
304 .setNode(BindingMap.of(createNode(NODE1_ID, TP1_ID, NODE1_IPV4), createNode(NODE2_ID, TP2_ID, NODE2_IPV4)))
309 private void createLink() throws InterruptedException, ExecutionException {
310 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
311 wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL,
312 TOPO_IID.child(Link.class, new LinkKey(LINK1_ID)),
314 .setSource(new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
315 .link.attributes.SourceBuilder().setSourceNode(NODE1_ID).setSourceTp(TP1_ID).build())
316 .setDestination(new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021
317 .link.attributes.DestinationBuilder().setDestNode(NODE2_ID).setDestTp(TP2_ID).build())
319 .addAugmentation(new Link1Builder().setSymbolicPathName(LINK1_ID.getValue()).build())