Update MRI upstreams for Phosphorus
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / protocol / deserialization / multipart / MultipartReplyMeterConfigDeserializer.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 package org.opendaylight.openflowplugin.impl.protocol.deserialization.multipart;
9
10 import static java.util.Objects.requireNonNull;
11 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint32;
12 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint8;
13
14 import io.netty.buffer.ByteBuf;
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.ExperimenterIdDeserializerKey;
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.multipart.reply.multipart.reply.body.MultipartReplyMeterConfigBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.BandId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterBandType;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterFlags;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DropBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemarkBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Experimenter;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeadersBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStatsBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStatsKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeaderKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.meter.band.header.MeterBandTypesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.multipart.types.rev170112.multipart.reply.MultipartReplyBody;
37 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
38 import org.opendaylight.yangtools.yang.common.Uint32;
39
40 public class MultipartReplyMeterConfigDeserializer implements OFDeserializer<MultipartReplyBody>,
41         DeserializerRegistryInjector {
42     private static final byte METER_CONFIG_LENGTH = 8;
43     private static final int OFPMBTDROP = 1;
44     private static final int OFPMBTDSCP = 2;
45     private static final int OFPMBTEXPERIMENTER = 0xFFFF;
46     private static final byte PADDING_IN_METER_BAND_DROP_HEADER = 4;
47     private static final byte PADDING_IN_METER_BAND_DSCP_HEADER = 3;
48
49     private DeserializerRegistry registry = null;
50
51     @Override
52     public MultipartReplyBody deserialize(final ByteBuf message) {
53         final MultipartReplyMeterConfigBuilder builder = new MultipartReplyMeterConfigBuilder();
54         final var items = BindingMap.<MeterConfigStatsKey, MeterConfigStats>orderedBuilder();
55
56         while (message.readableBytes() > 0) {
57             final int itemLength = message.readUnsignedShort();
58
59             final MeterConfigStatsBuilder itemBuilder = new MeterConfigStatsBuilder()
60                     .setFlags(readMeterFlags(message))
61                     .setMeterId(new MeterId(readUint32(message)));
62
63             final var subItems = BindingMap.<MeterBandHeaderKey, MeterBandHeader>orderedBuilder();
64             int actualLength = METER_CONFIG_LENGTH;
65             long bandKey = 0;
66
67             while (actualLength < itemLength) {
68                 final int itemStartIndex = message.readerIndex();
69                 final int itemBandType = message.readUnsignedShort();
70                 final MeterBandHeaderBuilder subItemBuilder = new MeterBandHeaderBuilder();
71                 actualLength += message.readUnsignedShort();
72
73                 switch (itemBandType) {
74                     case OFPMBTDROP:
75                         subItemBuilder
76                                 .setMeterBandTypes(new MeterBandTypesBuilder()
77                                         .setFlags(new MeterBandType(true, false, false))
78                                         .build())
79                                 .setBandType(new DropBuilder()
80                                         .setDropRate(readUint32(message))
81                                         .setDropBurstSize(readUint32(message))
82                                         .build());
83                         message.skipBytes(PADDING_IN_METER_BAND_DROP_HEADER);
84                         break;
85
86                     case OFPMBTDSCP:
87                         subItemBuilder
88                                 .setMeterBandTypes(new MeterBandTypesBuilder()
89                                         .setFlags(new MeterBandType(false, true, false))
90                                         .build())
91                                 .setBandType(new DscpRemarkBuilder()
92                                         .setDscpRemarkRate(readUint32(message))
93                                         .setDscpRemarkBurstSize(readUint32(message))
94                                         .setPrecLevel(readUint8(message))
95                                         .build());
96                         message.skipBytes(PADDING_IN_METER_BAND_DSCP_HEADER);
97                         break;
98
99                     case OFPMBTEXPERIMENTER:
100                         // TODO: Finish meter band experimenter deserialization
101                         final Uint32 expId =
102                             Uint32.fromIntBits(message.getInt(message.readerIndex() + 2 * Integer.BYTES));
103                         message.readerIndex(itemStartIndex);
104
105                         final OFDeserializer<Experimenter> deserializer = registry.getDeserializer(
106                                 new ExperimenterIdDeserializerKey(EncodeConstants.OF_VERSION_1_3, expId,
107                                         Experimenter.class));
108
109                         subItemBuilder
110                                 .setMeterBandTypes(new MeterBandTypesBuilder()
111                                         .setFlags(new MeterBandType(false, false, true))
112                                         .build())
113                                 .setBandType(deserializer.deserialize(message));
114                         break;
115                     default:
116                         // no operation
117
118                 }
119                 subItems.add(subItemBuilder.withKey(new MeterBandHeaderKey(new BandId(Uint32.valueOf(bandKey++))))
120                     .build());
121             }
122
123             items.add(itemBuilder
124                     .withKey(new MeterConfigStatsKey(itemBuilder.getMeterId()))
125                     .setMeterBandHeaders(new MeterBandHeadersBuilder()
126                             .setMeterBandHeader(subItems.build())
127                             .build())
128                     .build());
129         }
130
131         return builder
132                 .setMeterConfigStats(items.build())
133                 .build();
134     }
135
136     private static MeterFlags readMeterFlags(final ByteBuf message) {
137         int input = message.readUnsignedShort();
138         final Boolean mfKbps = (input & 1) != 0;
139         final Boolean mfPktps = (input & 1 << 1) != 0;
140         final Boolean mfBurst = (input & 1 << 2) != 0;
141         final Boolean mfStats = (input & 1 << 3) != 0;
142         return new MeterFlags(mfBurst, mfKbps, mfPktps, mfStats);
143     }
144
145     @Override
146     public void injectDeserializerRegistry(final DeserializerRegistry deserializerRegistry) {
147         registry = requireNonNull(deserializerRegistry);
148     }
149 }