2 * Copyright IBM Corporation, 2013. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.openflow.md.core.translator;
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.CopyOnWriteArrayList;
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;
74 * Class converts multipart reply messages to the notification objects defined
75 * by statistics provider (manager ).
77 * @author avishnoi@in.ibm.com
80 public class MultipartReplyTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
82 protected static final Logger logger = LoggerFactory
83 .getLogger(MultipartReplyTranslator.class);
85 private static FlowStatsResponseConvertor flowStatsConvertor = new FlowStatsResponseConvertor();
86 private static GroupStatsResponseConvertor groupStatsConvertor = new GroupStatsResponseConvertor();
87 private static MeterStatsResponseConvertor meterStatsConvertor = new MeterStatsResponseConvertor();
90 public List<DataObject> translate(SwitchConnectionDistinguisher cookie, SessionContext sc, OfHeader msg) {
92 List<DataObject> listDataObject = new CopyOnWriteArrayList<DataObject>();
94 if(msg instanceof MultipartReplyMessage){
95 MultipartReplyMessage mpReply = (MultipartReplyMessage)msg;
96 NodeId node = this.nodeIdFromDatapathId(sc.getFeatures().getDatapathId());
97 switch (mpReply.getType()){
99 logger.info("Received flow statistics reponse from openflow {} switch",msg.getVersion()==1?"1.0":"1.3+");
100 FlowsStatisticsUpdateBuilder message = new FlowsStatisticsUpdateBuilder();
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()));
108 logger.info("Converted flow statistics : {}",message.build().toString());
109 listDataObject.add(message.build());
110 return listDataObject;
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();
116 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
117 message.setTransactionId(generateTransactionId(mpReply.getXid()));
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()));
125 logger.info("Converted aggregate flow statistics : {}",message.build().toString());
126 listDataObject.add(message.build());
127 return listDataObject;
131 logger.info("Received group statistics multipart reponse");
132 GroupStatisticsUpdatedBuilder message = new GroupStatisticsUpdatedBuilder();
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()));
140 logger.debug("Converted group statistics : {}",message.toString());
141 listDataObject.add(message.build());
142 return listDataObject;
144 case OFPMPGROUPDESC:{
145 logger.info("Received group description statistics multipart reponse");
147 GroupDescStatsUpdatedBuilder message = new GroupDescStatsUpdatedBuilder();
149 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
150 message.setTransactionId(generateTransactionId(mpReply.getXid()));
151 MultipartReplyGroupDescCase caseBody = (MultipartReplyGroupDescCase)mpReply.getMultipartReplyBody();
152 MultipartReplyGroupDesc replyBody = caseBody.getMultipartReplyGroupDesc();
154 message.setGroupDescStats(groupStatsConvertor.toSALGroupDescStatsList(replyBody.getGroupDesc()));
156 logger.debug("Converted group statistics : {}",message.toString());
157 listDataObject.add(message.build());
158 return listDataObject;
160 case OFPMPGROUPFEATURES: {
161 logger.info("Received group features multipart reponse");
162 GroupFeaturesUpdatedBuilder message = new GroupFeaturesUpdatedBuilder();
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>>();
171 if(replyBody.getTypes().isOFPGTALL()){
172 supportedGroups.add(GroupAll.class);
174 if(replyBody.getTypes().isOFPGTSELECT()){
175 supportedGroups.add(GroupSelect.class);
177 if(replyBody.getTypes().isOFPGTINDIRECT()){
178 supportedGroups.add(GroupIndirect.class);
180 if(replyBody.getTypes().isOFPGTFF()){
181 supportedGroups.add(GroupFf.class);
183 message.setGroupTypesSupported(supportedGroups);
184 message.setMaxGroups(replyBody.getMaxGroups());
186 List<Class<? extends GroupCapability>> supportedCapabilities =
187 new ArrayList<Class<? extends GroupCapability>>();
189 if(replyBody.getCapabilities().isOFPGFCCHAINING()){
190 supportedCapabilities.add(Chaining.class);
192 if(replyBody.getCapabilities().isOFPGFCCHAININGCHECKS()){
193 supportedCapabilities.add(ChainingChecks.class);
195 if(replyBody.getCapabilities().isOFPGFCSELECTLIVENESS()){
196 supportedCapabilities.add(SelectLiveness.class);
198 if(replyBody.getCapabilities().isOFPGFCSELECTWEIGHT()){
199 supportedCapabilities.add(SelectWeight.class);
202 message.setGroupCapabilitiesSupported(supportedCapabilities);
204 message.setActions(getGroupActionsSupportBitmap(replyBody.getActionsBitmap()));
205 listDataObject.add(message.build());
207 //augmentGroupFeaturesToNode(message);
209 //Send update notification to all the listeners
210 return listDataObject;
213 logger.info("Received meter statistics multipart reponse");
214 MeterStatisticsUpdatedBuilder message = new MeterStatisticsUpdatedBuilder();
216 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
217 message.setTransactionId(generateTransactionId(mpReply.getXid()));
219 MultipartReplyMeterCase caseBody = (MultipartReplyMeterCase)mpReply.getMultipartReplyBody();
220 MultipartReplyMeter replyBody = caseBody.getMultipartReplyMeter();
221 message.setMeterStats(meterStatsConvertor.toSALMeterStatsList(replyBody.getMeterStats()));
223 listDataObject.add(message.build());
224 return listDataObject;
226 case OFPMPMETERCONFIG:{
227 logger.info("Received meter config statistics multipart reponse");
229 MeterConfigStatsUpdatedBuilder message = new MeterConfigStatsUpdatedBuilder();
231 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
232 message.setTransactionId(generateTransactionId(mpReply.getXid()));
234 MultipartReplyMeterConfigCase caseBody = (MultipartReplyMeterConfigCase)mpReply.getMultipartReplyBody();
235 MultipartReplyMeterConfig replyBody = caseBody.getMultipartReplyMeterConfig();
236 message.setMeterConfigStats(meterStatsConvertor.toSALMeterConfigList(replyBody.getMeterConfig()));
238 listDataObject.add(message.build());
239 return listDataObject;
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();
246 message.setMoreReplies(mpReply.getFlags().isOFPMPFREQMORE());
247 message.setTransactionId(generateTransactionId(mpReply.getXid()));
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()));
255 List<Class<? extends MeterCapability>> supportedCapabilities =
256 new ArrayList<Class<? extends MeterCapability>>();
257 if(replyBody.getCapabilities().isOFPMFBURST()){
258 supportedCapabilities.add(MeterBurst.class);
260 if(replyBody.getCapabilities().isOFPMFKBPS()){
261 supportedCapabilities.add(MeterKbps.class);
264 if(replyBody.getCapabilities().isOFPMFPKTPS()){
265 supportedCapabilities.add(MeterPktps.class);
268 if(replyBody.getCapabilities().isOFPMFSTATS()){
269 supportedCapabilities.add(MeterStats.class);
272 message.setMeterCapabilitiesSupported(supportedCapabilities);
274 List<Class<? extends MeterBand>> supportedMeterBand =
275 new ArrayList<Class <? extends MeterBand>>();
276 if(replyBody.getBandTypes().isOFPMBTDROP()){
277 supportedMeterBand.add(MeterBandDrop.class);
279 if(replyBody.getBandTypes().isOFPMBTDSCPREMARK()){
280 supportedMeterBand.add(MeterBandDscpRemark.class);
282 message.setMeterBandSupported(supportedMeterBand);
283 listDataObject.add(message.build());
285 //augmentMeterFeaturesToNode(message);
287 //Send update notification to all the listeners
288 return listDataObject;
291 return listDataObject;
295 return listDataObject;
298 private NodeId nodeIdFromDatapathId(BigInteger datapathId) {
299 String current = datapathId.toString();
300 return new NodeId("openflow:" + current);
303 private TransactionId generateTransactionId(Long xid){
304 String stringXid =xid.toString();
305 BigInteger bigIntXid = new BigInteger( stringXid );
306 return new TransactionId(bigIntXid);
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
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));
342 return supportActionByGroups;