2 * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. 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
9 package org.opendaylight.openflowjava.protocol.impl.deserialization.factories;
11 import io.netty.buffer.ByteBuf;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
17 import org.opendaylight.openflowjava.protocol.impl.deserialization.OFDeserializer;
18 import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;
19 import org.opendaylight.openflowjava.protocol.impl.util.EncodeConstants;
20 import org.opendaylight.openflowjava.protocol.impl.util.OF10ActionsDeserializer;
21 import org.opendaylight.openflowjava.protocol.impl.util.OF10MatchDeserializer;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCaseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregateBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenterBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlowBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStats;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStatsBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStatsBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStats;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStatsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueueBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStatsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTableBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStats;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStatsBuilder;
57 * Translates StatsReply messages (OpenFlow v1.0)
58 * @author michal.polkorab
60 public class OF10StatsReplyMessageFactory implements OFDeserializer<MultipartReplyMessage> {
62 private static final int DESC_STR_LEN = 256;
63 private static final int SERIAL_NUM_LEN = 32;
64 private static final byte PADDING_IN_FLOW_STATS_HEADER = 1;
65 private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 6;
66 private static final byte PADDING_IN_AGGREGATE_HEADER = 4;
67 private static final byte PADDING_IN_TABLE_HEADER = 3;
68 private static final byte MAX_TABLE_NAME_LENGTH = 32;
69 private static final byte PADDING_IN_PORT_STATS_HEADER = 6;
70 private static final byte PADDING_IN_QUEUE_HEADER = 2;
71 private static final byte LENGTH_OF_FLOW_STATS = 88;
72 private static final int TABLE_STATS_LENGTH = 64;
74 private static OF10StatsReplyMessageFactory instance;
76 private OF10StatsReplyMessageFactory() {
81 * @return singleton factory
83 public static synchronized OF10StatsReplyMessageFactory getInstance() {
84 if (instance == null){
85 instance = new OF10StatsReplyMessageFactory();
91 public MultipartReplyMessage bufferToMessage(ByteBuf rawMessage, short version) {
92 MultipartReplyMessageBuilder builder = new MultipartReplyMessageBuilder();
93 builder.setVersion(version);
94 builder.setXid(rawMessage.readUnsignedInt());
95 int type = rawMessage.readUnsignedShort();
96 builder.setType(MultipartType.forValue(type));
97 builder.setFlags(new MultipartRequestFlags((rawMessage.readUnsignedShort() & 0x01) != 0));
99 case 0: builder.setMultipartReplyBody(setDesc(rawMessage));
101 case 1: builder.setMultipartReplyBody(setFlow(rawMessage));
103 case 2: builder.setMultipartReplyBody(setAggregate(rawMessage));
105 case 3: builder.setMultipartReplyBody(setTable(rawMessage));
107 case 4: builder.setMultipartReplyBody(setPortStats(rawMessage));
109 case 5: builder.setMultipartReplyBody(setQueue(rawMessage));
111 case 0xFFFF: builder.setMultipartReplyBody(setExperimenter(rawMessage));
116 return builder.build();
119 private static MultipartReplyDescCase setDesc(ByteBuf input) {
120 MultipartReplyDescCaseBuilder caseBuilder = new MultipartReplyDescCaseBuilder();
121 MultipartReplyDescBuilder descBuilder = new MultipartReplyDescBuilder();
122 byte[] mfrDescBytes = new byte[DESC_STR_LEN];
123 input.readBytes(mfrDescBytes);
124 String mfrDesc = new String(mfrDescBytes);
125 descBuilder.setMfrDesc(mfrDesc.trim());
126 byte[] hwDescBytes = new byte[DESC_STR_LEN];
127 input.readBytes(hwDescBytes);
128 String hwDesc = new String(hwDescBytes);
129 descBuilder.setHwDesc(hwDesc.trim());
130 byte[] swDescBytes = new byte[DESC_STR_LEN];
131 input.readBytes(swDescBytes);
132 String swDesc = new String(swDescBytes);
133 descBuilder.setSwDesc(swDesc.trim());
134 byte[] serialNumBytes = new byte[SERIAL_NUM_LEN];
135 input.readBytes(serialNumBytes);
136 String serialNum = new String(serialNumBytes);
137 descBuilder.setSerialNum(serialNum.trim());
138 byte[] dpDescBytes = new byte[DESC_STR_LEN];
139 input.readBytes(dpDescBytes);
140 String dpDesc = new String(dpDescBytes);
141 descBuilder.setDpDesc(dpDesc.trim());
142 caseBuilder.setMultipartReplyDesc(descBuilder.build());
143 return caseBuilder.build();
146 private static MultipartReplyFlowCase setFlow(ByteBuf input) {
147 MultipartReplyFlowCaseBuilder caseBuilder = new MultipartReplyFlowCaseBuilder();
148 MultipartReplyFlowBuilder flowBuilder = new MultipartReplyFlowBuilder();
149 List<FlowStats> flowStatsList = new ArrayList<>();
150 while (input.readableBytes() > 0) {
151 FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder();
152 int length = input.readUnsignedShort();
153 flowStatsBuilder.setTableId(input.readUnsignedByte());
154 input.skipBytes(PADDING_IN_FLOW_STATS_HEADER);
155 flowStatsBuilder.setMatchV10(OF10MatchDeserializer.createMatchV10(input));
156 flowStatsBuilder.setDurationSec(input.readUnsignedInt());
157 flowStatsBuilder.setDurationNsec(input.readUnsignedInt());
158 flowStatsBuilder.setPriority(input.readUnsignedShort());
159 flowStatsBuilder.setIdleTimeout(input.readUnsignedShort());
160 flowStatsBuilder.setHardTimeout(input.readUnsignedShort());
161 input.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
162 byte[] cookie = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
163 input.readBytes(cookie);
164 flowStatsBuilder.setCookie(new BigInteger(1, cookie));
165 byte[] packetCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
166 input.readBytes(packetCount);
167 flowStatsBuilder.setPacketCount(new BigInteger(1, packetCount));
168 byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
169 input.readBytes(byteCount);
170 flowStatsBuilder.setByteCount(new BigInteger(1, byteCount));
171 flowStatsBuilder.setAction(OF10ActionsDeserializer
172 .createActionsList(input, length - LENGTH_OF_FLOW_STATS));
173 flowStatsList.add(flowStatsBuilder.build());
175 flowBuilder.setFlowStats(flowStatsList);
176 caseBuilder.setMultipartReplyFlow(flowBuilder.build());
177 return caseBuilder.build();
180 private static MultipartReplyAggregateCase setAggregate(ByteBuf input) {
181 MultipartReplyAggregateCaseBuilder caseBuilder = new MultipartReplyAggregateCaseBuilder();
182 MultipartReplyAggregateBuilder builder = new MultipartReplyAggregateBuilder();
183 byte[] packetCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
184 input.readBytes(packetCount);
185 builder.setPacketCount(new BigInteger(1, packetCount));
186 byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
187 input.readBytes(byteCount);
188 builder.setByteCount(new BigInteger(1, byteCount));
189 builder.setFlowCount(input.readUnsignedInt());
190 input.skipBytes(PADDING_IN_AGGREGATE_HEADER);
191 caseBuilder.setMultipartReplyAggregate(builder.build());
192 return caseBuilder.build();
195 private static MultipartReplyTableCase setTable(ByteBuf input) {
196 MultipartReplyTableCaseBuilder caseBuilder = new MultipartReplyTableCaseBuilder();
197 MultipartReplyTableBuilder builder = new MultipartReplyTableBuilder();
198 List<TableStats> tableStatsList = new ArrayList<>();
199 // TODO - replace ">= TABLE_STATS_LENGTH" with "> 0" after fix in OVS switch
200 while (input.readableBytes() >= TABLE_STATS_LENGTH) {
201 TableStatsBuilder tableStatsBuilder = new TableStatsBuilder();
202 tableStatsBuilder.setTableId(input.readUnsignedByte());
203 input.skipBytes(PADDING_IN_TABLE_HEADER);
204 tableStatsBuilder.setName(ByteBufUtils.decodeNullTerminatedString(input, MAX_TABLE_NAME_LENGTH));
205 long wildcards = input.readUnsignedInt();
206 tableStatsBuilder.setWildcards(OF10MatchDeserializer.createWildcards(wildcards));
207 tableStatsBuilder.setNwSrcMask(OF10MatchDeserializer.decodeNwSrcMask(wildcards));
208 tableStatsBuilder.setNwDstMask(OF10MatchDeserializer.decodeNwDstMask(wildcards));
209 tableStatsBuilder.setMaxEntries(input.readUnsignedInt());
210 tableStatsBuilder.setActiveCount(input.readUnsignedInt());
211 byte[] lookupCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
212 input.readBytes(lookupCount);
213 tableStatsBuilder.setLookupCount(new BigInteger(1, lookupCount));
214 byte[] matchedCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
215 input.readBytes(matchedCount);
216 tableStatsBuilder.setMatchedCount(new BigInteger(1, matchedCount));
217 tableStatsList.add(tableStatsBuilder.build());
219 input.skipBytes(input.readableBytes());
220 builder.setTableStats(tableStatsList);
221 caseBuilder.setMultipartReplyTable(builder.build());
222 return caseBuilder.build();
225 private static MultipartReplyPortStatsCase setPortStats(ByteBuf input) {
226 MultipartReplyPortStatsCaseBuilder caseBuilder = new MultipartReplyPortStatsCaseBuilder();
227 MultipartReplyPortStatsBuilder builder = new MultipartReplyPortStatsBuilder();
228 List<PortStats> portStatsList = new ArrayList<>();
229 while (input.readableBytes() > 0) {
230 PortStatsBuilder portStatsBuilder = new PortStatsBuilder();
231 portStatsBuilder.setPortNo((long) input.readUnsignedShort());
232 input.skipBytes(PADDING_IN_PORT_STATS_HEADER);
233 byte[] rxPackets = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
234 input.readBytes(rxPackets);
235 portStatsBuilder.setRxPackets(new BigInteger(1, rxPackets));
236 byte[] txPackets = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
237 input.readBytes(txPackets);
238 portStatsBuilder.setTxPackets(new BigInteger(1, txPackets));
239 byte[] rxBytes = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
240 input.readBytes(rxBytes);
241 portStatsBuilder.setRxBytes(new BigInteger(1, rxBytes));
242 byte[] txBytes = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
243 input.readBytes(txBytes);
244 portStatsBuilder.setTxBytes(new BigInteger(1, txBytes));
245 byte[] rxDropped = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
246 input.readBytes(rxDropped);
247 portStatsBuilder.setRxDropped(new BigInteger(1, rxDropped));
248 byte[] txDropped = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
249 input.readBytes(txDropped);
250 portStatsBuilder.setTxDropped(new BigInteger(1, txDropped));
251 byte[] rxErrors = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
252 input.readBytes(rxErrors);
253 portStatsBuilder.setRxErrors(new BigInteger(1, rxErrors));
254 byte[] txErrors = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
255 input.readBytes(txErrors);
256 portStatsBuilder.setTxErrors(new BigInteger(1, txErrors));
257 byte[] rxFrameErr = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
258 input.readBytes(rxFrameErr);
259 portStatsBuilder.setRxFrameErr(new BigInteger(1, rxFrameErr));
260 byte[] rxOverErr = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
261 input.readBytes(rxOverErr);
262 portStatsBuilder.setRxOverErr(new BigInteger(1, rxOverErr));
263 byte[] rxCrcErr = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
264 input.readBytes(rxCrcErr);
265 portStatsBuilder.setRxCrcErr(new BigInteger(1, rxCrcErr));
266 byte[] collisions = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
267 input.readBytes(collisions);
268 portStatsBuilder.setCollisions(new BigInteger(1, collisions));
269 portStatsList.add(portStatsBuilder.build());
271 builder.setPortStats(portStatsList);
272 caseBuilder.setMultipartReplyPortStats(builder.build());
273 return caseBuilder.build();
276 private static MultipartReplyQueueCase setQueue(ByteBuf input) {
277 MultipartReplyQueueCaseBuilder caseBuilder = new MultipartReplyQueueCaseBuilder();
278 MultipartReplyQueueBuilder builder = new MultipartReplyQueueBuilder();
279 List<QueueStats> queueStatsList = new ArrayList<>();
280 while (input.readableBytes() > 0) {
281 QueueStatsBuilder queueStatsBuilder = new QueueStatsBuilder();
282 queueStatsBuilder.setPortNo((long) input.readUnsignedShort());
283 input.skipBytes(PADDING_IN_QUEUE_HEADER);
284 queueStatsBuilder.setQueueId(input.readUnsignedInt());
285 byte[] txBytes = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
286 input.readBytes(txBytes);
287 queueStatsBuilder.setTxBytes(new BigInteger(1, txBytes));
288 byte[] txPackets = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
289 input.readBytes(txPackets);
290 queueStatsBuilder.setTxPackets(new BigInteger(1, txPackets));
291 byte[] txErrors = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
292 input.readBytes(txErrors);
293 queueStatsBuilder.setTxErrors(new BigInteger(1, txErrors));
294 queueStatsList.add(queueStatsBuilder.build());
296 builder.setQueueStats(queueStatsList);
297 caseBuilder.setMultipartReplyQueue(builder.build());
298 return caseBuilder.build();
301 private static MultipartReplyExperimenterCase setExperimenter(ByteBuf input) {
302 MultipartReplyExperimenterCaseBuilder caseBuilder = new MultipartReplyExperimenterCaseBuilder();
303 MultipartReplyExperimenterBuilder builder = new MultipartReplyExperimenterBuilder();
304 builder.setExperimenter(input.readUnsignedInt());
305 byte[] data = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
306 input.readBytes(data);
307 builder.setData(data);
308 caseBuilder.setMultipartReplyExperimenter(builder.build());
309 return caseBuilder.build();