Add multipart reply deserializers
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / protocol / deserialization / multipart / MultipartReplyFlowStatsDeserializer.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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
9 package org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart;
10
11 import io.netty.buffer.ByteBuf;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
18 import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
20 import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
21 import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
22 import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
23 import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
24 import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeActionExperimenterKey;
25 import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.and.statistics.map.list.FlowAndStatisticsMapListBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.multipart.reply.multipart.reply.body.MultipartReplyFlowStatsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.duration.DurationBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
41
42 public class MultipartReplyFlowStatsDeserializer implements OFDeserializer<MultipartReplyBody>, DeserializerRegistryInjector {
43
44     private static final MessageCodeKey MATCH_KEY = new MessageCodeMatchKey(EncodeConstants.OF13_VERSION_ID,
45             EncodeConstants.EMPTY_VALUE, Match.class,
46             MatchPath.FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH);
47
48     private static final byte PADDING_IN_FLOW_STATS_HEADER_01 = 1;
49     private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 4;
50     private DeserializerRegistry registry;
51
52     @Override
53     public MultipartReplyBody deserialize(ByteBuf message) {
54         final MultipartReplyFlowStatsBuilder builder = new MultipartReplyFlowStatsBuilder();
55         final List<FlowAndStatisticsMapList> items = new ArrayList<>();
56
57         while (message.readableBytes() > 0) {
58             final FlowAndStatisticsMapListBuilder itemBuilder = new FlowAndStatisticsMapListBuilder();
59             final int itemLength = message.readUnsignedShort();
60             final ByteBuf itemMessage = message.readSlice(itemLength - EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
61
62             itemBuilder.setTableId(itemMessage.readUnsignedByte());
63             itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_01);
64
65
66             itemBuilder
67                 .setDuration(new DurationBuilder()
68                         .setSecond(new Counter32(itemMessage.readUnsignedInt()))
69                         .setNanosecond(new Counter32(itemMessage.readUnsignedInt()))
70                         .build())
71                 .setPriority(itemMessage.readUnsignedShort())
72                 .setIdleTimeout(itemMessage.readUnsignedShort())
73                 .setHardTimeout(itemMessage.readUnsignedShort())
74                 .setFlags(createFlowModFlagsFromBitmap(itemMessage.readUnsignedShort()));
75
76             itemMessage.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
77
78             itemBuilder
79                 .setCookie(new FlowCookie(BigInteger.valueOf(message.readLong())))
80                 .setCookieMask(new FlowCookie(BigInteger.valueOf(message.readLong())))
81                 .setPacketCount(new Counter64(BigInteger.valueOf(message.readLong())))
82                 .setByteCount(new Counter64(BigInteger.valueOf(message.readLong())));
83
84
85             final OFDeserializer<Match> matchDeserializer = registry.getDeserializer(MATCH_KEY);
86             itemBuilder.setMatch(new MatchBuilder(matchDeserializer.deserialize(message)).build());
87
88             final int length = itemMessage.readableBytes();
89
90             if (length > 0) {
91                 final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
92                     .Instruction> instructions = new ArrayList<>();
93                 final int startIndex = itemMessage.readerIndex();
94                 int offset = 0;
95
96                 while ((itemMessage.readerIndex() - startIndex) < length) {
97                     final int type = itemMessage.getUnsignedShort(itemMessage.readerIndex());
98                     OFDeserializer<Instruction> deserializer = null;
99
100                     if (InstructionConstants.APPLY_ACTIONS_TYPE == type) {
101                         deserializer = registry.getDeserializer(
102                                 new MessageCodeActionExperimenterKey(
103                                     EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
104                                     ActionPath.NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_APPLYACTIONSCASE_APPLYACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION,
105                                     null));
106                     } else if (InstructionConstants.WRITE_ACTIONS_TYPE == type) {
107                         deserializer = registry.getDeserializer(
108                                 new MessageCodeActionExperimenterKey(
109                                     EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
110                                     ActionPath.NODES_NODE_TABLE_FLOW_INSTRUCTIONS_INSTRUCTION_WRITEACTIONSCASE_WRITEACTIONS_ACTION_ACTION_EXTENSIONLIST_EXTENSION,
111                                     null));
112                     } else {
113                         Long expId = null;
114
115                         if (EncodeConstants.EXPERIMENTER_VALUE == type) {
116                             expId = itemMessage.getUnsignedInt(itemMessage.readerIndex() +
117                                     2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
118                         }
119
120                         deserializer = registry.getDeserializer(
121                                 new MessageCodeExperimenterKey(
122                                     EncodeConstants.OF13_VERSION_ID, type, Instruction.class, expId));
123                     }
124
125                     instructions.add(new InstructionBuilder()
126                             .setKey(new InstructionKey(offset))
127                             .setOrder(offset)
128                             .setInstruction(deserializer.deserialize(itemMessage))
129                             .build());
130
131                     offset++;
132                 }
133
134                 itemBuilder.setInstructions(new InstructionsBuilder()
135                         .setInstruction(instructions)
136                         .build());
137             }
138
139             items.add(itemBuilder.build());
140         }
141
142         return builder
143             .setFlowAndStatisticsMapList(items)
144             .build();
145     }
146
147     private static FlowModFlags createFlowModFlagsFromBitmap(int input) {
148         final Boolean _oFPFFSENDFLOWREM = (input & (1 << 0)) > 0;
149         final Boolean _oFPFFCHECKOVERLAP = (input & (1 << 1)) > 0;
150         final Boolean _oFPFFRESETCOUNTS = (input & (1 << 2)) > 0;
151         final Boolean _oFPFFNOPKTCOUNTS = (input & (1 << 3)) > 0;
152         final Boolean _oFPFFNOBYTCOUNTS = (input & (1 << 4)) > 0;
153         return new FlowModFlags(_oFPFFCHECKOVERLAP, _oFPFFNOBYTCOUNTS, _oFPFFNOPKTCOUNTS, _oFPFFRESETCOUNTS,
154                 _oFPFFSENDFLOWREM);
155     }
156
157     @Override
158     public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
159         registry = deserializerRegistry;
160     }
161
162 }