Merge "fix callback handling"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / statistics / services / OpendaylightFlowStatisticsServiceImpl.java
1 /**
2  * Copyright (c) 2015 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.openflowplugin.impl.statistics.services;
9
10 import com.google.common.base.Function;
11 import com.google.common.base.MoreObjects;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.concurrent.Future;
17 import javax.annotation.Nullable;
18 import org.opendaylight.openflowplugin.api.OFConstants;
19 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
21 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
22 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
23 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
24 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
25 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
26 import org.opendaylight.openflowplugin.impl.services.CommonService;
27 import org.opendaylight.openflowplugin.impl.services.RequestInputUtils;
28 import org.opendaylight.openflowplugin.impl.util.StatisticsServiceUtil;
29 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.MatchReactor;
30 import org.opendaylight.openflowplugin.openflow.md.util.FlowCreatorUtil;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowStatisticsFromFlowTableOutput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetAllFlowsStatisticsFromAllFlowTablesOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.GetFlowStatisticsFromFlowTableOutput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.OpendaylightFlowStatisticsService;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.get.aggregate.flow.statistics.from.flow.table._for.given.match.output.AggregatedFlowStatistics;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestAggregateCaseBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlowCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.aggregate._case.MultipartRequestAggregateBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.flow._case.MultipartRequestFlowBuilder;
52 import org.opendaylight.yangtools.yang.common.RpcResult;
53 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 /**
58  * @author joe
59  */
60 public class OpendaylightFlowStatisticsServiceImpl extends CommonService implements OpendaylightFlowStatisticsService {
61
62     private static final Logger LOG = LoggerFactory.getLogger(OpendaylightFlowStatisticsServiceImpl.class);
63
64     public OpendaylightFlowStatisticsServiceImpl(final RequestContextStack requestContextStack, DeviceContext deviceContext) {
65         super(requestContextStack, deviceContext);
66     }
67
68     @Override
69     public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> getAggregateFlowStatisticsFromFlowTableForAllFlows(
70             final GetAggregateFlowStatisticsFromFlowTableForAllFlowsInput input) {
71
72
73         return this.<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput, Void>handleServiceCall(
74                 new Function<RequestContext<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>, ListenableFuture<RpcResult<Void>>>() {
75
76                     @Override
77                     public ListenableFuture<RpcResult<Void>> apply(final RequestContext<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput> requestContext) {
78
79                         // Create multipart request body for fetch all the group stats
80                         final MultipartRequestAggregateCaseBuilder multipartRequestAggregateCaseBuilder = new MultipartRequestAggregateCaseBuilder();
81                         final MultipartRequestAggregateBuilder mprAggregateRequestBuilder = new MultipartRequestAggregateBuilder();
82                         mprAggregateRequestBuilder.setTableId(input.getTableId().getValue());
83                         mprAggregateRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
84                         mprAggregateRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
85                         mprAggregateRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
86                         mprAggregateRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
87                         final short version = getVersion();
88                         FlowCreatorUtil.setWildcardedFlowMatch(version, mprAggregateRequestBuilder);
89
90                         // Set request body to main multipart request
91                         multipartRequestAggregateCaseBuilder.setMultipartRequestAggregate(mprAggregateRequestBuilder
92                                 .build());
93                         final Xid xid = requestContext.getXid();
94                         final MultipartRequestInputBuilder mprInput = RequestInputUtils.createMultipartHeader(
95                                 MultipartType.OFPMPAGGREGATE, xid.getValue(), version);
96
97                         mprInput.setMultipartRequestBody(multipartRequestAggregateCaseBuilder.build());
98
99                         return StatisticsServiceUtil.getRpcResultListenableFuture(xid, mprInput.build(), getDeviceContext());
100                     }
101                 });
102
103     }
104
105     @Override
106     public Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>> getAggregateFlowStatisticsFromFlowTableForGivenMatch(
107             final GetAggregateFlowStatisticsFromFlowTableForGivenMatchInput input) {
108
109
110         ListenableFuture<RpcResult<List<MultipartReply>>> rpcResultListenableFuture = handleServiceCall(
111                 new Function<RequestContext<List<MultipartReply>>, ListenableFuture<RpcResult<Void>>>() {
112
113                     @Override
114                     public ListenableFuture<RpcResult<Void>> apply(final RequestContext<List<MultipartReply>> requestContext) {
115                         final Xid xid = requestContext.getXid();
116                         final DeviceContext deviceContext = getDeviceContext();
117                         deviceContext.getMultiMsgCollector().registerMultipartXid(xid.getValue());
118                         final MultipartRequestAggregateCaseBuilder multipartRequestAggregateCaseBuilder = new MultipartRequestAggregateCaseBuilder();
119                         final MultipartRequestAggregateBuilder mprAggregateRequestBuilder = new MultipartRequestAggregateBuilder();
120                         final short tableId = MoreObjects.firstNonNull(input.getTableId(), OFConstants.OFPTT_ALL).shortValue();
121                         mprAggregateRequestBuilder.setTableId(tableId);
122                         long outputPortValue = MoreObjects.firstNonNull(input.getOutPort(), OFConstants.OFPP_ANY).longValue();
123                         mprAggregateRequestBuilder.setOutPort(outputPortValue);
124                         // TODO: repeating code
125
126                         final short version = getVersion();
127                         if (version == OFConstants.OFP_VERSION_1_3) {
128
129                             if (input.getCookie() == null) {
130                                 mprAggregateRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
131                             } else {
132                                 mprAggregateRequestBuilder.setCookie(MoreObjects.firstNonNull(input.getCookie().getValue(), OFConstants.DEFAULT_COOKIE));
133                             }
134
135                             if (input.getCookieMask() == null) {
136                                 mprAggregateRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
137                             } else {
138                                 mprAggregateRequestBuilder.setCookieMask(MoreObjects.firstNonNull(input.getCookieMask().getValue(), OFConstants.DEFAULT_COOKIE_MASK));
139                             }
140                             long outGroup = MoreObjects.firstNonNull(input.getOutGroup(), OFConstants.OFPG_ANY).longValue();
141                             mprAggregateRequestBuilder.setOutGroup(outGroup);
142                         } else {
143                             mprAggregateRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
144                             mprAggregateRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
145                             mprAggregateRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
146                         }
147
148                         MatchReactor.getInstance().convert(input.getMatch(), version, mprAggregateRequestBuilder,
149                                 deviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId());
150
151                         FlowCreatorUtil.setWildcardedFlowMatch(version, mprAggregateRequestBuilder);
152
153                         // Set request body to main multipart request
154                         multipartRequestAggregateCaseBuilder.setMultipartRequestAggregate(mprAggregateRequestBuilder
155                                 .build());
156
157                         final MultipartRequestInputBuilder mprInput = RequestInputUtils.createMultipartHeader(
158                                 MultipartType.OFPMPAGGREGATE, xid.getValue(), version);
159
160                         mprInput.setMultipartRequestBody(multipartRequestAggregateCaseBuilder.build());
161                         return StatisticsServiceUtil.getRpcResultListenableFuture(xid, mprInput.build(), getDeviceContext());
162                     }
163                 });
164
165         return Futures.transform(rpcResultListenableFuture, new Function<RpcResult<List<MultipartReply>>, RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>>() {
166             @Nullable
167             @Override
168             public RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput> apply(RpcResult<List<MultipartReply>> input) {
169                 final DeviceContext deviceContext = getDeviceContext();
170                 TranslatorLibrary translatorLibrary = deviceContext.oook();
171                 RpcResult<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput> rpcResult;
172                 if (input.isSuccessful()) {
173                     MultipartReply reply = input.getResult().get(0);
174                     final TranslatorKey translatorKey = new TranslatorKey(reply.getVersion(), MultipartReplyAggregateCase.class.getName());
175                     final MessageTranslator<MultipartReply, AggregatedFlowStatistics> messageTranslator = translatorLibrary.lookupTranslator(translatorKey);
176                     List<AggregatedFlowStatistics> aggregStats = new ArrayList<AggregatedFlowStatistics>();
177
178                     for (MultipartReply multipartReply : input.getResult()) {
179                         aggregStats.add(messageTranslator.translate(multipartReply, deviceContext, null));
180                     }
181
182                     GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder =
183                             new GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder();
184                     getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder.setAggregatedFlowStatistics(aggregStats);
185
186                     rpcResult = RpcResultBuilder
187                             .<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>success()
188                             .withResult(getAggregateFlowStatisticsFromFlowTableForGivenMatchOutputBuilder.build())
189                             .build();
190
191                 } else {
192                     rpcResult = RpcResultBuilder
193                             .<GetAggregateFlowStatisticsFromFlowTableForGivenMatchOutput>failed()
194                             .withRpcErrors(input.getErrors())
195                             .build();
196                 }
197                 return rpcResult;
198             }
199         });
200
201     }
202
203     @Override
204     public Future<RpcResult<GetAllFlowStatisticsFromFlowTableOutput>> getAllFlowStatisticsFromFlowTable(
205             final GetAllFlowStatisticsFromFlowTableInput input) {
206
207         return this.<GetAllFlowStatisticsFromFlowTableOutput, Void>handleServiceCall(new Function<RequestContext<GetAllFlowStatisticsFromFlowTableOutput>, ListenableFuture<RpcResult<Void>>>() {
208
209             @Override
210             public ListenableFuture<RpcResult<Void>> apply(final RequestContext<GetAllFlowStatisticsFromFlowTableOutput> requestContext) {
211
212                 final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
213                 mprFlowRequestBuilder.setTableId(input.getTableId().getValue());
214                 mprFlowRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
215                 mprFlowRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
216                 mprFlowRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
217                 mprFlowRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
218
219                 final short version = getVersion();
220                 FlowCreatorUtil.setWildcardedFlowMatch(version, mprFlowRequestBuilder);
221
222                 final MultipartRequestFlowCaseBuilder multipartRequestFlowCaseBuilder = new MultipartRequestFlowCaseBuilder();
223                 multipartRequestFlowCaseBuilder.setMultipartRequestFlow(mprFlowRequestBuilder.build());
224
225                 final Xid xid = requestContext.getXid();
226                 final MultipartRequestInputBuilder mprInput = RequestInputUtils.createMultipartHeader(
227                         MultipartType.OFPMPFLOW, xid.getValue(), version);
228
229                 mprInput.setMultipartRequestBody(multipartRequestFlowCaseBuilder.build());
230                 return StatisticsServiceUtil.getRpcResultListenableFuture(xid, mprInput.build(), getDeviceContext());
231             }
232         });
233     }
234
235     @Override
236     public Future<RpcResult<GetAllFlowsStatisticsFromAllFlowTablesOutput>> getAllFlowsStatisticsFromAllFlowTables(
237             final GetAllFlowsStatisticsFromAllFlowTablesInput input) {
238
239
240         return this.<GetAllFlowsStatisticsFromAllFlowTablesOutput, Void>handleServiceCall(new Function<RequestContext<GetAllFlowsStatisticsFromAllFlowTablesOutput>, ListenableFuture<RpcResult<Void>>>() {
241
242             @Override
243             public ListenableFuture<RpcResult<Void>> apply(final RequestContext<GetAllFlowsStatisticsFromAllFlowTablesOutput> requestContext) {
244
245                 final MultipartRequestFlowCaseBuilder multipartRequestFlowCaseBuilder = new MultipartRequestFlowCaseBuilder();
246                 final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
247                 mprFlowRequestBuilder.setTableId(OFConstants.OFPTT_ALL);
248                 mprFlowRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
249                 mprFlowRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
250                 mprFlowRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
251                 mprFlowRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
252                 final short version = getVersion();
253                 FlowCreatorUtil.setWildcardedFlowMatch(version, mprFlowRequestBuilder);
254
255                 final Xid xid = requestContext.getXid();
256                 final MultipartRequestInputBuilder mprInput = RequestInputUtils.createMultipartHeader(
257                         MultipartType.OFPMPFLOW, xid.getValue(), version);
258
259                 multipartRequestFlowCaseBuilder.setMultipartRequestFlow(mprFlowRequestBuilder.build());
260                 mprInput.setMultipartRequestBody(multipartRequestFlowCaseBuilder.build());
261                 return StatisticsServiceUtil.getRpcResultListenableFuture(xid, mprInput.build(), getDeviceContext());
262             }
263         });
264     }
265
266     @Override
267     public Future<RpcResult<GetFlowStatisticsFromFlowTableOutput>> getFlowStatisticsFromFlowTable(
268             final GetFlowStatisticsFromFlowTableInput input) {
269
270
271         return this.<GetFlowStatisticsFromFlowTableOutput, Void>handleServiceCall(new Function<RequestContext<GetFlowStatisticsFromFlowTableOutput>, ListenableFuture<RpcResult<Void>>>() {
272
273             @Override
274             public ListenableFuture<RpcResult<Void>> apply(final RequestContext<GetFlowStatisticsFromFlowTableOutput> requestContext) {
275
276                 final MultipartRequestFlowCaseBuilder multipartRequestFlowCaseBuilder = new MultipartRequestFlowCaseBuilder();
277                 final MultipartRequestFlowBuilder mprFlowRequestBuilder = new MultipartRequestFlowBuilder();
278                 mprFlowRequestBuilder.setTableId(input.getTableId());
279
280                 if (input.getOutPort() != null) {
281                     mprFlowRequestBuilder.setOutPort(input.getOutPort().longValue());
282                 } else {
283                     mprFlowRequestBuilder.setOutPort(OFConstants.OFPP_ANY);
284                 }
285
286                 if (input.getOutGroup() != null) {
287                     mprFlowRequestBuilder.setOutGroup(input.getOutGroup());
288                 } else {
289                     mprFlowRequestBuilder.setOutGroup(OFConstants.OFPG_ANY);
290                 }
291
292                 if (input.getCookie() != null) {
293                     mprFlowRequestBuilder.setCookie(input.getCookie().getValue());
294                 } else {
295                     mprFlowRequestBuilder.setCookie(OFConstants.DEFAULT_COOKIE);
296                 }
297
298                 if (input.getCookieMask() != null) {
299                     mprFlowRequestBuilder.setCookieMask(input.getCookieMask().getValue());
300                 } else {
301                     mprFlowRequestBuilder.setCookieMask(OFConstants.DEFAULT_COOKIE_MASK);
302                 }
303
304                 // convert and inject match
305                 final short version = getVersion();
306                 final DeviceContext deviceContext = getDeviceContext();
307                 MatchReactor.getInstance().convert(input.getMatch(), version, mprFlowRequestBuilder,
308                         deviceContext.getPrimaryConnectionContext().getFeatures().getDatapathId());
309
310                 // Set request body to main multipart request
311                 final Xid xid = requestContext.getXid();
312                 multipartRequestFlowCaseBuilder.setMultipartRequestFlow(mprFlowRequestBuilder.build());
313                 final MultipartRequestInputBuilder mprInput = RequestInputUtils.createMultipartHeader(
314                         MultipartType.OFPMPFLOW, xid.getValue(), version);
315                 mprInput.setMultipartRequestBody(multipartRequestFlowCaseBuilder.build());
316                 return StatisticsServiceUtil.getRpcResultListenableFuture(xid, mprInput.build(), getDeviceContext());
317             }
318         });
319     }
320
321 }