Code clean up
[bgpcep.git] / bgp / benchmark-app / src / main / java / org / opendaylight / protocol / bgp / benchmark / app / AppPeerBenchmark.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.protocol.bgp.benchmark.app;
10
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;
72
73 public class AppPeerBenchmark implements OdlBgpAppPeerBenchmarkService, TransactionChainListener, AutoCloseable {
74
75     private static final Logger LOG = LoggerFactory.getLogger(AppPeerBenchmark.class);
76
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();
81
82     private static final String SLASH = "/";
83     private static final String PREFIX = SLASH + "32";
84
85     private static final PathId PATH_ID = new PathId(0L);
86
87     private final BindingTransactionChain txChain;
88     private final RpcRegistration<OdlBgpAppPeerBenchmarkService> rpcRegistration;
89     private final InstanceIdentifier<ApplicationRib> iid;
90     private final InstanceIdentifier<Ipv4Routes> routesIId;
91
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.");
101     }
102
103     @Override
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);
108         close();
109     }
110
111     @Override
112     public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
113         LOG.debug("DatastoreBaAbstractWrite closed successfully, chain {}", chain);
114     }
115
116     private InstanceIdentifier<ApplicationRib> initTable(final String appRibId) {
117         final Tables tables = new TablesBuilder()
118                 .setAfi(Ipv4AddressFamily.class)
119                 .setSafi(UnicastSubsequentAddressFamily.class)
120                 .setRoutes(
121                         new Ipv4RoutesCaseBuilder().setIpv4Routes(
122                                 new Ipv4RoutesBuilder().setIpv4Route(Collections.emptyList()).build())
123                                 .build()).build();
124
125         final ApplicationRib appRib = new ApplicationRibBuilder()
126                 .setId(new ApplicationRibId(new ApplicationRibId(appRibId)))
127                 .setTables(Collections.singletonList(tables)).build();
128
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);
133         wTx.submit();
134         return ribIID;
135     }
136
137     @Override
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());
141
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();
146     }
147
148     @Override
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());
152
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();
157     }
158
159     @Override
160     public void close() {
161         this.rpcRegistration.close();
162         final WriteTransaction dTx = this.txChain.newWriteOnlyTransaction();
163         dTx.delete(LogicalDatastoreType.CONFIGURATION, this.iid);
164         try {
165             dTx.submit().checkedGet();
166         } catch (final TransactionCommitFailedException e) {
167             LOG.warn("Failed to clean-up BGP Application RIB.", e);
168         }
169         this.txChain.close();
170         LOG.info("BGP Application Peer Benchmark Application closed.");
171     }
172
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);
183     }
184
185     private long deleteRoute(final Ipv4Prefix ipv4Prefix, final long count, final long batch) {
186         return processRoutes(ipv4Prefix, count, batch, null);
187     }
188
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,
203                         ipv4Route);
204             } else {
205                 wTx.delete(LogicalDatastoreType.CONFIGURATION, routeIId);
206             }
207             if (i % batch == 0) {
208                 wTx.submit();
209                 wTx = this.txChain.newWriteOnlyTransaction();
210             }
211             address = increasePrefix(address);
212         }
213         wTx.submit();
214         return stopwatch.stop().elapsed(TimeUnit.MILLISECONDS);
215     }
216
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;
221         }
222         return count;
223     }
224
225     private static String increasePrefix(final String prefix) {
226         return InetAddresses.increment(InetAddresses.forString(prefix)).getHostAddress();
227     }
228
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();
231     }
232
233     private static String getAdddressFromPrefix(final Ipv4Prefix prefix) {
234         return prefix.getValue().split(SLASH)[0];
235     }
236
237     private static Ipv4Prefix createPrefix(final String address) {
238         return new Ipv4Prefix(address + PREFIX);
239     }
240 }