Modified as per gerrit 3314
[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.GroupId;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Meter;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInputBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInput;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInputBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.Match;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.MatchBuilder;
99 //import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features.TableFeatures;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupDescBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroupFeaturesBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterConfigBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterFeaturesBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeaturesBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features.TableFeatures;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.GetPortOutput;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.service.rev131107.UpdatePortOutputBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableInput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutput;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.UpdateTableOutputBuilder;
116 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
117 import org.opendaylight.yangtools.yang.common.RpcError;
118 import org.opendaylight.yangtools.yang.common.RpcResult;
119 import org.slf4j.Logger;
120
121 import com.google.common.util.concurrent.Futures;
122
123 /**
124  * RPC implementation of MD-switch
125  */
126 public class ModelDrivenSwitchImpl extends AbstractModelDrivenSwitch {
127
128     private static final Logger LOG = org.slf4j.LoggerFactory
129             .getLogger(ModelDrivenSwitchImpl.class);
130     private final NodeId nodeId;
131     private final IMessageDispatchService messageService ;
132     private short version = 0;
133
134     protected ModelDrivenSwitchImpl(NodeId nodeId,
135             InstanceIdentifier<Node> identifier, SessionContext context) {
136         super(identifier, context);
137         this.nodeId = nodeId;
138         messageService = sessionContext.getMessageDispatchService() ;
139         version = context.getPrimaryConductor().getVersion();
140     }
141
142     @Override
143     public Future<RpcResult<AddFlowOutput>> addFlow(AddFlowInput input) {
144         // Convert the AddFlowInput to FlowModInput
145         FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input, version);
146
147         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
148         // the request can be routed through any connection to the switch
149
150         SwitchConnectionDistinguisher cookie = null ;
151
152         LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
153         Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
154
155         RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
156
157         try {
158                 rpcResultFromOFLib = resultFromOFLib.get();
159         } catch( Exception ex ) {
160                 LOG.error( " Error while getting result for AddFlow RPC" + ex.getMessage());
161         }
162
163         UpdateFlowOutput updateFlowOutput = rpcResultFromOFLib.getResult() ;
164
165         AddFlowOutputBuilder addFlowOutput = new AddFlowOutputBuilder() ;
166         addFlowOutput.setTransactionId(updateFlowOutput.getTransactionId()) ;
167         AddFlowOutput result = addFlowOutput.build();
168
169         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
170         RpcResult<AddFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
171
172         LOG.debug("Returning the Add Flow RPC result to MD-SAL");
173         return Futures.immediateFuture(rpcResult);
174     }
175
176     @Override
177     public Future<RpcResult<AddGroupOutput>> addGroup(AddGroupInput input) {
178         // Convert the AddGroupInput to GroupModInput
179         GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input, version);
180
181
182         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
183         // the request can be routed through any connection to the switch
184
185         SwitchConnectionDistinguisher cookie = null ;
186
187         LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
188         Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
189
190         RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
191
192         try {
193                 rpcResultFromOFLib = resultFromOFLib.get();
194         } catch( Exception ex ) {
195                 LOG.error( " Error while getting result for AddGroup RPC" + ex.getMessage());
196         }
197
198         UpdateGroupOutput updateGroupOutput = rpcResultFromOFLib.getResult() ;
199
200         AddGroupOutputBuilder addGroupOutput = new AddGroupOutputBuilder() ;
201         addGroupOutput.setTransactionId(updateGroupOutput.getTransactionId()) ;
202         AddGroupOutput result = addGroupOutput.build();
203
204         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
205         RpcResult<AddGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
206
207         LOG.debug("Returning the Add Group RPC result to MD-SAL");
208         return Futures.immediateFuture(rpcResult);
209     }
210
211     @Override
212     public Future<RpcResult<AddMeterOutput>> addMeter(AddMeterInput input) {
213         // Convert the AddMeterInput to MeterModInput
214         MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input, version);
215
216
217         // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
218         // the request can be routed through any connection to the switch
219
220         SwitchConnectionDistinguisher cookie = null ;
221
222         LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
223         Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
224
225         RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
226
227         try {
228                 rpcResultFromOFLib = resultFromOFLib.get();
229         } catch( Exception ex ) {
230                 LOG.error( " Error while getting result for AddMeter RPC" + ex.getMessage());
231         }
232
233         UpdateMeterOutput updateMeterOutput = rpcResultFromOFLib.getResult() ;
234
235         AddMeterOutputBuilder addMeterOutput = new AddMeterOutputBuilder() ;
236         addMeterOutput.setTransactionId(updateMeterOutput.getTransactionId()) ;
237         AddMeterOutput result = addMeterOutput.build();
238
239         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
240         RpcResult<AddMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
241
242         LOG.debug("Returning the Add Meter RPC result to MD-SAL");
243         return Futures.immediateFuture(rpcResult);
244     }
245
246     @Override
247     public Future<RpcResult<RemoveFlowOutput>> removeFlow(RemoveFlowInput input) {
248         // Convert the RemoveFlowInput to FlowModInput
249         FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input, version);
250
251
252         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
253         // the request can be routed through any connection to the switch
254
255         SwitchConnectionDistinguisher cookie = null ;
256
257         LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
258         Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
259
260         RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
261
262         try {
263                 rpcResultFromOFLib = resultFromOFLib.get();
264         } catch( Exception ex ) {
265                 LOG.error( " Error while getting result for remove Flow RPC" + ex.getMessage());
266         }
267
268         UpdateFlowOutput updateFlowOutput = rpcResultFromOFLib.getResult() ;
269
270         RemoveFlowOutputBuilder removeFlowOutput = new RemoveFlowOutputBuilder() ;
271         removeFlowOutput.setTransactionId(updateFlowOutput.getTransactionId()) ;
272         RemoveFlowOutput result = removeFlowOutput.build();
273
274         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
275         RpcResult<RemoveFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
276
277         LOG.debug("Returning the Remove Flow RPC result to MD-SAL");
278         return Futures.immediateFuture(rpcResult);
279     }
280
281     @Override
282     public Future<RpcResult<RemoveGroupOutput>> removeGroup(
283             RemoveGroupInput input) {
284         // Convert the RemoveGroupInput to GroupModInput
285         GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input, version);
286
287
288         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
289         // the request can be routed through any connection to the switch
290
291         SwitchConnectionDistinguisher cookie = null ;
292
293         LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
294         Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
295
296         RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
297
298         try {
299                 rpcResultFromOFLib = resultFromOFLib.get();
300         } catch( Exception ex ) {
301                 LOG.error( " Error while getting result for RemoveGroup RPC" + ex.getMessage());
302         }
303
304         UpdateGroupOutput updateGroupOutput = rpcResultFromOFLib.getResult() ;
305
306         RemoveGroupOutputBuilder removeGroupOutput = new RemoveGroupOutputBuilder() ;
307         removeGroupOutput.setTransactionId(updateGroupOutput.getTransactionId()) ;
308         RemoveGroupOutput result = removeGroupOutput.build();
309
310         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
311         RpcResult<RemoveGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
312
313         LOG.debug("Returning the Remove Group RPC result to MD-SAL");
314         return Futures.immediateFuture(rpcResult);
315     }
316
317     @Override
318     public Future<RpcResult<RemoveMeterOutput>> removeMeter(
319             RemoveMeterInput input) {
320         // Convert the RemoveMeterInput to MeterModInput
321         MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input, version);
322
323
324         // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
325         // the request can be routed through any connection to the switch
326
327         SwitchConnectionDistinguisher cookie = null ;
328
329         LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
330         Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
331
332         RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
333
334         try {
335                 rpcResultFromOFLib = resultFromOFLib.get();
336         } catch( Exception ex ) {
337                 LOG.error( " Error while getting result for RemoveMeter RPC" + ex.getMessage());
338         }
339
340         UpdateMeterOutput updatemeterOutput = rpcResultFromOFLib.getResult() ;
341
342         RemoveMeterOutputBuilder removeMeterOutput = new RemoveMeterOutputBuilder() ;
343         removeMeterOutput.setTransactionId(updatemeterOutput.getTransactionId()) ;
344         RemoveMeterOutput result = removeMeterOutput.build();
345
346         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
347         RpcResult<RemoveMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
348
349         LOG.debug("Returning the Remove Meter RPC result to MD-SAL");
350         return Futures.immediateFuture(rpcResult);
351     }
352
353     @Override
354     public Future<RpcResult<Void>> transmitPacket(TransmitPacketInput input) {
355         // TODO Auto-generated method stub
356         return null;
357     }
358
359     private FlowModInputBuilder toFlowModInputBuilder(Flow source) {
360         FlowModInputBuilder target = new FlowModInputBuilder();
361         target.setCookie(source.getCookie());
362         target.setIdleTimeout(source.getIdleTimeout());
363         target.setHardTimeout(source.getHardTimeout());
364         target.setMatch(toMatch(source.getMatch()));
365
366         return target;
367     }
368
369     private Match toMatch(
370             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match match) {
371         MatchBuilder target = new MatchBuilder();
372
373         target.setMatchEntries(toMatchEntries(match));
374
375         return null;
376     }
377
378     private List<MatchEntries> toMatchEntries(
379             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match match) {
380         List<MatchEntries> entries = new ArrayList<>();
381
382         return null;
383     }
384
385     @Override
386     public Future<RpcResult<UpdateFlowOutput>> updateFlow(UpdateFlowInput input) {
387         // Convert the UpdateFlowInput to FlowModInput
388         FlowModInput ofFlowModInput = FlowConvertor.toFlowModInput(input.getUpdatedFlow(), version);
389
390         // Call the RPC method on MessageDispatchService
391
392         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
393         // the request can be routed through any connection to the switch
394
395         SwitchConnectionDistinguisher cookie = null ;
396
397         LOG.debug("Calling the FlowMod RPC method on MessageDispatchService");
398         Future<RpcResult<UpdateFlowOutput>> resultFromOFLib = messageService.flowMod(ofFlowModInput, cookie) ;
399
400         RpcResult<UpdateFlowOutput> rpcResultFromOFLib = null ;
401
402         try {
403                 rpcResultFromOFLib = resultFromOFLib.get();
404         } catch( Exception ex ) {
405                 LOG.error( " Error while getting result for UpdateFlow RPC" + ex.getMessage());
406         }
407
408         UpdateFlowOutput updateFlowOutputOFLib = rpcResultFromOFLib.getResult() ;
409
410         UpdateFlowOutputBuilder updateFlowOutput = new UpdateFlowOutputBuilder() ;
411         updateFlowOutput.setTransactionId(updateFlowOutputOFLib.getTransactionId()) ;
412         UpdateFlowOutput result = updateFlowOutput.build();
413
414         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
415         RpcResult<UpdateFlowOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
416
417         LOG.debug("Returning the Update Flow RPC result to MD-SAL");
418         return Futures.immediateFuture(rpcResult);
419     }
420
421     @Override
422     public Future<RpcResult<UpdateGroupOutput>> updateGroup(
423             UpdateGroupInput input) {
424         // Convert the UpdateGroupInput to GroupModInput
425         GroupModInput ofGroupModInput = GroupConvertor.toGroupModInput(input.getUpdatedGroup(), version);
426
427
428         // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so
429         // the request can be routed through any connection to the switch
430
431         SwitchConnectionDistinguisher cookie = null ;
432
433         LOG.debug("Calling the GroupMod RPC method on MessageDispatchService");
434         Future<RpcResult<UpdateGroupOutput>> resultFromOFLib = messageService.groupMod(ofGroupModInput, cookie) ;
435
436         RpcResult<UpdateGroupOutput> rpcResultFromOFLib = null ;
437
438         try {
439                 rpcResultFromOFLib = resultFromOFLib.get();
440         } catch( Exception ex ) {
441                 LOG.error( " Error while getting result for updateGroup RPC" + ex.getMessage());
442         }
443
444         UpdateGroupOutput updateGroupOutputOFLib = rpcResultFromOFLib.getResult() ;
445
446         UpdateGroupOutputBuilder updateGroupOutput = new UpdateGroupOutputBuilder() ;
447         updateGroupOutput.setTransactionId(updateGroupOutputOFLib.getTransactionId()) ;
448         UpdateGroupOutput result = updateGroupOutput.build();
449
450         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
451         RpcResult<UpdateGroupOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
452
453         LOG.debug("Returning the Update Group RPC result to MD-SAL");
454         return Futures.immediateFuture(rpcResult);
455     }
456
457     @Override
458     public Future<RpcResult<UpdateMeterOutput>> updateMeter(
459             UpdateMeterInput input) {
460         // Convert the UpdateMeterInput to MeterModInput
461         MeterModInput ofMeterModInput = MeterConvertor.toMeterModInput(input.getUpdatedMeter(), version);
462
463
464         // For Meter provisioning, the SwitchConnectionDistinguisher is set to null so
465         // the request can be routed through any connection to the switch
466
467         SwitchConnectionDistinguisher cookie = null ;
468
469         LOG.debug("Calling the MeterMod RPC method on MessageDispatchService");
470         Future<RpcResult<UpdateMeterOutput>> resultFromOFLib = messageService.meterMod(ofMeterModInput, cookie) ;
471
472         RpcResult<UpdateMeterOutput> rpcResultFromOFLib = null ;
473
474         try {
475                 rpcResultFromOFLib = resultFromOFLib.get();
476         } catch( Exception ex ) {
477                 LOG.error( " Error while getting result for UpdateMeter RPC" + ex.getMessage());
478         }
479
480         UpdateMeterOutput updateMeterOutputFromOFLib = rpcResultFromOFLib.getResult() ;
481
482         UpdateMeterOutputBuilder updateMeterOutput = new UpdateMeterOutputBuilder() ;
483         updateMeterOutput.setTransactionId(updateMeterOutputFromOFLib.getTransactionId()) ;
484         UpdateMeterOutput result = updateMeterOutput.build();
485
486         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
487         RpcResult<UpdateMeterOutput> rpcResult = Rpcs.getRpcResult(true, result, errors);
488
489         LOG.debug("Returning the Update Meter RPC result to MD-SAL");
490         return Futures.immediateFuture(rpcResult);
491     }
492
493     @Override
494     public NodeId getNodeId() {
495         return nodeId;
496     }
497
498     /*
499      * Methods for requesting statistics from switch
500      */
501     @Override
502     public Future<RpcResult<GetAllGroupStatisticsOutput>> getAllGroupStatistics(GetAllGroupStatisticsInput input) {
503
504         //Generate xid to associate it with the request
505         Long xid = this.getSessionContext().getNextXid();
506
507         LOG.debug("Prepare statistics request for all the groups - Transaction id - {}",xid);
508
509         // Create multipart request header
510         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
511         mprInput.setType(MultipartType.OFPMPGROUP);
512         mprInput.setVersion(version);
513         mprInput.setXid(xid);
514         mprInput.setFlags(new MultipartRequestFlags(false));
515
516         // Create multipart request body for fetch all the group stats
517         MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
518         mprGroupBuild.setGroupId(new GroupId(BinContent.intToUnsignedLong(Group.OFPGALL.getIntValue())));
519
520         //Set request body to main multipart request
521         mprInput.setMultipartRequestBody(mprGroupBuild.build());
522
523         //Send the request, no cookies associated, use any connection
524         LOG.debug("Send group statistics request to the switch :{}",mprGroupBuild);
525         this.messageService.multipartRequest(mprInput.build(), null);
526
527         // Prepare rpc return output. Set xid and send it back.
528         LOG.debug("Return results and transaction id back to caller");
529         GetAllGroupStatisticsOutputBuilder output = new GetAllGroupStatisticsOutputBuilder();
530         output.setTransactionId(generateTransactionId(xid));
531         output.setGroupStats(null);
532
533         Collection<RpcError> errors = Collections.emptyList();
534         RpcResult<GetAllGroupStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
535         return Futures.immediateFuture(rpcResult);
536
537     }
538
539     @Override
540     public Future<RpcResult<GetGroupDescriptionOutput>> getGroupDescription(GetGroupDescriptionInput input) {
541
542         //Generate xid to associate it with the request
543         Long xid = this.getSessionContext().getNextXid();
544
545         LOG.debug("Prepare group description statistics request - Transaction id - {}",xid);
546
547         // Create multipart request header
548         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
549         mprInput.setType(MultipartType.OFPMPGROUPDESC);
550         mprInput.setVersion(version);
551         mprInput.setXid(xid);
552         mprInput.setFlags(new MultipartRequestFlags(false));
553
554         // Create multipart request body for fetch all the group description stats
555         MultipartRequestGroupDescBuilder mprGroupDescBuild = new MultipartRequestGroupDescBuilder();
556
557         //Set request body to main multipart request
558         mprInput.setMultipartRequestBody(mprGroupDescBuild.build());
559
560         //Send the request, no cookies associated, use any connection
561         LOG.debug("Send group desciption statistics request to switch : {}",mprGroupDescBuild);
562         this.messageService.multipartRequest(mprInput.build(), null);
563
564         // Prepare rpc return output. Set xid and send it back.
565         LOG.debug("Return results and transaction id back to caller");
566         GetGroupDescriptionOutputBuilder output = new GetGroupDescriptionOutputBuilder();
567         output.setTransactionId(generateTransactionId(xid));
568         output.setGroupDescStats(null);
569
570         Collection<RpcError> errors = Collections.emptyList();
571         RpcResult<GetGroupDescriptionOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
572         return Futures.immediateFuture(rpcResult);
573
574     }
575
576     @Override
577     public Future<RpcResult<GetGroupFeaturesOutput>> getGroupFeatures(GetGroupFeaturesInput input) {
578
579         //Generate xid to associate it with the request
580         Long xid = this.getSessionContext().getNextXid();
581
582         LOG.debug("Prepare group features statistics request - Transaction id - {}",xid);
583
584         // Create multipart request header
585         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
586         mprInput.setType(MultipartType.OFPMPGROUPFEATURES);
587         mprInput.setVersion(version);
588         mprInput.setXid(xid);
589         mprInput.setFlags(new MultipartRequestFlags(false));
590
591         // Create multipart request body for fetch all the group description stats
592         MultipartRequestGroupFeaturesBuilder mprGroupFeaturesBuild = new MultipartRequestGroupFeaturesBuilder();
593
594         //Set request body to main multipart request
595         mprInput.setMultipartRequestBody(mprGroupFeaturesBuild.build());
596
597         //Send the request, no cookies associated, use any connection
598         LOG.debug("Send group features statistics request :{}",mprGroupFeaturesBuild);
599         this.messageService.multipartRequest(mprInput.build(), null);
600
601         // Prepare rpc return output. Set xid and send it back.
602         LOG.debug("Return results and transaction id back to caller");
603         GetGroupFeaturesOutputBuilder output = new GetGroupFeaturesOutputBuilder();
604         output.setTransactionId(generateTransactionId(xid));
605
606         Collection<RpcError> errors = Collections.emptyList();
607         RpcResult<GetGroupFeaturesOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
608         return Futures.immediateFuture(rpcResult);
609     }
610
611     @Override
612     public Future<RpcResult<GetGroupStatisticsOutput>> getGroupStatistics(GetGroupStatisticsInput input) {
613
614         //Generate xid to associate it with the request
615         Long xid = this.getSessionContext().getNextXid();
616
617         LOG.debug("Prepare statistics request for node {} group ({}) - Transaction id - {}",input.getNode(),input.getGroupId(),xid);
618
619         // Create multipart request header
620         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
621         mprInput.setType(MultipartType.OFPMPGROUP);
622         mprInput.setVersion(version);
623         mprInput.setXid(xid);
624         mprInput.setFlags(new MultipartRequestFlags(false));
625
626         // Create multipart request body for fetch all the group stats
627         MultipartRequestGroupBuilder mprGroupBuild = new MultipartRequestGroupBuilder();
628         mprGroupBuild.setGroupId(new GroupId(input.getGroupId().getValue()));
629
630         //Set request body to main multipart request
631         mprInput.setMultipartRequestBody(mprGroupBuild.build());
632
633         //Send the request, no cookies associated, use any connection
634         LOG.debug("Send group statistics request :{}",mprGroupBuild);
635         this.messageService.multipartRequest(mprInput.build(), null);
636
637         // Prepare rpc return output. Set xid and send it back.
638         LOG.debug("Return results and transaction id back to caller");
639         GetGroupStatisticsOutputBuilder output = new GetGroupStatisticsOutputBuilder();
640         output.setTransactionId(generateTransactionId(xid));
641         output.setGroupStats(null);
642
643         Collection<RpcError> errors = Collections.emptyList();
644         RpcResult<GetGroupStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
645         return Futures.immediateFuture(rpcResult);
646     }
647
648     @Override
649     public Future<RpcResult<GetAllMeterConfigStatisticsOutput>> getAllMeterConfigStatistics(
650             GetAllMeterConfigStatisticsInput input) {
651
652         //Generate xid to associate it with the request
653         Long xid = this.getSessionContext().getNextXid();
654
655         LOG.debug("Prepare config request for all the meters - Transaction id - {}",xid);
656
657         // Create multipart request header
658         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
659         mprInput.setType(MultipartType.OFPMPMETERCONFIG);
660         mprInput.setVersion(version);
661         mprInput.setXid(xid);
662         mprInput.setFlags(new MultipartRequestFlags(false));
663
664         // Create multipart request body for fetch all the meter stats
665         MultipartRequestMeterConfigBuilder mprMeterConfigBuild = new MultipartRequestMeterConfigBuilder();
666         mprMeterConfigBuild.setMeterId(new MeterId(BinContent.intToUnsignedLong(Meter.OFPMALL.getIntValue())));
667
668         //Set request body to main multipart request
669         mprInput.setMultipartRequestBody(mprMeterConfigBuild.build());
670
671         //Send the request, no cookies associated, use any connection
672         LOG.debug("Send meter statistics request :{}",mprMeterConfigBuild);
673         this.messageService.multipartRequest(mprInput.build(), null);
674
675         // Prepare rpc return output. Set xid and send it back.
676         LOG.debug("Return results and transaction id back to caller");
677         GetAllMeterConfigStatisticsOutputBuilder output = new GetAllMeterConfigStatisticsOutputBuilder();
678         output.setTransactionId(generateTransactionId(xid));
679         output.setMeterConfigStats(null);
680
681         Collection<RpcError> errors = Collections.emptyList();
682         RpcResult<GetAllMeterConfigStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
683         return Futures.immediateFuture(rpcResult);
684     }
685
686     @Override
687     public Future<RpcResult<GetAllMeterStatisticsOutput>> getAllMeterStatistics(GetAllMeterStatisticsInput input) {
688
689         //Generate xid to associate it with the request
690         Long xid = this.getSessionContext().getNextXid();
691
692         LOG.debug("Prepare statistics request for all the meters - Transaction id - {}",xid);
693
694         // Create multipart request header
695         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
696         mprInput.setType(MultipartType.OFPMPMETER);
697         mprInput.setVersion(version);
698         mprInput.setXid(xid);
699         mprInput.setFlags(new MultipartRequestFlags(false));
700
701         // Create multipart request body for fetch all the meter stats
702         MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
703         mprMeterBuild.setMeterId(new MeterId(BinContent.intToUnsignedLong(Meter.OFPMALL.getIntValue())));
704
705         //Set request body to main multipart request
706         mprInput.setMultipartRequestBody(mprMeterBuild.build());
707
708         //Send the request, no cookies associated, use any connection
709         LOG.debug("Send meter statistics request :{}",mprMeterBuild);
710         this.messageService.multipartRequest(mprInput.build(), null);
711
712         // Prepare rpc return output. Set xid and send it back.
713         LOG.debug("Return results and transaction id back to caller");
714         GetAllMeterStatisticsOutputBuilder output = new GetAllMeterStatisticsOutputBuilder();
715         output.setTransactionId(generateTransactionId(xid));
716         output.setMeterStats(null);
717
718         Collection<RpcError> errors = Collections.emptyList();
719         RpcResult<GetAllMeterStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
720         return Futures.immediateFuture(rpcResult);
721     }
722
723     @Override
724     public Future<RpcResult<GetMeterFeaturesOutput>> getMeterFeatures(GetMeterFeaturesInput input) {
725
726         //Generate xid to associate it with the request
727         Long xid = this.getSessionContext().getNextXid();
728
729         LOG.debug("Prepare features statistics request for all the meters - Transaction id - {}",xid);
730
731         // Create multipart request header
732         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
733         mprInput.setType(MultipartType.OFPMPMETERFEATURES);
734         mprInput.setVersion(version);
735         mprInput.setXid(xid);
736         mprInput.setFlags(new MultipartRequestFlags(false));
737
738         // Create multipart request body for fetch all the group description stats
739         MultipartRequestMeterFeaturesBuilder mprMeterFeaturesBuild = new MultipartRequestMeterFeaturesBuilder();
740
741         //Set request body to main multipart request
742         mprInput.setMultipartRequestBody(mprMeterFeaturesBuild.build());
743
744         //Send the request, no cookies associated, use any connection
745         LOG.debug("Send meter features statistics request :{}",mprMeterFeaturesBuild);
746         this.messageService.multipartRequest(mprInput.build(), null);
747
748         // Prepare rpc return output. Set xid and send it back.
749         LOG.debug("Return results and transaction id back to caller");
750         GetMeterFeaturesOutputBuilder output = new GetMeterFeaturesOutputBuilder();
751         output.setTransactionId(generateTransactionId(xid));
752
753         Collection<RpcError> errors = Collections.emptyList();
754         RpcResult<GetMeterFeaturesOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
755         return Futures.immediateFuture(rpcResult);
756     }
757
758     @Override
759     public Future<RpcResult<GetMeterStatisticsOutput>> getMeterStatistics(GetMeterStatisticsInput input) {
760         //Generate xid to associate it with the request
761         Long xid = this.getSessionContext().getNextXid();
762
763         LOG.debug("Preprae statistics request for Meter ({}) - Transaction id - {}",input.getMeterId().getValue(),xid);
764
765         // Create multipart request header
766         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
767         mprInput.setType(MultipartType.OFPMPMETER);
768         mprInput.setVersion(version);
769         mprInput.setXid(xid);
770         mprInput.setFlags(new MultipartRequestFlags(false));
771
772         // Create multipart request body for fetch all the meter stats
773         MultipartRequestMeterBuilder mprMeterBuild = new MultipartRequestMeterBuilder();
774         //Select specific meter
775         mprMeterBuild.setMeterId(new MeterId(input.getMeterId().getValue()));
776
777         //Set request body to main multipart request
778         mprInput.setMultipartRequestBody(mprMeterBuild.build());
779
780         //Send the request, no cookies associated, use any connection
781         LOG.debug("Send meter statistics request :{}",mprMeterBuild);
782         this.messageService.multipartRequest(mprInput.build(), null);
783
784         // Prepare rpc return output. Set xid and send it back.
785         LOG.debug("Return results and transaction id back to caller");
786         GetMeterStatisticsOutputBuilder output = new GetMeterStatisticsOutputBuilder();
787         output.setTransactionId(generateTransactionId(xid));
788         output.setMeterStats(null);
789
790         Collection<RpcError> errors = Collections.emptyList();
791         RpcResult<GetMeterStatisticsOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
792         return Futures.immediateFuture(rpcResult);
793     }
794
795     private TransactionId generateTransactionId(Long xid){
796         String stringXid =xid.toString();
797         BigInteger bigIntXid = new BigInteger( stringXid );
798         return new TransactionId(bigIntXid);
799
800     }
801
802         @Override
803         public Future<RpcResult<GetPortOutput>> getPort() {
804                 // TODO Auto-generated method stub
805                 return null;
806         }
807
808         @Override
809         public Future<RpcResult<UpdatePortOutput>> updatePort(UpdatePortInput input) {
810                 PortModInput ofPortModInput = null ;
811                 RpcResult<UpdatePortOutput> rpcResultFromOFLib = null ;
812                 
813                                 
814                 // For Flow provisioning, the SwitchConnectionDistinguisher is set to null so  
815         // the request can be routed through any connection to the switch
816         
817         SwitchConnectionDistinguisher cookie = null ;
818         
819                 // NSF sends a list of port and the ModelDrivenSwitch will 
820         // send one port at a time towards the switch ( mutiple RPCs calls)
821                 List<Port> inputPorts = input.getUpdatedPort().getPort().getPort() ;
822                 
823                 // Get the Xid. The same Xid has to be sent in all the RPCs
824                 Long Xid = sessionContext.getNextXid();
825                 
826                 for( Port inputPort : inputPorts) {
827                    
828                         // Convert the UpdateGroupInput to GroupModInput 
829                                 ofPortModInput = PortConvertor.toPortModInput(inputPort, version) ;
830                                                         
831                                 // Insert the Xid ( transaction Id) before calling the RPC on the OFLibrary
832                         
833                         PortModInputBuilder mdInput = new PortModInputBuilder();
834                         mdInput.setXid(Xid);
835                         mdInput.setVersion(ofPortModInput.getVersion()) ;
836                         mdInput.setPortNo(ofPortModInput.getPortNo()) ;
837                         mdInput.setMaskV10(ofPortModInput.getMaskV10()) ;
838                         mdInput.setMask(ofPortModInput.getMask()) ;
839                         mdInput.setHwAddress(ofPortModInput.getHwAddress());
840                         mdInput.setConfigV10(ofPortModInput.getConfigV10()) ;
841                         mdInput.setConfig(ofPortModInput.getConfig()) ;
842                         mdInput.setAdvertiseV10(ofPortModInput.getAdvertiseV10()) ;
843                         mdInput.setAdvertise(ofPortModInput.getAdvertise()) ;
844                         
845                         LOG.debug("Calling the PortMod RPC method on MessageDispatchService");
846                         Future<RpcResult<UpdatePortOutput>> resultFromOFLib = messageService.portMod(ofPortModInput, cookie) ;
847                                         
848                         try { 
849                                 rpcResultFromOFLib = resultFromOFLib.get();
850                         } catch( Exception ex ) {
851                                 LOG.error( " Error while getting result for updatePort RPC" + ex.getMessage());
852                         }
853                         
854                         // The Future response value for all the RPCs except the last one is ignored
855                         
856                 }
857                         
858                                 //Extract the Xid only from the Future for the last RPC and
859                                 // send it back to the NSF
860                         UpdatePortOutput updatePortOutputOFLib = rpcResultFromOFLib.getResult() ;
861                         
862                         UpdatePortOutputBuilder updatePortOutput = new UpdatePortOutputBuilder() ;
863                         updatePortOutput.setTransactionId(updatePortOutputOFLib.getTransactionId()) ;
864                         UpdatePortOutput result = updatePortOutput.build();
865                         
866                         Collection<RpcError> errors = rpcResultFromOFLib.getErrors() ;
867                         RpcResult<UpdatePortOutput> rpcResult = Rpcs.getRpcResult(true, result, errors); 
868                         
869                         LOG.debug("Returning the Update Group RPC result to MD-SAL");
870                         return Futures.immediateFuture(rpcResult);
871         
872         }
873         @Override
874         public Future<RpcResult<UpdateTableOutput>> updateTable(
875                         UpdateTableInput input) {
876
877                 // Get the Xid. The same Xid has to be sent in all the Multipart requests
878         Long xid = this.getSessionContext().getNextXid();
879
880         LOG.debug("Prepare the Multipart Table Mod requests for Transaction Id {} ",xid);
881
882         // Create multipart request header
883         MultipartRequestInputBuilder mprInput = new MultipartRequestInputBuilder();
884         mprInput.setType(MultipartType.OFPMPTABLEFEATURES);
885         mprInput.setVersion((short)0x04);
886         mprInput.setXid(xid);
887
888         //Convert the list of all MD-SAL table feature object into OF library object
889         List<TableFeatures> ofTableFeatureList = TableFeaturesConvertor.toTableFeaturesRequest(input.getUpdatedTable()) ;
890         int totalNoOfTableFeatureEntry = ofTableFeatureList.size();
891
892         MultipartRequestTableFeaturesBuilder tableFeaturesRequest = new MultipartRequestTableFeaturesBuilder();
893
894          // Slice the multipart request based on the configuration parameter, which is the no. of TableFeatureList element
895         // to be put in one multipart message. Default is 5
896         // This parameter must be set based on switch's Buffer capacity
897
898         List<TableFeatures> tmpOfTableFeatureList = null ;
899         String tableFeatureListCount = System.getProperty( "of.tableFeaturesCountPerMultipart", "5") ;
900         int noOfEntriesInMPR = Integer.parseInt(tableFeatureListCount) ;
901
902         int index = 0 ;
903         while(totalNoOfTableFeatureEntry-index > 0 ) {
904                 if( (totalNoOfTableFeatureEntry-index) > noOfEntriesInMPR ) {
905                         mprInput.setFlags(new MultipartRequestFlags(true));
906                         tmpOfTableFeatureList = ofTableFeatureList.subList(index, index + noOfEntriesInMPR);
907                 }
908                 else {
909                         // Last multipart request
910                         mprInput.setFlags(new MultipartRequestFlags(false));
911                         tmpOfTableFeatureList = ofTableFeatureList.subList(index, totalNoOfTableFeatureEntry );
912                 }
913
914         tableFeaturesRequest.setTableFeatures(tmpOfTableFeatureList) ;
915         //Set request body to main multipart request
916         mprInput.setMultipartRequestBody(tableFeaturesRequest.build());
917
918         //Send the request, no cookies associated, use any connection
919         LOG.debug("Send Table Feature request :{}",tmpOfTableFeatureList);
920         this.messageService.multipartRequest(mprInput.build(), null);
921         index += noOfEntriesInMPR ;
922                 tmpOfTableFeatureList = null ; // To avoid any corrupt data
923         }
924       //Extract the Xid only from the Future for the last RPC and
925                 // send it back to the NSF
926         LOG.debug("Returning the result and transaction id to NSF");
927         LOG.debug("Return results and transaction id back to caller");
928         UpdateTableOutputBuilder output = new UpdateTableOutputBuilder();
929         output.setTransactionId(generateTransactionId(xid));
930
931         Collection<RpcError> errors = Collections.emptyList();
932         RpcResult<UpdateTableOutput> rpcResult = Rpcs.getRpcResult(true, output.build(), errors);
933         return Futures.immediateFuture(rpcResult);
934
935         }
936 }