2 * Copyright (c) 2013 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.openflowplugin.openflow.md.core.sal;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.concurrent.Future;
17 import org.opendaylight.controller.sal.common.util.Rpcs;
18 import org.opendaylight.openflowjava.protocol.api.util.BinContent;
19 import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.FlowConvertor;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.GroupConvertor;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.MeterConvertor;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.PortConvertor;
24 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.TableFeaturesConvertor;
25 import org.opendaylight.openflowplugin.openflow.md.core.session.IMessageDispatchService;
26 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.port.mod.port.Port;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupOutputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutput;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.RemoveGroupOutputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInput;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutput;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupOutputBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsInput;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetAllGroupStatisticsOutputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionInput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionOutput;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupDescriptionOutputBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesInput;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesOutput;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupFeaturesOutputBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatisticsInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatisticsOutput;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GetGroupStatisticsOutputBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterOutputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterOutputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterInput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutput;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.UpdateMeterOutputBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsInput;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutput;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterConfigStatisticsOutputBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutput;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetAllMeterStatisticsOutputBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesOutput;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterFeaturesOutputBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsOutput;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.GetMeterStatisticsOutputBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Group;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Meter;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInput;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInputBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.Match;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.MatchBuilder;
97 //import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features.TableFeatures;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupDescBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupFeaturesBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterConfigBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterFeaturesBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features.TableFeatures;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.GetPortOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutputBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
114 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
115 import org.opendaylight.yangtools.yang.common.RpcError;
116 import org.opendaylight.yangtools.yang.common.RpcResult;
117 import org.slf4j.Logger;
119 import com.google.common.util.concurrent.Futures;
122 * RPC implementation of MD-switch
124 public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
126 private static final Logger LOG = org.slf4j.LoggerFactory
127 .getLogger(ModelDrivenSwitchImpl.class);
128 private final NodeId nodeId;
129 private final IMessageDispatchService messageService ;
130 private short version = 0;
132 protected ModelDrivenSwitchImpl(NodeId nodeId,
133 InstanceIdentifier<Node> identifier, SessionContext context) {
134 super(identifier, context);
135 this.nodeId = nodeId;
136 messageService = sessionContext.getMessageDispatchService() ;
137 version = context.getPrimaryConductor().getVersion();
141 public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
142 // Convert the AddFlowInput to FlowModInput
143 FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input, version);
145 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
146 // the request can be routed through any connection to the switch
148 SwitchConnectionDistinguisher cookie = null ;
150 LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
151 Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
153 RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
156 rpcResultFromOFLib = resultFromOFLib.get();
157 } catch( Exception ex ) {
158 LOG.error( " Error while getting result for AddFlow RPC" + ex.getMessage());
161 UpdateFlowOutput updateFlowOutput = rpcResultFromOFLib.getResult() ;
163 AddFlowOutputBuilder addFlowOutput = new AddFlowOutputBuilder() ;
164 addFlowOutput.setTransactionId(updateFlowOutput.getTransactionId()) ;
165 AddFlowOutput result = addFlowOutput.build();
167 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
168 RpcResult<AddFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
170 LOG.debug("Returning the Add Flow RPC result to MD-SAL");
171 return Futures.immediateFuture(rpcResult);
175 public Future<RpcResult<AddGroupOutput>> addGroup(AddGroupInput input) {
176 // Convert the AddGroupInput to GroupModInput
177 GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input, version);
180 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
181 // the request can be routed through any connection to the switch
183 SwitchConnectionDistinguisher cookie = null ;
185 LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
186 Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
188 RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
191 rpcResultFromOFLib = resultFromOFLib.get();
192 } catch( Exception ex ) {
193 LOG.error( " Error while getting result for AddGroup RPC" + ex.getMessage());
196 UpdateGroupOutput updateGroupOutput = rpcResultFromOFLib.getResult() ;
198 AddGroupOutputBuilder addGroupOutput = new AddGroupOutputBuilder() ;
199 addGroupOutput.setTransactionId(updateGroupOutput.getTransactionId()) ;
200 AddGroupOutput result = addGroupOutput.build();
202 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
203 RpcResult<AddGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
205 LOG.debug("Returning the Add Group RPC result to MD-SAL");
206 return Futures.immediateFuture(rpcResult);
210 public Future<RpcResult<AddMeterOutput>> addMeter(AddMeterInput input) {
211 // Convert the AddMeterInput to MeterModInput
212 MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input, version);
215 // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
216 // the request can be routed through any connection to the switch
218 SwitchConnectionDistinguisher cookie = null ;
220 LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
221 Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
223 RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
226 rpcResultFromOFLib = resultFromOFLib.get();
227 } catch( Exception ex ) {
228 LOG.error( " Error while getting result for AddMeter RPC" + ex.getMessage());
231 UpdateMeterOutput updateMeterOutput = rpcResultFromOFLib.getResult() ;
233 AddMeterOutputBuilder addMeterOutput = new AddMeterOutputBuilder() ;
234 addMeterOutput.setTransactionId(updateMeterOutput.getTransactionId()) ;
235 AddMeterOutput result = addMeterOutput.build();
237 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
238 RpcResult<AddMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
240 LOG.debug("Returning the Add Meter RPC result to MD-SAL");
241 return Futures.immediateFuture(rpcResult);
245 public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
246 // Convert the RemoveFlowInput to FlowModInput
247 FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input, version);
250 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
251 // the request can be routed through any connection to the switch
253 SwitchConnectionDistinguisher cookie = null ;
255 LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
256 Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
258 RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
261 rpcResultFromOFLib = resultFromOFLib.get();
262 } catch( Exception ex ) {
263 LOG.error( " Error while getting result for remove Flow RPC" + ex.getMessage());
266 UpdateFlowOutput updateFlowOutput = rpcResultFromOFLib.getResult() ;
268 RemoveFlowOutputBuilder removeFlowOutput = new RemoveFlowOutputBuilder() ;
269 removeFlowOutput.setTransactionId(updateFlowOutput.getTransactionId()) ;
270 RemoveFlowOutput result = removeFlowOutput.build();
272 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
273 RpcResult<RemoveFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
275 LOG.debug("Returning the Remove Flow RPC result to MD-SAL");
276 return Futures.immediateFuture(rpcResult);
280 public Future<RpcResult<RemoveGroupOutput>> removeGroup(
281 RemoveGroupInput input) {
282 // Convert the RemoveGroupInput to GroupModInput
283 GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input, version);
286 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
287 // the request can be routed through any connection to the switch
289 SwitchConnectionDistinguisher cookie = null ;
291 LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
292 Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
294 RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
297 rpcResultFromOFLib = resultFromOFLib.get();
298 } catch( Exception ex ) {
299 LOG.error( " Error while getting result for RemoveGroup RPC" + ex.getMessage());
302 UpdateGroupOutput updateGroupOutput = rpcResultFromOFLib.getResult() ;
304 RemoveGroupOutputBuilder removeGroupOutput = new RemoveGroupOutputBuilder() ;
305 removeGroupOutput.setTransactionId(updateGroupOutput.getTransactionId()) ;
306 RemoveGroupOutput result = removeGroupOutput.build();
308 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
309 RpcResult<RemoveGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
311 LOG.debug("Returning the Remove Group RPC result to MD-SAL");
312 return Futures.immediateFuture(rpcResult);
316 public Future<RpcResult<RemoveMeterOutput>> removeMeter(
317 RemoveMeterInput input) {
318 // Convert the RemoveMeterInput to MeterModInput
319 MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input, version);
322 // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
323 // the request can be routed through any connection to the switch
325 SwitchConnectionDistinguisher cookie = null ;
327 LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
328 Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
330 RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
333 rpcResultFromOFLib = resultFromOFLib.get();
334 } catch( Exception ex ) {
335 LOG.error( " Error while getting result for RemoveMeter RPC" + ex.getMessage());
338 UpdateMeterOutput updatemeterOutput = rpcResultFromOFLib.getResult() ;
340 RemoveMeterOutputBuilder removeMeterOutput = new RemoveMeterOutputBuilder() ;
341 removeMeterOutput.setTransactionId(updatemeterOutput.getTransactionId()) ;
342 RemoveMeterOutput result = removeMeterOutput.build();
344 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
345 RpcResult<RemoveMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
347 LOG.debug("Returning the Remove Meter RPC result to MD-SAL");
348 return Futures.immediateFuture(rpcResult);
352 public Future<RpcResult<Void>> transmitPacket(TransmitPacketInput input) {
353 // TODO Auto-generated method stub
357 private FlowModInputBuilder toFlowModInputBuilder(Flow source) {
358 FlowModInputBuilder target = new FlowModInputBuilder();
359 target.setCookie(source.getCookie());
360 target.setIdleTimeout(source.getIdleTimeout());
361 target.setHardTimeout(source.getHardTimeout());
362 target.setMatch(toMatch(source.getMatch()));
367 private Match toMatch(
368 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match match) {
369 MatchBuilder target = new MatchBuilder();
371 target.setMatchEntries(toMatchEntries(match));
376 private List<MatchEntries> toMatchEntries(
377 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match match) {
378 List<MatchEntries> entries = new ArrayList<>();
384 public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
385 // Convert the UpdateFlowInput to FlowModInput
386 FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input.getUpdatedFlow(), version);
388 // Call the RPC method on MessageDispatchService
390 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
391 // the request can be routed through any connection to the switch
393 SwitchConnectionDistinguisher cookie = null ;
395 LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
396 Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
398 RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
401 rpcResultFromOFLib = resultFromOFLib.get();
402 } catch( Exception ex ) {
403 LOG.error( " Error while getting result for UpdateFlow RPC" + ex.getMessage());
406 UpdateFlowOutput updateFlowOutputOFLib = rpcResultFromOFLib.getResult() ;
408 UpdateFlowOutputBuilder updateFlowOutput = new UpdateFlowOutputBuilder() ;
409 updateFlowOutput.setTransactionId(updateFlowOutputOFLib.getTransactionId()) ;
410 UpdateFlowOutput result = updateFlowOutput.build();
412 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
413 RpcResult<UpdateFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
415 LOG.debug("Returning the Update Flow RPC result to MD-SAL");
416 return Futures.immediateFuture(rpcResult);
420 public Future<RpcResult<UpdateGroupOutput>> updateGroup(
421 UpdateGroupInput input) {
422 // Convert the UpdateGroupInput to GroupModInput
423 GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input.getUpdatedGroup(), version);
426 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
427 // the request can be routed through any connection to the switch
429 SwitchConnectionDistinguisher cookie = null ;
431 LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
432 Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
434 RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
437 rpcResultFromOFLib = resultFromOFLib.get();
438 } catch( Exception ex ) {
439 LOG.error( " Error while getting result for updateGroup RPC" + ex.getMessage());
442 UpdateGroupOutput updateGroupOutputOFLib = rpcResultFromOFLib.getResult() ;
444 UpdateGroupOutputBuilder updateGroupOutput = new UpdateGroupOutputBuilder() ;
445 updateGroupOutput.setTransactionId(updateGroupOutputOFLib.getTransactionId()) ;
446 UpdateGroupOutput result = updateGroupOutput.build();
448 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
449 RpcResult<UpdateGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
451 LOG.debug("Returning the Update Group RPC result to MD-SAL");
452 return Futures.immediateFuture(rpcResult);
456 public Future<RpcResult<UpdateMeterOutput>> updateMeter(
457 UpdateMeterInput input) {
458 // Convert the UpdateMeterInput to MeterModInput
459 MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input.getUpdatedMeter(), version);
462 // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
463 // the request can be routed through any connection to the switch
465 SwitchConnectionDistinguisher cookie = null ;
467 LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
468 Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
470 RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
473 rpcResultFromOFLib = resultFromOFLib.get();
474 } catch( Exception ex ) {
475 LOG.error( " Error while getting result for UpdateMeter RPC" + ex.getMessage());
478 UpdateMeterOutput updateMeterOutputFromOFLib = rpcResultFromOFLib.getResult() ;
480 UpdateMeterOutputBuilder updateMeterOutput = new UpdateMeterOutputBuilder() ;
481 updateMeterOutput.setTransactionId(updateMeterOutputFromOFLib.getTransactionId()) ;
482 UpdateMeterOutput result = updateMeterOutput.build();
484 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
485 RpcResult<UpdateMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
487 LOG.debug("Returning the Update Meter RPC result to MD-SAL");
488 return Futures.immediateFuture(rpcResult);
492 public NodeId getNodeId() {
497 * Methods for requesting statistics from switch
500 public Future<RpcResult<GetAllGroupStatisticsOutput>> getAllGroupStatistics(GetAllGroupStatisticsInput input) {
502 //Generate xid to associate it with the request
503 Long xid = this.getSessionContext().getNextXid();
505 LOG.debug("Prepare statistics request for all the groups - Transaction id - {}",xid);
507 // Create multipart request header
508 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
509 mprInput.setType(MultipartType.OFPMPGROUP);
510 mprInput.setVersion(version);
511 mprInput.setXid(xid);
512 mprInput.setFlags(new MultipartRequestFlags(false));
514 // Create multipart request body for fetch all the group stats
515 MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
516 mprGroupBuild.setGroupId(BinContent.intToUnsignedLong(Group.OFPGALL.getIntValue()));
518 //Set request body to main multipart request
519 mprInput.setMultipartRequestBody(mprGroupBuild.build());
521 //Send the request, no cookies associated, use any connection
522 LOG.debug("Send group statistics request to the switch :{}",mprGroupBuild);
523 this.messageService.multipartRequest(mprInput.build(), null);
525 // Prepare rpc return output. Set xid and send it back.
526 LOG.debug("Return results and transaction id back to caller");
527 GetAllGroupStatisticsOutputBuilder output = new GetAllGroupStatisticsOutputBuilder();
528 output.setTransactionId(generateTransactionId(xid));
529 output.setGroupStats(null);
531 Collection<RpcError> errors = Collections.emptyList();
532 RpcResult<GetAllGroupStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
533 return Futures.immediateFuture(rpcResult);
538 public Future<RpcResult<GetGroupDescriptionOutput>> getGroupDescription(GetGroupDescriptionInput input) {
540 //Generate xid to associate it with the request
541 Long xid = this.getSessionContext().getNextXid();
543 LOG.debug("Prepare group description statistics request - Transaction id - {}",xid);
545 // Create multipart request header
546 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
547 mprInput.setType(MultipartType.OFPMPGROUPDESC);
548 mprInput.setVersion(version);
549 mprInput.setXid(xid);
550 mprInput.setFlags(new MultipartRequestFlags(false));
552 // Create multipart request body for fetch all the group description stats
553 MultipartRequestGroupDescBuilder mprGroupDescBuild = new MultipartRequestGroupDescBuilder();
555 //Set request body to main multipart request
556 mprInput.setMultipartRequestBody(mprGroupDescBuild.build());
558 //Send the request, no cookies associated, use any connection
559 LOG.debug("Send group desciption statistics request to switch : {}",mprGroupDescBuild);
560 this.messageService.multipartRequest(mprInput.build(), null);
562 // Prepare rpc return output. Set xid and send it back.
563 LOG.debug("Return results and transaction id back to caller");
564 GetGroupDescriptionOutputBuilder output = new GetGroupDescriptionOutputBuilder();
565 output.setTransactionId(generateTransactionId(xid));
566 output.setGroupDescStats(null);
568 Collection<RpcError> errors = Collections.emptyList();
569 RpcResult<GetGroupDescriptionOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
570 return Futures.immediateFuture(rpcResult);
575 public Future<RpcResult<GetGroupFeaturesOutput>> getGroupFeatures(GetGroupFeaturesInput input) {
577 //Generate xid to associate it with the request
578 Long xid = this.getSessionContext().getNextXid();
580 LOG.debug("Prepare group features statistics request - Transaction id - {}",xid);
582 // Create multipart request header
583 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
584 mprInput.setType(MultipartType.OFPMPGROUPFEATURES);
585 mprInput.setVersion(version);
586 mprInput.setXid(xid);
587 mprInput.setFlags(new MultipartRequestFlags(false));
589 // Create multipart request body for fetch all the group description stats
590 MultipartRequestGroupFeaturesBuilder mprGroupFeaturesBuild = new MultipartRequestGroupFeaturesBuilder();
592 //Set request body to main multipart request
593 mprInput.setMultipartRequestBody(mprGroupFeaturesBuild.build());
595 //Send the request, no cookies associated, use any connection
596 LOG.debug("Send group features statistics request :{}",mprGroupFeaturesBuild);
597 this.messageService.multipartRequest(mprInput.build(), null);
599 // Prepare rpc return output. Set xid and send it back.
600 LOG.debug("Return results and transaction id back to caller");
601 GetGroupFeaturesOutputBuilder output = new GetGroupFeaturesOutputBuilder();
602 output.setTransactionId(generateTransactionId(xid));
604 Collection<RpcError> errors = Collections.emptyList();
605 RpcResult<GetGroupFeaturesOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
606 return Futures.immediateFuture(rpcResult);
610 public Future<RpcResult<GetGroupStatisticsOutput>> getGroupStatistics(GetGroupStatisticsInput input) {
612 //Generate xid to associate it with the request
613 Long xid = this.getSessionContext().getNextXid();
615 LOG.debug("Prepare statistics request for node {} group ({}) - Transaction id - {}",input.getNode(),input.getGroupId(),xid);
617 // Create multipart request header
618 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
619 mprInput.setType(MultipartType.OFPMPGROUP);
620 mprInput.setVersion(version);
621 mprInput.setXid(xid);
622 mprInput.setFlags(new MultipartRequestFlags(false));
624 // Create multipart request body for fetch all the group stats
625 MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
626 mprGroupBuild.setGroupId(input.getGroupId().getValue());
628 //Set request body to main multipart request
629 mprInput.setMultipartRequestBody(mprGroupBuild.build());
631 //Send the request, no cookies associated, use any connection
632 LOG.debug("Send group statistics request :{}",mprGroupBuild);
633 this.messageService.multipartRequest(mprInput.build(), null);
635 // Prepare rpc return output. Set xid and send it back.
636 LOG.debug("Return results and transaction id back to caller");
637 GetGroupStatisticsOutputBuilder output = new GetGroupStatisticsOutputBuilder();
638 output.setTransactionId(generateTransactionId(xid));
639 output.setGroupStats(null);
641 Collection<RpcError> errors = Collections.emptyList();
642 RpcResult<GetGroupStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
643 return Futures.immediateFuture(rpcResult);
647 public Future<RpcResult<GetAllMeterConfigStatisticsOutput>> getAllMeterConfigStatistics(
648 GetAllMeterConfigStatisticsInput input) {
650 //Generate xid to associate it with the request
651 Long xid = this.getSessionContext().getNextXid();
653 LOG.debug("Prepare config request for all the meters - Transaction id - {}",xid);
655 // Create multipart request header
656 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
657 mprInput.setType(MultipartType.OFPMPMETERCONFIG);
658 mprInput.setVersion(version);
659 mprInput.setXid(xid);
660 mprInput.setFlags(new MultipartRequestFlags(false));
662 // Create multipart request body for fetch all the meter stats
663 MultipartRequestMeterConfigBuilder mprMeterConfigBuild = new MultipartRequestMeterConfigBuilder();
664 mprMeterConfigBuild.setMeterId(BinContent.intToUnsignedLong(Meter.OFPMALL.getIntValue()));
666 //Set request body to main multipart request
667 mprInput.setMultipartRequestBody(mprMeterConfigBuild.build());
669 //Send the request, no cookies associated, use any connection
670 LOG.debug("Send meter statistics request :{}",mprMeterConfigBuild);
671 this.messageService.multipartRequest(mprInput.build(), null);
673 // Prepare rpc return output. Set xid and send it back.
674 LOG.debug("Return results and transaction id back to caller");
675 GetAllMeterConfigStatisticsOutputBuilder output = new GetAllMeterConfigStatisticsOutputBuilder();
676 output.setTransactionId(generateTransactionId(xid));
677 output.setMeterConfigStats(null);
679 Collection<RpcError> errors = Collections.emptyList();
680 RpcResult<GetAllMeterConfigStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
681 return Futures.immediateFuture(rpcResult);
685 public Future<RpcResult<GetAllMeterStatisticsOutput>> getAllMeterStatistics(GetAllMeterStatisticsInput input) {
687 //Generate xid to associate it with the request
688 Long xid = this.getSessionContext().getNextXid();
690 LOG.debug("Prepare statistics request for all the meters - Transaction id - {}",xid);
692 // Create multipart request header
693 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
694 mprInput.setType(MultipartType.OFPMPMETER);
695 mprInput.setVersion(version);
696 mprInput.setXid(xid);
697 mprInput.setFlags(new MultipartRequestFlags(false));
699 // Create multipart request body for fetch all the meter stats
700 MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
701 mprMeterBuild.setMeterId(BinContent.intToUnsignedLong(Meter.OFPMALL.getIntValue()));
703 //Set request body to main multipart request
704 mprInput.setMultipartRequestBody(mprMeterBuild.build());
706 //Send the request, no cookies associated, use any connection
707 LOG.debug("Send meter statistics request :{}",mprMeterBuild);
708 this.messageService.multipartRequest(mprInput.build(), null);
710 // Prepare rpc return output. Set xid and send it back.
711 LOG.debug("Return results and transaction id back to caller");
712 GetAllMeterStatisticsOutputBuilder output = new GetAllMeterStatisticsOutputBuilder();
713 output.setTransactionId(generateTransactionId(xid));
714 output.setMeterStats(null);
716 Collection<RpcError> errors = Collections.emptyList();
717 RpcResult<GetAllMeterStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
718 return Futures.immediateFuture(rpcResult);
722 public Future<RpcResult<GetMeterFeaturesOutput>> getMeterFeatures(GetMeterFeaturesInput input) {
724 //Generate xid to associate it with the request
725 Long xid = this.getSessionContext().getNextXid();
727 LOG.debug("Prepare features statistics request for all the meters - Transaction id - {}",xid);
729 // Create multipart request header
730 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
731 mprInput.setType(MultipartType.OFPMPMETERFEATURES);
732 mprInput.setVersion(version);
733 mprInput.setXid(xid);
734 mprInput.setFlags(new MultipartRequestFlags(false));
736 // Create multipart request body for fetch all the group description stats
737 MultipartRequestMeterFeaturesBuilder mprMeterFeaturesBuild = new MultipartRequestMeterFeaturesBuilder();
739 //Set request body to main multipart request
740 mprInput.setMultipartRequestBody(mprMeterFeaturesBuild.build());
742 //Send the request, no cookies associated, use any connection
743 LOG.debug("Send meter features statistics request :{}",mprMeterFeaturesBuild);
744 this.messageService.multipartRequest(mprInput.build(), null);
746 // Prepare rpc return output. Set xid and send it back.
747 LOG.debug("Return results and transaction id back to caller");
748 GetMeterFeaturesOutputBuilder output = new GetMeterFeaturesOutputBuilder();
749 output.setTransactionId(generateTransactionId(xid));
751 Collection<RpcError> errors = Collections.emptyList();
752 RpcResult<GetMeterFeaturesOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
753 return Futures.immediateFuture(rpcResult);
757 public Future<RpcResult<GetMeterStatisticsOutput>> getMeterStatistics(GetMeterStatisticsInput input) {
758 //Generate xid to associate it with the request
759 Long xid = this.getSessionContext().getNextXid();
761 LOG.debug("Preprae statistics request for Meter ({}) - Transaction id - {}",input.getMeterId().getValue(),xid);
763 // Create multipart request header
764 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
765 mprInput.setType(MultipartType.OFPMPMETER);
766 mprInput.setVersion(version);
767 mprInput.setXid(xid);
768 mprInput.setFlags(new MultipartRequestFlags(false));
770 // Create multipart request body for fetch all the meter stats
771 MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
772 //Select specific meter
773 mprMeterBuild.setMeterId(input.getMeterId().getValue());
775 //Set request body to main multipart request
776 mprInput.setMultipartRequestBody(mprMeterBuild.build());
778 //Send the request, no cookies associated, use any connection
779 LOG.debug("Send meter statistics request :{}",mprMeterBuild);
780 this.messageService.multipartRequest(mprInput.build(), null);
782 // Prepare rpc return output. Set xid and send it back.
783 LOG.debug("Return results and transaction id back to caller");
784 GetMeterStatisticsOutputBuilder output = new GetMeterStatisticsOutputBuilder();
785 output.setTransactionId(generateTransactionId(xid));
786 output.setMeterStats(null);
788 Collection<RpcError> errors = Collections.emptyList();
789 RpcResult<GetMeterStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
790 return Futures.immediateFuture(rpcResult);
793 private TransactionId generateTransactionId(Long xid){
794 String stringXid =xid.toString();
795 BigInteger bigIntXid = new BigInteger( stringXid );
796 return new TransactionId(bigIntXid);
801 public Future<RpcResult<GetPortOutput>> getPort() {
802 // TODO Auto-generated method stub
807 public Future<RpcResult<UpdatePortOutput>> updatePort(UpdatePortInput input) {
808 PortModInput ofPortModInput = null ;
809 RpcResult<UpdatePortOutput> rpcResultFromOFLib = null ;
812 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
813 // the request can be routed through any connection to the switch
815 SwitchConnectionDistinguisher cookie = null ;
817 // NSF sends a list of port and the ModelDrivenSwitch will
818 // send one port at a time towards the switch ( mutiple RPCs calls)
819 List<Port> inputPorts = input.getUpdatedPort().getPort().getPort() ;
821 // Get the Xid. The same Xid has to be sent in all the RPCs
822 Long Xid = sessionContext.getNextXid();
824 for( Port inputPort : inputPorts) {
826 // Convert the UpdateGroupInput to GroupModInput
827 ofPortModInput = PortConvertor.toPortModInput(inputPort, version) ;
829 // Insert the Xid ( transaction Id) before calling the RPC on the OFLibrary
831 PortModInputBuilder mdInput = new PortModInputBuilder();
833 mdInput.setVersion(ofPortModInput.getVersion()) ;
834 mdInput.setPortNo(ofPortModInput.getPortNo()) ;
835 mdInput.setMaskV10(ofPortModInput.getMaskV10()) ;
836 mdInput.setMask(ofPortModInput.getMask()) ;
837 mdInput.setHwAddress(ofPortModInput.getHwAddress());
838 mdInput.setConfigV10(ofPortModInput.getConfigV10()) ;
839 mdInput.setConfig(ofPortModInput.getConfig()) ;
840 mdInput.setAdvertiseV10(ofPortModInput.getAdvertiseV10()) ;
841 mdInput.setAdvertise(ofPortModInput.getAdvertise()) ;
843 LOG.debug("Calling the PortMod RPC method on MessageDispatchService");
844 Future<RpcResult<UpdatePortOutput>> resultFromOFLib = messageService.portMod(ofPortModInput, cookie) ;
847 rpcResultFromOFLib = resultFromOFLib.get();
848 } catch( Exception ex ) {
849 LOG.error( " Error while getting result for updatePort RPC" + ex.getMessage());
852 // The Future response value for all the RPCs except the last one is ignored
856 //Extract the Xid only from the Future for the last RPC and
857 // send it back to the NSF
858 UpdatePortOutput updatePortOutputOFLib = rpcResultFromOFLib.getResult() ;
860 UpdatePortOutputBuilder updatePortOutput = new UpdatePortOutputBuilder() ;
861 updatePortOutput.setTransactionId(updatePortOutputOFLib.getTransactionId()) ;
862 UpdatePortOutput result = updatePortOutput.build();
864 Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
865 RpcResult<UpdatePortOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
867 LOG.debug("Returning the Update Group RPC result to MD-SAL");
868 return Futures.immediateFuture(rpcResult);
872 public Future<RpcResult<UpdateTableOutput>> updateTable(
873 UpdateTableInput input) {
875 // Get the Xid. The same Xid has to be sent in all the Multipart requests
876 Long xid = this.getSessionContext().getNextXid();
878 LOG.debug("Prepare the Multipart Table Mod requests for Transaction Id {} ",xid);
880 // Create multipart request header
881 MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
882 mprInput.setType(MultipartType.OFPMPTABLEFEATURES);
883 mprInput.setVersion((short)0x04);
884 mprInput.setXid(xid);
886 //Convert the list of all MD-SAL table feature object into OF library object
887 List<TableFeatures> ofTableFeatureList = TableFeaturesConvertor.toTableFeaturesRequest(input.getUpdatedTable()) ;
888 int totalNoOfTableFeatureEntry = ofTableFeatureList.size();
890 MultipartRequestTableFeaturesBuilder tableFeaturesRequest = new MultipartRequestTableFeaturesBuilder();
892 // Slice the multipart request based on the configuration parameter, which is the no. of TableFeatureList element
893 // to be put in one multipart message. Default is 5
894 // This parameter must be set based on switch's Buffer capacity
896 List<TableFeatures> tmpOfTableFeatureList = null ;
897 String tableFeatureListCount = System.getProperty( "of.tableFeaturesCountPerMultipart", "5") ;
898 int noOfEntriesInMPR = Integer.parseInt(tableFeatureListCount) ;
901 while(totalNoOfTableFeatureEntry-index > 0 ) {
902 if( (totalNoOfTableFeatureEntry-index) > noOfEntriesInMPR ) {
903 mprInput.setFlags(new MultipartRequestFlags(true));
904 tmpOfTableFeatureList = ofTableFeatureList.subList(index, index + noOfEntriesInMPR);
907 // Last multipart request
908 mprInput.setFlags(new MultipartRequestFlags(false));
909 tmpOfTableFeatureList = ofTableFeatureList.subList(index, totalNoOfTableFeatureEntry );
912 tableFeaturesRequest.setTableFeatures(tmpOfTableFeatureList) ;
913 //Set request body to main multipart request
914 mprInput.setMultipartRequestBody(tableFeaturesRequest.build());
916 //Send the request, no cookies associated, use any connection
917 LOG.debug("Send Table Feature request :{}",tmpOfTableFeatureList);
918 this.messageService.multipartRequest(mprInput.build(), null);
919 index += noOfEntriesInMPR ;
920 tmpOfTableFeatureList = null ; // To avoid any corrupt data
922 //Extract the Xid only from the Future for the last RPC and
923 // send it back to the NSF
924 LOG.debug("Returning the result and transaction id to NSF");
925 LOG.debug("Return results and transaction id back to caller");
926 UpdateTableOutputBuilder output = new UpdateTableOutputBuilder();
927 output.setTransactionId(generateTransactionId(xid));
929 Collection<RpcError> errors = Collections.emptyList();
930 RpcResult<UpdateTableOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
931 return Futures.immediateFuture(rpcResult);