2 * Copyright (c) 2016 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
9 package org.opendaylight.protocol.bgp.benchmark.app;
11 import com.google.common.base.Stopwatch;
12 import com.google.common.net.InetAddresses;
13 import java.util.Collections;
14 import java.util.concurrent.Future;
15 import java.util.concurrent.TimeUnit;
16 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
22 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
25 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.application.rib.tables.routes.Ipv4RoutesCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.Ipv4Routes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.Ipv4RoutesBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4Route;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4RouteBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4RouteKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.PathId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPathBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.LocalPref;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.LocalPrefBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDisc;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.MultiExitDiscBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.OriginBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRib;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.ipv4.next.hop._case.Ipv4NextHopBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.AddPrefixInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.AddPrefixOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.AddPrefixOutputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.DeletePrefixInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.DeletePrefixOutput;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.DeletePrefixOutputBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.OdlBgpAppPeerBenchmarkService;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.output.Result;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.app.peer.benchmark.rev160309.output.ResultBuilder;
66 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
68 import org.opendaylight.yangtools.yang.common.RpcResult;
69 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
73 public class AppPeerBenchmark implements OdlBgpAppPeerBenchmarkService, TransactionChainListener, AutoCloseable {
75 private static final Logger LOG = LoggerFactory.getLogger(AppPeerBenchmark.class);
77 private static final AsPath AS_PATH = new AsPathBuilder().build();
78 private static final Origin ORIGIN = new OriginBuilder().setValue(BgpOrigin.Igp).build();
79 private static final MultiExitDisc MED = new MultiExitDiscBuilder().setMed(0L).build();
80 private static final LocalPref LOC_PREF = new LocalPrefBuilder().setPref(100L).build();
82 private static final String SLASH = "/";
83 private static final String PREFIX = SLASH + "32";
85 private static final PathId PATH_ID = new PathId(0L);
87 private final BindingTransactionChain txChain;
88 private final RpcRegistration<OdlBgpAppPeerBenchmarkService> rpcRegistration;
89 private final InstanceIdentifier<ApplicationRib> iid;
90 private final InstanceIdentifier<Ipv4Routes> routesIId;
92 public AppPeerBenchmark(final DataBroker bindingDataBroker, final RpcProviderRegistry rpcProviderRegistry,
93 final String appRibId) {
94 this.txChain = bindingDataBroker.createTransactionChain(this);
95 this.iid = initTable(appRibId);
96 final InstanceIdentifier tablesIId = this.iid
97 .child(Tables.class, new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class));
98 this.routesIId = tablesIId.child(Ipv4Routes.class);
99 this.rpcRegistration = rpcProviderRegistry.addRpcImplementation(OdlBgpAppPeerBenchmarkService.class, this);
100 LOG.info("BGP Application Peer Benchmark Application started.");
104 public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction,
105 final Throwable cause) {
106 LOG.error("Broken chain {} in DatastoreBaAbstractWrite, transaction {}, cause {}", chain,
107 transaction.getIdentifier(), cause);
112 public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
113 LOG.debug("DatastoreBaAbstractWrite closed successfully, chain {}", chain);
116 private InstanceIdentifier<ApplicationRib> initTable(final String appRibId) {
117 final Tables tables = new TablesBuilder()
118 .setAfi(Ipv4AddressFamily.class)
119 .setSafi(UnicastSubsequentAddressFamily.class)
121 new Ipv4RoutesCaseBuilder().setIpv4Routes(
122 new Ipv4RoutesBuilder().setIpv4Route(Collections.emptyList()).build())
125 final ApplicationRib appRib = new ApplicationRibBuilder()
126 .setId(new ApplicationRibId(new ApplicationRibId(appRibId)))
127 .setTables(Collections.singletonList(tables)).build();
129 final InstanceIdentifier<ApplicationRib> ribIID = KeyedInstanceIdentifier.builder(ApplicationRib.class,
130 new ApplicationRibKey(new ApplicationRibId(appRibId))).build();
131 final WriteTransaction wTx = this.txChain.newWriteOnlyTransaction();
132 wTx.put(LogicalDatastoreType.CONFIGURATION, ribIID, appRib);
138 public Future<RpcResult<AddPrefixOutput>> addPrefix(final AddPrefixInput input) {
139 final long duration = addRoute(input.getPrefix(), input.getNexthop(), input.getCount(), input.getBatchsize());
140 final long rate = countRate(duration, input.getCount());
142 final AddPrefixOutputBuilder outputbuilder = new AddPrefixOutputBuilder();
143 outputbuilder.setResult(createResult(input.getCount(), duration, rate));
144 final AddPrefixOutput output = outputbuilder.build();
145 return RpcResultBuilder.success(output).buildFuture();
149 public Future<RpcResult<DeletePrefixOutput>> deletePrefix(final DeletePrefixInput input) {
150 final long duration = deleteRoute(input.getPrefix(), input.getCount(), input.getBatchsize());
151 final long rate = countRate(duration, input.getCount());
153 final DeletePrefixOutputBuilder outputbuilder = new DeletePrefixOutputBuilder();
154 outputbuilder.setResult(createResult(input.getCount(), duration, rate));
155 final DeletePrefixOutput output = outputbuilder.build();
156 return RpcResultBuilder.success(output).buildFuture();
160 public void close() {
161 this.rpcRegistration.close();
162 final WriteTransaction dTx = this.txChain.newWriteOnlyTransaction();
163 dTx.delete(LogicalDatastoreType.CONFIGURATION, this.iid);
165 dTx.submit().checkedGet();
166 } catch (final TransactionCommitFailedException e) {
167 LOG.warn("Failed to clean-up BGP Application RIB.", e);
169 this.txChain.close();
170 LOG.info("BGP Application Peer Benchmark Application closed.");
173 private long addRoute(final Ipv4Prefix ipv4Prefix, final Ipv4Address nextHop, final long count, final long batch) {
174 final AttributesBuilder attributesBuilder = new AttributesBuilder();
175 attributesBuilder.setCNextHop(new Ipv4NextHopCaseBuilder().setIpv4NextHop(
176 new Ipv4NextHopBuilder().setGlobal(new Ipv4Address(nextHop)).build()).build());
177 attributesBuilder.setMultiExitDisc(MED);
178 attributesBuilder.setLocalPref(LOC_PREF);
179 attributesBuilder.setOrigin(ORIGIN);
180 attributesBuilder.setAsPath(AS_PATH);
181 final Attributes attributes = attributesBuilder.build();
182 return processRoutes(ipv4Prefix, count, batch, attributes);
185 private long deleteRoute(final Ipv4Prefix ipv4Prefix, final long count, final long batch) {
186 return processRoutes(ipv4Prefix, count, batch, null);
189 private long processRoutes(final Ipv4Prefix ipv4Prefix, final long count, final long batch, final Attributes attributes) {
190 WriteTransaction wTx = this.txChain.newWriteOnlyTransaction();
191 String address = getAdddressFromPrefix(ipv4Prefix);
192 final Stopwatch stopwatch = Stopwatch.createStarted();
193 for (int i = 1; i <= count; i++) {
194 final Ipv4RouteKey routeKey = new Ipv4RouteKey(PATH_ID, createPrefix(address));
195 final KeyedInstanceIdentifier<Ipv4Route, Ipv4RouteKey> routeIId = this.routesIId.child(Ipv4Route.class, routeKey);
196 if (attributes != null) {
197 final Ipv4RouteBuilder ipv4RouteBuilder = new Ipv4RouteBuilder();
198 ipv4RouteBuilder.setPrefix(routeKey.getPrefix());
199 ipv4RouteBuilder.setKey(routeKey);
200 ipv4RouteBuilder.setAttributes(attributes);
201 final Ipv4Route ipv4Route = ipv4RouteBuilder.build();
202 wTx.put(LogicalDatastoreType.CONFIGURATION, routeIId,
205 wTx.delete(LogicalDatastoreType.CONFIGURATION, routeIId);
207 if (i % batch == 0) {
209 wTx = this.txChain.newWriteOnlyTransaction();
211 address = increasePrefix(address);
214 return stopwatch.stop().elapsed(TimeUnit.MILLISECONDS);
217 private static long countRate(final long durationMillis, final long count) {
218 final long durationSec = TimeUnit.MILLISECONDS.toSeconds(durationMillis);
219 if (durationSec != 0) {
220 return count / durationSec;
225 private static String increasePrefix(final String prefix) {
226 return InetAddresses.increment(InetAddresses.forString(prefix)).getHostAddress();
229 private static Result createResult(final long count, final long duration, final long rate) {
230 return new ResultBuilder().setCount(count).setDuration(duration).setRate(rate).build();
233 private static String getAdddressFromPrefix(final Ipv4Prefix prefix) {
234 return prefix.getValue().split(SLASH)[0];
237 private static Ipv4Prefix createPrefix(final String address) {
238 return new Ipv4Prefix(address + PREFIX);