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