MD-SAL Statistics Manager - Fetching Group/Meter feature details will be done by...
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / translator / MultipartReplyTranslator.java
1 package org.opendaylight.openflowplugin.openflow.md.core.translator;
2
3 import java.math.BigInteger;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.concurrent.CopyOnWriteArrayList;
7
8 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
9 import org.opendaylight.openflowplugin.openflow.md.core.IMDMessageTranslator;
10 import org.opendaylight.openflowplugin.openflow.md.core.SwitchConnectionDistinguisher;
11 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.GroupStatsResponseConvertor;
12 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.MeterStatsResponseConvertor;
13 import org.opendaylight.openflowplugin.openflow.md.core.session.SessionContext;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.Counter32;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupDescStatsUpdatedBuilder;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupFeaturesUpdatedBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.GroupStatisticsUpdatedBuilder;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.features.GroupFeaturesBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.Chaining;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.ChainingChecks;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupAll;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupCapability;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupFf;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupIndirect;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupSelect;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectLiveness;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.SelectWeight;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterConfigStatsUpdatedBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterFeaturesUpdatedBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.MeterStatisticsUpdatedBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.MeterFeaturesBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBand;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDrop;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandDscpRemark;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBurst;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterCapability;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterKbps;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterPktps;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterStats;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroup;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupDesc;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyGroupFeatures;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeter;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterConfig;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyMeterFeatures;
57 import org.opendaylight.yangtools.yang.binding.DataObject;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 /**
62  * Class converts multipart reply messages to the notification objects defined
63  * by statistics provider (manager ).
64  * 
65  * @author avishnoi@in.ibm.com
66  *
67  */
68 public class MultipartReplyTranslator implements IMDMessageTranslator<OfHeader,  List<DataObject>> {
69
70     protected static final Logger logger = LoggerFactory
71             .getLogger(MultipartReplyTranslator.class);
72     
73     private static GroupStatsResponseConvertor groupStatsConvertor = new GroupStatsResponseConvertor();
74     private static MeterStatsResponseConvertor meterStatsConvertor = new MeterStatsResponseConvertor();
75
76     @Override
77     public  List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sc, OfHeader msg) {
78         
79         List<DataObject> listDataObject = new CopyOnWriteArrayList<DataObject>();
80
81         if(msg instanceof MultipartReplyMessage){
82             MultipartReplyMessage mpReply = (MultipartReplyMessage)msg;
83             NodeId node = this.nodeIdFromDatapathId(sc.getFeatures().getDatapathId());
84             switch (mpReply.getType()){
85             case OFPMPGROUP:{
86                 logger.info("Received group statistics multipart reponse");
87                 GroupStatisticsUpdatedBuilder message = new GroupStatisticsUpdatedBuilder();
88                 message.setId(node);
89                 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
90                 message.setTransactionId(generateTransactionId(mpReply.getXid()));
91                 MultipartReplyGroup replyBody = (MultipartReplyGroup)mpReply.getMultipartReplyBody();
92                 message.setGroupStats(groupStatsConvertor.toSALGroupStatsList(replyBody.getGroupStats()));
93                 logger.debug("Converted group statistics : {}",message.toString());
94                 listDataObject.add(message.build());
95                 return listDataObject;
96             }
97             case OFPMPGROUPDESC:{
98                 logger.info("Received group description statistics multipart reponse");
99                 
100                 GroupDescStatsUpdatedBuilder message = new GroupDescStatsUpdatedBuilder();
101                 message.setId(node);
102                 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
103                 message.setTransactionId(generateTransactionId(mpReply.getXid()));
104                 MultipartReplyGroupDesc replyBody = (MultipartReplyGroupDesc)mpReply.getMultipartReplyBody();
105                 message.setGroupDescStats(groupStatsConvertor.toSALGroupDescStatsList(replyBody.getGroupDesc()));
106                 logger.debug("Converted group statistics : {}",message.toString());
107                 listDataObject.add(message.build());
108                 return listDataObject;
109             }
110             case OFPMPGROUPFEATURES: {
111                 logger.info("Received group features multipart reponse");
112                 GroupFeaturesUpdatedBuilder message = new GroupFeaturesUpdatedBuilder();
113                 message.setId(node);
114                 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
115                 message.setTransactionId(generateTransactionId(mpReply.getXid()));
116                 MultipartReplyGroupFeatures replyBody = (MultipartReplyGroupFeatures)mpReply.getMultipartReplyBody();
117                 List<Class<? extends GroupType>> supportedGroups = 
118                         new ArrayList<Class<? extends GroupType>>();
119                 
120                 if(replyBody.getTypes().isOFPGTALL()){
121                     supportedGroups.add(GroupAll.class);
122                 }
123                 if(replyBody.getTypes().isOFPGTSELECT()){
124                     supportedGroups.add(GroupSelect.class);
125                 }
126                 if(replyBody.getTypes().isOFPGTINDIRECT()){
127                     supportedGroups.add(GroupIndirect.class);
128                 }
129                 if(replyBody.getTypes().isOFPGTFF()){
130                     supportedGroups.add(GroupFf.class);
131                 }
132                 message.setGroupTypesSupported(supportedGroups);
133                 message.setMaxGroups(replyBody.getMaxGroups());
134                 
135                 List<Class<? extends GroupCapability>> supportedCapabilities = 
136                         new ArrayList<Class<? extends GroupCapability>>();
137                 
138                 if(replyBody.getCapabilities().isOFPGFCCHAINING()){
139                     supportedCapabilities.add(Chaining.class);
140                 }
141                 if(replyBody.getCapabilities().isOFPGFCCHAININGCHECKS()){
142                     supportedCapabilities.add(ChainingChecks.class);
143                 }
144                 if(replyBody.getCapabilities().isOFPGFCSELECTLIVENESS()){
145                     supportedCapabilities.add(SelectLiveness.class);
146                 }
147                 if(replyBody.getCapabilities().isOFPGFCSELECTWEIGHT()){
148                     supportedCapabilities.add(SelectWeight.class);
149                 }
150
151                 message.setGroupCapabilitiesSupported(supportedCapabilities);
152                 
153                 message.setActions(getGroupActionsSupportBitmap(replyBody.getActionsBitmap()));
154                 listDataObject.add(message.build());
155
156                 //augmentGroupFeaturesToNode(message);
157                 
158                 //Send update notification to all the listeners 
159                 return listDataObject;
160             }
161             case OFPMPMETER: {
162                 logger.info("Received meter statistics multipart reponse");
163                 MeterStatisticsUpdatedBuilder message = new MeterStatisticsUpdatedBuilder();
164                 message.setId(node);
165                 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
166                 message.setTransactionId(generateTransactionId(mpReply.getXid()));
167                 
168                 MultipartReplyMeter replyBody = (MultipartReplyMeter)mpReply.getMultipartReplyBody();
169                 message.setMeterStats(meterStatsConvertor.toSALMeterStatsList(replyBody.getMeterStats()));
170
171                 listDataObject.add(message.build());
172                 return listDataObject;
173             }
174             case OFPMPMETERCONFIG:{
175                 logger.info("Received meter config statistics multipart reponse");
176                 
177                 MeterConfigStatsUpdatedBuilder message = new MeterConfigStatsUpdatedBuilder();
178                 message.setId(node);
179                 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
180                 message.setTransactionId(generateTransactionId(mpReply.getXid()));
181                 
182                 MultipartReplyMeterConfig replyBody = (MultipartReplyMeterConfig)mpReply.getMultipartReplyBody();
183                 message.setMeterConfigStats(meterStatsConvertor.toSALMeterConfigList(replyBody.getMeterConfig()));
184                 listDataObject.add(message.build());
185                 return listDataObject;
186             }
187             case OFPMPMETERFEATURES:{
188                 logger.info("Received meter features multipart reponse");
189                 //Convert OF message and send it to SAL listener
190                 MeterFeaturesUpdatedBuilder message = new MeterFeaturesUpdatedBuilder();
191                 message.setId(node);
192                 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
193                 message.setTransactionId(generateTransactionId(mpReply.getXid()));
194                 
195                 MultipartReplyMeterFeatures replyBody = (MultipartReplyMeterFeatures)mpReply.getMultipartReplyBody();
196                 message.setMaxBands(replyBody.getMaxBands());
197                 message.setMaxColor(replyBody.getMaxColor());
198                 message.setMaxMeter(new Counter32(replyBody.getMaxMeter()));
199                 
200                 List<Class<? extends MeterCapability>> supportedCapabilities = 
201                         new ArrayList<Class<? extends MeterCapability>>();
202                 if(replyBody.getCapabilities().isOFPMFBURST()){
203                     supportedCapabilities.add(MeterBurst.class);
204                 }
205                 if(replyBody.getCapabilities().isOFPMFKBPS()){
206                     supportedCapabilities.add(MeterKbps.class);
207                     
208                 }
209                 if(replyBody.getCapabilities().isOFPMFPKTPS()){
210                     supportedCapabilities.add(MeterPktps.class);
211                     
212                 }
213                 if(replyBody.getCapabilities().isOFPMFSTATS()){
214                     supportedCapabilities.add(MeterStats.class);
215                     
216                 }
217                 message.setMeterCapabilitiesSupported(supportedCapabilities);
218                 
219                 List<Class<? extends MeterBand>> supportedMeterBand = 
220                         new ArrayList<Class <? extends MeterBand>>();
221                 if(replyBody.getBandTypes().isOFPMBTDROP()){
222                     supportedMeterBand.add(MeterBandDrop.class);
223                 }
224                 if(replyBody.getBandTypes().isOFPMBTDSCPREMARK()){
225                     supportedMeterBand.add(MeterBandDscpRemark.class);
226                 }
227                 message.setMeterBandSupported(supportedMeterBand);
228                 listDataObject.add(message.build());
229
230                 //augmentMeterFeaturesToNode(message);
231
232                 //Send update notification to all the listeners 
233                 return listDataObject;
234             }
235             default:
236                 logger.info(" Type : {}, not handled yet",mpReply.getType().name() );
237                 return listDataObject;
238             }
239         }
240         
241         return listDataObject;
242     }
243     
244     private void augmentGroupFeaturesToNode(GroupFeaturesUpdatedBuilder message){
245         GroupFeaturesBuilder groupFeatures = new GroupFeaturesBuilder();
246         groupFeatures.setActions(message.getActions());
247         groupFeatures.setGroupCapabilitiesSupported(message.getGroupCapabilitiesSupported());
248         groupFeatures.setGroupTypesSupported(message.getGroupTypesSupported());
249         groupFeatures.setMaxGroups(message.getMaxGroups());
250
251         final NodeBuilder nodeData = new NodeBuilder(); 
252         nodeData.setKey(new NodeKey(message.getId()));
253         
254         NodeGroupFeaturesBuilder nodeGroupFeatures= new NodeGroupFeaturesBuilder();
255         nodeGroupFeatures.setGroupFeatures(groupFeatures.build());
256         //Update augmented data
257         nodeData.addAugmentation(NodeGroupFeatures.class, nodeGroupFeatures.build());
258     }
259
260     private void augmentMeterFeaturesToNode(MeterFeaturesUpdatedBuilder message){
261         MeterFeaturesBuilder meterFeature = new MeterFeaturesBuilder();
262         meterFeature.setMeterBandSupported(message.getMeterBandSupported());
263         meterFeature.setMeterCapabilitiesSupported(message.getMeterCapabilitiesSupported());
264         meterFeature.setMaxBands(message.getMaxBands());
265         meterFeature.setMaxColor(message.getMaxColor());
266         meterFeature.setMaxMeter(message.getMaxMeter());
267         
268         final NodeBuilder nodeData = new NodeBuilder(); 
269         nodeData.setKey(new NodeKey(message.getId()));
270         
271         NodeMeterFeaturesBuilder nodeMeterFeatures= new NodeMeterFeaturesBuilder();
272         nodeMeterFeatures.setMeterFeatures(meterFeature.build());
273         //Update augmented data
274         nodeData.addAugmentation(NodeMeterFeatures.class, nodeMeterFeatures.build());
275     }
276     
277     private NodeId nodeIdFromDatapathId(BigInteger datapathId) {
278         String current = datapathId.toString();
279         return new NodeId("openflow:" + current);
280     }
281     
282     private TransactionId generateTransactionId(Long xid){
283         String stringXid =xid.toString();
284         BigInteger bigIntXid = new BigInteger( stringXid );
285         return new TransactionId(bigIntXid);
286
287     }
288
289     /* 
290      * Method returns the bitmap of actions supported by each group.
291      * TODO: My recommendation would be, its good to have a respective model of 
292      * 'type bits', which will generate a class where all these flags will eventually
293      * be stored as boolean. It will be convenient for application to check the
294      * supported action, rather then doing bitmap operation.
295      * @param actionsSupported
296      * @return
297      */
298     private List<Long> getGroupActionsSupportBitmap(List<org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType> actionsSupported){
299         List<Long> supportActionByGroups = new ArrayList<Long>();
300         for(org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType supportedActions : actionsSupported){
301             long supportActionBitmap = 0;
302             supportActionBitmap |= supportedActions.isOFPATOUTPUT()?(1 << 0): ~(1 << 0);
303             supportActionBitmap |= supportedActions.isOFPATCOPYTTLOUT()?(1 << 11): ~(1 << 11);
304             supportActionBitmap |= supportedActions.isOFPATCOPYTTLIN()?(1 << 12): ~(1 << 12);
305             supportActionBitmap |= supportedActions.isOFPATSETMPLSTTL()?(1 << 15): ~(1 << 15);
306             supportActionBitmap |= supportedActions.isOFPATDECMPLSTTL()?(1 << 16): ~(1 << 16);
307             supportActionBitmap |= supportedActions.isOFPATPUSHVLAN()?(1 << 16): ~(1 << 16);
308             supportActionBitmap |= supportedActions.isOFPATPOPVLAN()?(1 << 17): ~(1 << 17);
309             supportActionBitmap |= supportedActions.isOFPATPUSHMPLS()?(1 << 18): ~(1 << 18);
310             supportActionBitmap |= supportedActions.isOFPATPOPMPLS()?(1 << 19): ~(1 << 19);
311             supportActionBitmap |= supportedActions.isOFPATSETQUEUE()?(1 << 20): ~(1 << 20);
312             supportActionBitmap |= supportedActions.isOFPATGROUP()?(1 << 21): ~(1 << 21);
313             supportActionBitmap |= supportedActions.isOFPATSETNWTTL()?(1 << 22): ~(1 << 22);
314             supportActionBitmap |= supportedActions.isOFPATDECNWTTL()?(1 << 23): ~(1 << 23);
315             supportActionBitmap |= supportedActions.isOFPATSETFIELD()?(1 << 24): ~(1 << 24);
316             supportActionBitmap |= supportedActions.isOFPATPUSHPBB()?(1 << 25): ~(1 << 25);
317             supportActionBitmap |= supportedActions.isOFPATPOPPBB()?(1 << 26): ~(1 << 26);
318             supportActionBitmap |= supportedActions.isOFPATEXPERIMENTER()?(1 << 27): ~(1 << 27);
319             supportActionByGroups.add(new Long(supportActionBitmap));
320         }
321         return supportActionByGroups;
322     }
323
324 }