Implemented Table Feature Multipart RPC
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / ModelDrivenSwitchImpl.java
1 /**
2  * Copyright (c) 2013 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.openflow.md.core.sal;
9
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;
16
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;
118
119 import com.google.common.util.concurrent.Futures;
120
121 /**
122  * RPC implementation of MD-switch
123  */
124 public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
125
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;
131
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();
138     }
139
140     @Override
141     public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
142         // Convert the AddFlowInput to FlowModInput
143         FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input, version);
144
145         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
146         // the request can be routed through any connection to the switch
147
148         SwitchConnectionDistinguisher cookie = null ;
149
150         LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
151         Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
152
153         RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
154
155         try {
156                 rpcResultFromOFLib = resultFromOFLib.get();
157         } catch( Exception ex ) {
158                 LOG.error( " Error while getting result for AddFlow RPC" + ex.getMessage());
159         }
160
161         UpdateFlowOutput updateFlowOutput = rpcResultFromOFLib.getResult() ;
162
163         AddFlowOutputBuilder addFlowOutput = new AddFlowOutputBuilder() ;
164         addFlowOutput.setTransactionId(updateFlowOutput.getTransactionId()) ;
165         AddFlowOutput result = addFlowOutput.build();
166
167         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
168         RpcResult<AddFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
169
170         LOG.debug("Returning the Add Flow RPC result to MD-SAL");
171         return Futures.immediateFuture(rpcResult);
172     }
173
174     @Override
175     public Future<RpcResult<AddGroupOutput>> addGroup(AddGroupInput input) {
176         // Convert the AddGroupInput to GroupModInput
177         GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input, version);
178
179
180         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
181         // the request can be routed through any connection to the switch
182
183         SwitchConnectionDistinguisher cookie = null ;
184
185         LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
186         Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
187
188         RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
189
190         try {
191                 rpcResultFromOFLib = resultFromOFLib.get();
192         } catch( Exception ex ) {
193                 LOG.error( " Error while getting result for AddGroup RPC" + ex.getMessage());
194         }
195
196         UpdateGroupOutput updateGroupOutput = rpcResultFromOFLib.getResult() ;
197
198         AddGroupOutputBuilder addGroupOutput = new AddGroupOutputBuilder() ;
199         addGroupOutput.setTransactionId(updateGroupOutput.getTransactionId()) ;
200         AddGroupOutput result = addGroupOutput.build();
201
202         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
203         RpcResult<AddGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
204
205         LOG.debug("Returning the Add Group RPC result to MD-SAL");
206         return Futures.immediateFuture(rpcResult);
207     }
208
209     @Override
210     public Future<RpcResult<AddMeterOutput>> addMeter(AddMeterInput input) {
211         // Convert the AddMeterInput to MeterModInput
212         MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input, version);
213
214
215         // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
216         // the request can be routed through any connection to the switch
217
218         SwitchConnectionDistinguisher cookie = null ;
219
220         LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
221         Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
222
223         RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
224
225         try {
226                 rpcResultFromOFLib = resultFromOFLib.get();
227         } catch( Exception ex ) {
228                 LOG.error( " Error while getting result for AddMeter RPC" + ex.getMessage());
229         }
230
231         UpdateMeterOutput updateMeterOutput = rpcResultFromOFLib.getResult() ;
232
233         AddMeterOutputBuilder addMeterOutput = new AddMeterOutputBuilder() ;
234         addMeterOutput.setTransactionId(updateMeterOutput.getTransactionId()) ;
235         AddMeterOutput result = addMeterOutput.build();
236
237         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
238         RpcResult<AddMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
239
240         LOG.debug("Returning the Add Meter RPC result to MD-SAL");
241         return Futures.immediateFuture(rpcResult);
242     }
243
244     @Override
245     public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
246         // Convert the RemoveFlowInput to FlowModInput
247         FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input, version);
248
249
250         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
251         // the request can be routed through any connection to the switch
252
253         SwitchConnectionDistinguisher cookie = null ;
254
255         LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
256         Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
257
258         RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
259
260         try {
261                 rpcResultFromOFLib = resultFromOFLib.get();
262         } catch( Exception ex ) {
263                 LOG.error( " Error while getting result for remove Flow RPC" + ex.getMessage());
264         }
265
266         UpdateFlowOutput updateFlowOutput = rpcResultFromOFLib.getResult() ;
267
268         RemoveFlowOutputBuilder removeFlowOutput = new RemoveFlowOutputBuilder() ;
269         removeFlowOutput.setTransactionId(updateFlowOutput.getTransactionId()) ;
270         RemoveFlowOutput result = removeFlowOutput.build();
271
272         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
273         RpcResult<RemoveFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
274
275         LOG.debug("Returning the Remove Flow RPC result to MD-SAL");
276         return Futures.immediateFuture(rpcResult);
277     }
278
279     @Override
280     public Future<RpcResult<RemoveGroupOutput>> removeGroup(
281             RemoveGroupInput input) {
282         // Convert the RemoveGroupInput to GroupModInput
283         GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input, version);
284
285
286         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
287         // the request can be routed through any connection to the switch
288
289         SwitchConnectionDistinguisher cookie = null ;
290
291         LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
292         Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
293
294         RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
295
296         try {
297                 rpcResultFromOFLib = resultFromOFLib.get();
298         } catch( Exception ex ) {
299                 LOG.error( " Error while getting result for RemoveGroup RPC" + ex.getMessage());
300         }
301
302         UpdateGroupOutput updateGroupOutput = rpcResultFromOFLib.getResult() ;
303
304         RemoveGroupOutputBuilder removeGroupOutput = new RemoveGroupOutputBuilder() ;
305         removeGroupOutput.setTransactionId(updateGroupOutput.getTransactionId()) ;
306         RemoveGroupOutput result = removeGroupOutput.build();
307
308         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
309         RpcResult<RemoveGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
310
311         LOG.debug("Returning the Remove Group RPC result to MD-SAL");
312         return Futures.immediateFuture(rpcResult);
313     }
314
315     @Override
316     public Future<RpcResult<RemoveMeterOutput>> removeMeter(
317             RemoveMeterInput input) {
318         // Convert the RemoveMeterInput to MeterModInput
319         MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input, version);
320
321
322         // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
323         // the request can be routed through any connection to the switch
324
325         SwitchConnectionDistinguisher cookie = null ;
326
327         LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
328         Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
329
330         RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
331
332         try {
333                 rpcResultFromOFLib = resultFromOFLib.get();
334         } catch( Exception ex ) {
335                 LOG.error( " Error while getting result for RemoveMeter RPC" + ex.getMessage());
336         }
337
338         UpdateMeterOutput updatemeterOutput = rpcResultFromOFLib.getResult() ;
339
340         RemoveMeterOutputBuilder removeMeterOutput = new RemoveMeterOutputBuilder() ;
341         removeMeterOutput.setTransactionId(updatemeterOutput.getTransactionId()) ;
342         RemoveMeterOutput result = removeMeterOutput.build();
343
344         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
345         RpcResult<RemoveMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
346
347         LOG.debug("Returning the Remove Meter RPC result to MD-SAL");
348         return Futures.immediateFuture(rpcResult);
349     }
350
351     @Override
352     public Future<RpcResult<Void>> transmitPacket(TransmitPacketInput input) {
353         // TODO Auto-generated method stub
354         return null;
355     }
356
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()));
363
364         return target;
365     }
366
367     private Match toMatch(
368             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match match) {
369         MatchBuilder target = new MatchBuilder();
370
371         target.setMatchEntries(toMatchEntries(match));
372
373         return null;
374     }
375
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<>();
379
380         return null;
381     }
382
383     @Override
384     public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
385         // Convert the UpdateFlowInput to FlowModInput
386         FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input.getUpdatedFlow(), version);
387
388         // Call the RPC method on MessageDispatchService
389
390         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
391         // the request can be routed through any connection to the switch
392
393         SwitchConnectionDistinguisher cookie = null ;
394
395         LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
396         Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
397
398         RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
399
400         try {
401                 rpcResultFromOFLib = resultFromOFLib.get();
402         } catch( Exception ex ) {
403                 LOG.error( " Error while getting result for UpdateFlow RPC" + ex.getMessage());
404         }
405
406         UpdateFlowOutput updateFlowOutputOFLib = rpcResultFromOFLib.getResult() ;
407
408         UpdateFlowOutputBuilder updateFlowOutput = new UpdateFlowOutputBuilder() ;
409         updateFlowOutput.setTransactionId(updateFlowOutputOFLib.getTransactionId()) ;
410         UpdateFlowOutput result = updateFlowOutput.build();
411
412         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
413         RpcResult<UpdateFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
414
415         LOG.debug("Returning the Update Flow RPC result to MD-SAL");
416         return Futures.immediateFuture(rpcResult);
417     }
418
419     @Override
420     public Future<RpcResult<UpdateGroupOutput>> updateGroup(
421             UpdateGroupInput input) {
422         // Convert the UpdateGroupInput to GroupModInput
423         GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input.getUpdatedGroup(), version);
424
425
426         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
427         // the request can be routed through any connection to the switch
428
429         SwitchConnectionDistinguisher cookie = null ;
430
431         LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
432         Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
433
434         RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
435
436         try {
437                 rpcResultFromOFLib = resultFromOFLib.get();
438         } catch( Exception ex ) {
439                 LOG.error( " Error while getting result for updateGroup RPC" + ex.getMessage());
440         }
441
442         UpdateGroupOutput updateGroupOutputOFLib = rpcResultFromOFLib.getResult() ;
443
444         UpdateGroupOutputBuilder updateGroupOutput = new UpdateGroupOutputBuilder() ;
445         updateGroupOutput.setTransactionId(updateGroupOutputOFLib.getTransactionId()) ;
446         UpdateGroupOutput result = updateGroupOutput.build();
447
448         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
449         RpcResult<UpdateGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
450
451         LOG.debug("Returning the Update Group RPC result to MD-SAL");
452         return Futures.immediateFuture(rpcResult);
453     }
454
455     @Override
456     public Future<RpcResult<UpdateMeterOutput>> updateMeter(
457             UpdateMeterInput input) {
458         // Convert the UpdateMeterInput to MeterModInput
459         MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input.getUpdatedMeter(), version);
460
461
462         // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
463         // the request can be routed through any connection to the switch
464
465         SwitchConnectionDistinguisher cookie = null ;
466
467         LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
468         Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
469
470         RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
471
472         try {
473                 rpcResultFromOFLib = resultFromOFLib.get();
474         } catch( Exception ex ) {
475                 LOG.error( " Error while getting result for UpdateMeter RPC" + ex.getMessage());
476         }
477
478         UpdateMeterOutput updateMeterOutputFromOFLib = rpcResultFromOFLib.getResult() ;
479
480         UpdateMeterOutputBuilder updateMeterOutput = new UpdateMeterOutputBuilder() ;
481         updateMeterOutput.setTransactionId(updateMeterOutputFromOFLib.getTransactionId()) ;
482         UpdateMeterOutput result = updateMeterOutput.build();
483
484         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
485         RpcResult<UpdateMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
486
487         LOG.debug("Returning the Update Meter RPC result to MD-SAL");
488         return Futures.immediateFuture(rpcResult);
489     }
490
491     @Override
492     public NodeId getNodeId() {
493         return nodeId;
494     }
495
496     /*
497      * Methods for requesting statistics from switch
498      */
499     @Override
500     public Future<RpcResult<GetAllGroupStatisticsOutput>> getAllGroupStatistics(GetAllGroupStatisticsInput input) {
501
502         //Generate xid to associate it with the request
503         Long xid = this.getSessionContext().getNextXid();
504
505         LOG.debug("Prepare statistics request for all the groups - Transaction id - {}",xid);
506
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));
513
514         // Create multipart request body for fetch all the group stats
515         MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
516         mprGroupBuild.setGroupId(BinContent.intToUnsignedLong(Group.OFPGALL.getIntValue()));
517
518         //Set request body to main multipart request
519         mprInput.setMultipartRequestBody(mprGroupBuild.build());
520
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);
524
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);
530
531         Collection<RpcError> errors = Collections.emptyList();
532         RpcResult<GetAllGroupStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
533         return Futures.immediateFuture(rpcResult);
534
535     }
536
537     @Override
538     public Future<RpcResult<GetGroupDescriptionOutput>> getGroupDescription(GetGroupDescriptionInput input) {
539
540         //Generate xid to associate it with the request
541         Long xid = this.getSessionContext().getNextXid();
542
543         LOG.debug("Prepare group description statistics request - Transaction id - {}",xid);
544
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));
551
552         // Create multipart request body for fetch all the group description stats
553         MultipartRequestGroupDescBuilder mprGroupDescBuild = new MultipartRequestGroupDescBuilder();
554
555         //Set request body to main multipart request
556         mprInput.setMultipartRequestBody(mprGroupDescBuild.build());
557
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);
561
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);
567
568         Collection<RpcError> errors = Collections.emptyList();
569         RpcResult<GetGroupDescriptionOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
570         return Futures.immediateFuture(rpcResult);
571
572     }
573
574     @Override
575     public Future<RpcResult<GetGroupFeaturesOutput>> getGroupFeatures(GetGroupFeaturesInput input) {
576
577         //Generate xid to associate it with the request
578         Long xid = this.getSessionContext().getNextXid();
579
580         LOG.debug("Prepare group features statistics request - Transaction id - {}",xid);
581
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));
588
589         // Create multipart request body for fetch all the group description stats
590         MultipartRequestGroupFeaturesBuilder mprGroupFeaturesBuild = new MultipartRequestGroupFeaturesBuilder();
591
592         //Set request body to main multipart request
593         mprInput.setMultipartRequestBody(mprGroupFeaturesBuild.build());
594
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);
598
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));
603
604         Collection<RpcError> errors = Collections.emptyList();
605         RpcResult<GetGroupFeaturesOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
606         return Futures.immediateFuture(rpcResult);
607     }
608
609     @Override
610     public Future<RpcResult<GetGroupStatisticsOutput>> getGroupStatistics(GetGroupStatisticsInput input) {
611
612         //Generate xid to associate it with the request
613         Long xid = this.getSessionContext().getNextXid();
614
615         LOG.debug("Prepare statistics request for node {} group ({}) - Transaction id - {}",input.getNode(),input.getGroupId(),xid);
616
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));
623
624         // Create multipart request body for fetch all the group stats
625         MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
626         mprGroupBuild.setGroupId(input.getGroupId().getValue());
627
628         //Set request body to main multipart request
629         mprInput.setMultipartRequestBody(mprGroupBuild.build());
630
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);
634
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);
640
641         Collection<RpcError> errors = Collections.emptyList();
642         RpcResult<GetGroupStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
643         return Futures.immediateFuture(rpcResult);
644     }
645
646     @Override
647     public Future<RpcResult<GetAllMeterConfigStatisticsOutput>> getAllMeterConfigStatistics(
648             GetAllMeterConfigStatisticsInput input) {
649
650         //Generate xid to associate it with the request
651         Long xid = this.getSessionContext().getNextXid();
652
653         LOG.debug("Prepare config request for all the meters - Transaction id - {}",xid);
654
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));
661
662         // Create multipart request body for fetch all the meter stats
663         MultipartRequestMeterConfigBuilder mprMeterConfigBuild = new MultipartRequestMeterConfigBuilder();
664         mprMeterConfigBuild.setMeterId(BinContent.intToUnsignedLong(Meter.OFPMALL.getIntValue()));
665
666         //Set request body to main multipart request
667         mprInput.setMultipartRequestBody(mprMeterConfigBuild.build());
668
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);
672
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);
678
679         Collection<RpcError> errors = Collections.emptyList();
680         RpcResult<GetAllMeterConfigStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
681         return Futures.immediateFuture(rpcResult);
682     }
683
684     @Override
685     public Future<RpcResult<GetAllMeterStatisticsOutput>> getAllMeterStatistics(GetAllMeterStatisticsInput input) {
686
687         //Generate xid to associate it with the request
688         Long xid = this.getSessionContext().getNextXid();
689
690         LOG.debug("Prepare statistics request for all the meters - Transaction id - {}",xid);
691
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));
698
699         // Create multipart request body for fetch all the meter stats
700         MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
701         mprMeterBuild.setMeterId(BinContent.intToUnsignedLong(Meter.OFPMALL.getIntValue()));
702
703         //Set request body to main multipart request
704         mprInput.setMultipartRequestBody(mprMeterBuild.build());
705
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);
709
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);
715
716         Collection<RpcError> errors = Collections.emptyList();
717         RpcResult<GetAllMeterStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
718         return Futures.immediateFuture(rpcResult);
719     }
720
721     @Override
722     public Future<RpcResult<GetMeterFeaturesOutput>> getMeterFeatures(GetMeterFeaturesInput input) {
723
724         //Generate xid to associate it with the request
725         Long xid = this.getSessionContext().getNextXid();
726
727         LOG.debug("Prepare features statistics request for all the meters - Transaction id - {}",xid);
728
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));
735
736         // Create multipart request body for fetch all the group description stats
737         MultipartRequestMeterFeaturesBuilder mprMeterFeaturesBuild = new MultipartRequestMeterFeaturesBuilder();
738
739         //Set request body to main multipart request
740         mprInput.setMultipartRequestBody(mprMeterFeaturesBuild.build());
741
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);
745
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));
750
751         Collection<RpcError> errors = Collections.emptyList();
752         RpcResult<GetMeterFeaturesOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
753         return Futures.immediateFuture(rpcResult);
754     }
755
756     @Override
757     public Future<RpcResult<GetMeterStatisticsOutput>> getMeterStatistics(GetMeterStatisticsInput input) {
758         //Generate xid to associate it with the request
759         Long xid = this.getSessionContext().getNextXid();
760
761         LOG.debug("Preprae statistics request for Meter ({}) - Transaction id - {}",input.getMeterId().getValue(),xid);
762
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));
769
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());
774
775         //Set request body to main multipart request
776         mprInput.setMultipartRequestBody(mprMeterBuild.build());
777
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);
781
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);
787
788         Collection<RpcError> errors = Collections.emptyList();
789         RpcResult<GetMeterStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
790         return Futures.immediateFuture(rpcResult);
791     }
792
793     private TransactionId generateTransactionId(Long xid){
794         String stringXid =xid.toString();
795         BigInteger bigIntXid = new BigInteger( stringXid );
796         return new TransactionId(bigIntXid);
797
798     }
799
800         @Override
801         public Future<RpcResult<GetPortOutput>> getPort() {
802                 // TODO Auto-generated method stub
803                 return null;
804         }
805
806         @Override
807         public Future<RpcResult<UpdatePortOutput>> updatePort(UpdatePortInput input) {
808                 PortModInput ofPortModInput = null ;
809                 RpcResult<UpdatePortOutput> rpcResultFromOFLib = null ;
810                 
811                                 
812                 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so  
813         // the request can be routed through any connection to the switch
814         
815         SwitchConnectionDistinguisher cookie = null ;
816         
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() ;
820                 
821                 // Get the Xid. The same Xid has to be sent in all the RPCs
822                 Long Xid = sessionContext.getNextXid();
823                 
824                 for( Port inputPort : inputPorts) {
825                    
826                         // Convert the UpdateGroupInput to GroupModInput 
827                                 ofPortModInput = PortConvertor.toPortModInput(inputPort, version) ;
828                                                         
829                                 // Insert the Xid ( transaction Id) before calling the RPC on the OFLibrary
830                         
831                         PortModInputBuilder mdInput = new PortModInputBuilder();
832                         mdInput.setXid(Xid);
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()) ;
842                         
843                         LOG.debug("Calling the PortMod RPC method on MessageDispatchService");
844                         Future<RpcResult<UpdatePortOutput>> resultFromOFLib = messageService.portMod(ofPortModInput, cookie) ;
845                                         
846                         try { 
847                                 rpcResultFromOFLib = resultFromOFLib.get();
848                         } catch( Exception ex ) {
849                                 LOG.error( " Error while getting result for updatePort RPC" + ex.getMessage());
850                         }
851                         
852                         // The Future response value for all the RPCs except the last one is ignored
853                         
854                 }
855                         
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() ;
859                         
860                         UpdatePortOutputBuilder updatePortOutput = new UpdatePortOutputBuilder() ;
861                         updatePortOutput.setTransactionId(updatePortOutputOFLib.getTransactionId()) ;
862                         UpdatePortOutput result = updatePortOutput.build();
863                         
864                         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
865                         RpcResult<UpdatePortOutput> rpcResult = Rpcs.getRpcResult(true, result, errors); 
866                         
867                         LOG.debug("Returning the Update Group RPC result to MD-SAL");
868                         return Futures.immediateFuture(rpcResult);
869         
870         }
871         @Override
872         public Future<RpcResult<UpdateTableOutput>> updateTable(
873                         UpdateTableInput input) {
874
875                 // Get the Xid. The same Xid has to be sent in all the Multipart requests
876         Long xid = this.getSessionContext().getNextXid();
877
878         LOG.debug("Prepare the Multipart Table Mod requests for Transaction Id {} ",xid);
879
880         // Create multipart request header
881         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
882         mprInput.setType(MultipartType.OFPMPTABLEFEATURES);
883         mprInput.setVersion((short)0x04);
884         mprInput.setXid(xid);
885
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();
889
890         MultipartRequestTableFeaturesBuilder tableFeaturesRequest = new MultipartRequestTableFeaturesBuilder();
891
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
895
896         List<TableFeatures> tmpOfTableFeatureList = null ;
897         String tableFeatureListCount = System.getProperty( "of.tableFeaturesCountPerMultipart", "5") ;
898         int noOfEntriesInMPR = Integer.parseInt(tableFeatureListCount) ;
899
900         int index = 0 ;
901         while(totalNoOfTableFeatureEntry-index > 0 ) {
902                 if( (totalNoOfTableFeatureEntry-index) > noOfEntriesInMPR ) {
903                         mprInput.setFlags(new MultipartRequestFlags(true));
904                         tmpOfTableFeatureList = ofTableFeatureList.subList(index, index + noOfEntriesInMPR);
905                 }
906                 else {
907                         // Last multipart request
908                         mprInput.setFlags(new MultipartRequestFlags(false));
909                         tmpOfTableFeatureList = ofTableFeatureList.subList(index, totalNoOfTableFeatureEntry );
910                 }
911
912         tableFeaturesRequest.setTableFeatures(tmpOfTableFeatureList) ;
913         //Set request body to main multipart request
914         mprInput.setMultipartRequestBody(tableFeaturesRequest.build());
915
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
921         }
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));
928
929         Collection<RpcError> errors = Collections.emptyList();
930         RpcResult<UpdateTableOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
931         return Futures.immediateFuture(rpcResult);
932
933         }
934 }