Extend openflow-protocol-impl serialization
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / serialization / factories / OF10StatsReplyMessageFactory.java
1 /*
2  * Copyright (c) 2015 NetIDE Consortium 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.openflowjava.protocol.impl.serialization.factories;
9
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.UnpooledByteBufAllocator;
12 import java.util.HashMap;
13 import java.util.Map;
14 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistryInjector;
17 import org.opendaylight.openflowjava.protocol.api.keys.MessageTypeKey;
18 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
19 import org.opendaylight.openflowjava.protocol.impl.util.ListSerializer;
20 import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMaker;
21 import org.opendaylight.openflowjava.protocol.impl.util.TypeKeyMakerFactory;
22 import org.opendaylight.openflowjava.util.ByteBufUtils;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowWildcardsV10;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.MultipartReplyBody;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
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.MultipartReplyPortStatsCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregate;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDesc;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenter;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlow;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStats;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStats;
42 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;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueue;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTable;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStats;
47
48 /**
49  * @author giuseppex.petralia@intel.com
50  *
51  */
52 public class OF10StatsReplyMessageFactory implements OFSerializer<MultipartReplyMessage>, SerializerRegistryInjector {
53
54     private SerializerRegistry registry;
55     private static final byte MESSAGE_TYPE = 17;
56     private static final byte FLOW_STATS_PADDING_1 = 1;
57     private static final byte FLOW_STATS_PADDING_2 = 6;
58     private static final TypeKeyMaker<Action> ACTION_KEY_MAKER = TypeKeyMakerFactory
59             .createActionKeyMaker(EncodeConstants.OF10_VERSION_ID);
60     private static final int FLOW_STATS_LENGTH_INDEX = 0;
61     private static final int QUEUE_STATS_LENGTH_INDEX = 0;
62     private static final byte AGGREGATE_PADDING = 4;
63     private static final byte TABLE_PADDING = 3;
64     private static final byte QUEUE_PADDING = 2;
65     private static final byte PORT_STATS_PADDING = 6;
66
67     @Override
68     public void injectSerializerRegistry(SerializerRegistry serializerRegistry) {
69         registry = serializerRegistry;
70     }
71
72     @Override
73     public void serialize(MultipartReplyMessage message, ByteBuf outBuffer) {
74         ByteBufUtils.writeOFHeader(MESSAGE_TYPE, message, outBuffer, EncodeConstants.EMPTY_LENGTH);
75         outBuffer.writeShort(message.getType().getIntValue());
76         writeFlags(message.getFlags(), outBuffer);
77         switch (message.getType()) {
78         case OFPMPDESC:
79             serializeDescBody(message.getMultipartReplyBody(), outBuffer);
80             break;
81         case OFPMPFLOW:
82             serializeFlowBody(message.getMultipartReplyBody(), outBuffer, message);
83             break;
84         case OFPMPAGGREGATE:
85             serializeAggregateBody(message.getMultipartReplyBody(), outBuffer);
86             break;
87         case OFPMPTABLE:
88             serializeTableBody(message.getMultipartReplyBody(), outBuffer);
89             break;
90         case OFPMPPORTSTATS:
91             serializePortStatsBody(message.getMultipartReplyBody(), outBuffer);
92             break;
93         case OFPMPQUEUE:
94             serializeQueueBody(message.getMultipartReplyBody(), outBuffer);
95             break;
96         case OFPMPEXPERIMENTER:
97             serializeExperimenterBody(message.getMultipartReplyBody(), outBuffer);
98             break;
99         default:
100             break;
101         }
102         ByteBufUtils.updateOFHeaderLength(outBuffer);
103     }
104
105     private void serializeExperimenterBody(MultipartReplyBody body, ByteBuf outBuffer) {
106         MultipartReplyExperimenterCase experimenterCase = (MultipartReplyExperimenterCase) body;
107         MultipartReplyExperimenter experimenterBody = experimenterCase.getMultipartReplyExperimenter();
108         // TODO: experimenterBody does not have get methods
109     }
110
111     private void serializeQueueBody(MultipartReplyBody body, ByteBuf outBuffer) {
112         MultipartReplyQueueCase queueCase = (MultipartReplyQueueCase) body;
113         MultipartReplyQueue queue = queueCase.getMultipartReplyQueue();
114         for (QueueStats queueStats : queue.getQueueStats()) {
115             ByteBuf queueStatsBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
116             queueStatsBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
117             queueStatsBuff.writeZero(QUEUE_PADDING);
118             queueStatsBuff.writeInt(queueStats.getQueueId().intValue());
119             queueStatsBuff.writeLong(queueStats.getTxBytes().longValue());
120             queueStatsBuff.writeLong(queueStats.getTxPackets().longValue());
121             queueStatsBuff.writeLong(queueStats.getTxErrors().longValue());
122             queueStatsBuff.setShort(QUEUE_STATS_LENGTH_INDEX, queueStatsBuff.readableBytes());
123             outBuffer.writeBytes(queueStatsBuff);
124         }
125     }
126
127     private void serializePortStatsBody(MultipartReplyBody body, ByteBuf outBuffer) {
128         MultipartReplyPortStatsCase portStatsCase = (MultipartReplyPortStatsCase) body;
129         MultipartReplyPortStats portStats = portStatsCase.getMultipartReplyPortStats();
130         for (PortStats portStat : portStats.getPortStats()) {
131             outBuffer.writeInt(portStat.getPortNo().intValue());
132             outBuffer.writeZero(PORT_STATS_PADDING);
133             outBuffer.writeLong(portStat.getRxPackets().longValue());
134             outBuffer.writeLong(portStat.getTxPackets().longValue());
135             outBuffer.writeLong(portStat.getRxBytes().longValue());
136             outBuffer.writeLong(portStat.getTxBytes().longValue());
137             outBuffer.writeLong(portStat.getRxDropped().longValue());
138             outBuffer.writeLong(portStat.getTxDropped().longValue());
139             outBuffer.writeLong(portStat.getRxErrors().longValue());
140             outBuffer.writeLong(portStat.getTxErrors().longValue());
141             outBuffer.writeLong(portStat.getRxFrameErr().longValue());
142             outBuffer.writeLong(portStat.getRxOverErr().longValue());
143             outBuffer.writeLong(portStat.getRxCrcErr().longValue());
144             outBuffer.writeLong(portStat.getCollisions().longValue());
145         }
146     }
147
148     private void serializeTableBody(MultipartReplyBody body, ByteBuf outBuffer) {
149         MultipartReplyTableCase tableCase = (MultipartReplyTableCase) body;
150         MultipartReplyTable table = tableCase.getMultipartReplyTable();
151         for (TableStats tableStats : table.getTableStats()) {
152             outBuffer.writeByte(tableStats.getTableId());
153             outBuffer.writeZero(TABLE_PADDING);
154             write16String(tableStats.getName(), outBuffer);
155             writeFlowWildcardsV10(tableStats.getWildcards(), outBuffer);
156             outBuffer.writeInt(tableStats.getMaxEntries().intValue());
157             outBuffer.writeInt(tableStats.getActiveCount().intValue());
158             outBuffer.writeLong(tableStats.getLookupCount().longValue());
159             outBuffer.writeLong(tableStats.getMatchedCount().longValue());
160         }
161     }
162
163     private void writeFlowWildcardsV10(FlowWildcardsV10 feature, ByteBuf outBuffer) {
164         Map<Integer, Boolean> map = new HashMap<>();
165         map.put(0, feature.isINPORT());
166         map.put(1, feature.isDLVLAN());
167         map.put(2, feature.isDLSRC());
168         map.put(3, feature.isDLDST());
169         map.put(4, feature.isDLTYPE());
170         map.put(5, feature.isNWPROTO());
171         map.put(6, feature.isTPSRC());
172         map.put(7, feature.isTPDST());
173         map.put(20, feature.isDLVLANPCP());
174         map.put(21, feature.isNWTOS());
175         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
176         outBuffer.writeInt(bitmap);
177     }
178
179     private void serializeAggregateBody(MultipartReplyBody body, ByteBuf outBuffer) {
180         MultipartReplyAggregateCase aggregateCase = (MultipartReplyAggregateCase) body;
181         MultipartReplyAggregate aggregate = aggregateCase.getMultipartReplyAggregate();
182         outBuffer.writeLong(aggregate.getPacketCount().longValue());
183         outBuffer.writeLong(aggregate.getByteCount().longValue());
184         outBuffer.writeInt(aggregate.getFlowCount().intValue());
185         outBuffer.writeZero(AGGREGATE_PADDING);
186     }
187
188     private void serializeFlowBody(MultipartReplyBody body, ByteBuf outBuffer, MultipartReplyMessage message) {
189         MultipartReplyFlowCase flowCase = (MultipartReplyFlowCase) body;
190         MultipartReplyFlow flow = flowCase.getMultipartReplyFlow();
191         for (FlowStats flowStats : flow.getFlowStats()) {
192             ByteBuf flowStatsBuff = UnpooledByteBufAllocator.DEFAULT.buffer();
193             flowStatsBuff.writeShort(EncodeConstants.EMPTY_LENGTH);
194             flowStatsBuff.writeByte(new Long(flowStats.getTableId()).byteValue());
195             flowStatsBuff.writeZero(FLOW_STATS_PADDING_1);
196             OFSerializer<MatchV10> matchSerializer = registry
197                     .getSerializer(new MessageTypeKey<>(message.getVersion(), MatchV10.class));
198             matchSerializer.serialize(flowStats.getMatchV10(), flowStatsBuff);
199             flowStatsBuff.writeInt(flowStats.getDurationSec().intValue());
200             flowStatsBuff.writeInt(flowStats.getDurationNsec().intValue());
201             flowStatsBuff.writeShort(flowStats.getPriority());
202             flowStatsBuff.writeShort(flowStats.getIdleTimeout());
203             flowStatsBuff.writeShort(flowStats.getHardTimeout());
204             flowStatsBuff.writeZero(FLOW_STATS_PADDING_2);
205             flowStatsBuff.writeLong(flowStats.getCookie().longValue());
206             flowStatsBuff.writeLong(flowStats.getPacketCount().longValue());
207             flowStatsBuff.writeLong(flowStats.getByteCount().longValue());
208             ListSerializer.serializeList(flowStats.getAction(), ACTION_KEY_MAKER, registry, flowStatsBuff);
209             flowStatsBuff.setShort(FLOW_STATS_LENGTH_INDEX, flowStatsBuff.readableBytes());
210             outBuffer.writeBytes(flowStatsBuff);
211         }
212     }
213
214     private void writeFlags(MultipartRequestFlags flags, ByteBuf outBuffer) {
215         Map<Integer, Boolean> map = new HashMap<>();
216         map.put(0, flags.isOFPMPFREQMORE());
217         int bitmap = ByteBufUtils.fillBitMaskFromMap(map);
218         outBuffer.writeShort(bitmap);
219     }
220
221     private void serializeDescBody(MultipartReplyBody body, ByteBuf outBuffer) {
222         MultipartReplyDescCase descCase = (MultipartReplyDescCase) body;
223         MultipartReplyDesc desc = descCase.getMultipartReplyDesc();
224         write256String(desc.getMfrDesc(), outBuffer);
225         write256String(desc.getHwDesc(), outBuffer);
226         write256String(desc.getSwDesc(), outBuffer);
227         write32String(desc.getSerialNum(), outBuffer);
228         write256String(desc.getDpDesc(), outBuffer);
229     }
230
231     private void write256String(String toWrite, ByteBuf outBuffer) {
232         byte[] nameBytes = toWrite.getBytes();
233         if (nameBytes.length < 256) {
234             byte[] nameBytesPadding = new byte[256];
235             int i = 0;
236             for (byte b : nameBytes) {
237                 nameBytesPadding[i] = b;
238                 i++;
239             }
240             for (; i < 256; i++) {
241                 nameBytesPadding[i] = 0x0;
242             }
243             outBuffer.writeBytes(nameBytesPadding);
244         } else {
245             outBuffer.writeBytes(nameBytes);
246         }
247     }
248
249     private void write16String(String toWrite, ByteBuf outBuffer) {
250         byte[] nameBytes = toWrite.getBytes();
251         if (nameBytes.length < 16) {
252             byte[] nameBytesPadding = new byte[16];
253             int i = 0;
254             for (byte b : nameBytes) {
255                 nameBytesPadding[i] = b;
256                 i++;
257             }
258             for (; i < 16; i++) {
259                 nameBytesPadding[i] = 0x0;
260             }
261             outBuffer.writeBytes(nameBytesPadding);
262         } else {
263             outBuffer.writeBytes(nameBytes);
264         }
265     }
266
267     private void write32String(String toWrite, ByteBuf outBuffer) {
268         byte[] nameBytes = toWrite.getBytes();
269         if (nameBytes.length < 32) {
270             byte[] nameBytesPadding = new byte[32];
271             int i = 0;
272             for (byte b : nameBytes) {
273                 nameBytesPadding[i] = b;
274                 i++;
275             }
276             for (; i < 32; i++) {
277                 nameBytesPadding[i] = 0x0;
278             }
279             outBuffer.writeBytes(nameBytesPadding);
280         } else {
281             outBuffer.writeBytes(nameBytes);
282         }
283     }
284 }