Bump MRI upstreams
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / MeterConvertor.java
1 /*
2  * Copyright (c) 2014 Ericsson India Global Services Pvt Ltd. 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.openflow.md.core.sal.convertor;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.Collection;
15 import java.util.List;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
17 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeter;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemark;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Experimenter;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeaders;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ExperimenterIdMeterBandBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterBandType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterFlags;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterModCommand;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInputBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.MeterBand;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDropCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDscpRemarkCaseBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.drop._case.MeterBandDropBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.dscp.remark._case.MeterBandDscpRemarkBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.experimenter._case.MeterBandExperimenterBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.mod.Bands;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.mod.BandsBuilder;
43 import org.opendaylight.yangtools.yang.common.Uint8;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * Converts a MD-SAL meter mod command into the OF library meter mod command.
49  *
50  * <p>
51  * Example usage:
52  * <pre>
53  * {@code
54  * VersionConvertorData data = new VersionConvertorData(version);
55  * Optional<MeterModInputBuilder> ofMeter = convertorManager.convert(salMeter, data);
56  * }
57  * </pre>
58  */
59 public class MeterConvertor extends Convertor<Meter, MeterModInputBuilder, VersionConvertorData> {
60     private static final Logger LOG = LoggerFactory.getLogger(MeterConvertor.class);
61     private static final List<Class<?>> TYPES = Arrays.asList(Meter.class, AddMeterInput.class,
62             RemoveMeterInput.class, UpdatedMeter.class);
63
64     /**
65      * Create default empty meter mot input builder.
66      * Use this method, if result from convertor is empty.
67      *
68      * @param version Openflow version
69      * @return default empty meter mod input builder
70      */
71     public static MeterModInputBuilder defaultResult(final Uint8 version) {
72         return new MeterModInputBuilder()
73                 .setVersion(requireNonNull(version))
74                 .setFlags(new MeterFlags(false, false, true, false));
75     }
76
77     private static void getBandsFromSAL(final MeterBandHeaders meterBandHeaders, final List<Bands> bands) {
78         for (MeterBandHeader meterBandHeader : meterBandHeaders.nonnullMeterBandHeader().values()) {
79             // The band types :drop,DSCP_Remark or experimenter.
80             if (null != meterBandHeader.getMeterBandTypes() && null != meterBandHeader.getMeterBandTypes().getFlags()) {
81                 if (meterBandHeader.getMeterBandTypes().getFlags().getOfpmbtDrop()) {
82                     if (meterBandHeader.getBandType() != null) {
83                         MeterBandDropBuilder meterBandDropBuilder = new MeterBandDropBuilder();
84                         meterBandDropBuilder.setType(MeterBandType.OFPMBTDROP);
85                         Drop drop = (Drop) meterBandHeader.getBandType();
86                         meterBandDropBuilder.setBurstSize(drop.getDropBurstSize());
87                         meterBandDropBuilder.setRate(drop.getDropRate());
88                         MeterBandDropCaseBuilder dropCaseBuilder = new MeterBandDropCaseBuilder();
89                         dropCaseBuilder.setMeterBandDrop(meterBandDropBuilder.build());
90                         MeterBand meterBandItem = dropCaseBuilder.build();
91                         BandsBuilder bandsB = new BandsBuilder();
92                         bandsB.setMeterBand(meterBandItem);
93                         // Bands list
94                         bands.add(bandsB.build());
95                     } else {
96                         logBandTypeMissing(MeterBandType.OFPMBTDROP);
97                     }
98                 } else if (meterBandHeader.getMeterBandTypes().getFlags().getOfpmbtDscpRemark()) {
99                     if (meterBandHeader.getBandType() != null) {
100                         MeterBandDscpRemarkBuilder meterBandDscpRemarkBuilder = new MeterBandDscpRemarkBuilder();
101                         meterBandDscpRemarkBuilder.setType(MeterBandType.OFPMBTDSCPREMARK);
102                         DscpRemark dscpRemark = (DscpRemark) meterBandHeader.getBandType();
103                         meterBandDscpRemarkBuilder.setBurstSize(dscpRemark.getDscpRemarkBurstSize());
104                         meterBandDscpRemarkBuilder.setRate(dscpRemark.getDscpRemarkRate());
105                         meterBandDscpRemarkBuilder.setPrecLevel(dscpRemark.getPrecLevel());
106                         MeterBandDscpRemarkCaseBuilder dscpCaseBuilder = new MeterBandDscpRemarkCaseBuilder();
107                         dscpCaseBuilder.setMeterBandDscpRemark(meterBandDscpRemarkBuilder.build());
108                         MeterBand meterBandItem = dscpCaseBuilder.build();
109                         BandsBuilder bandsB = new BandsBuilder();
110                         bandsB.setMeterBand(meterBandItem);
111                         // Bands list
112                         bands.add(bandsB.build());
113                     } else {
114                         logBandTypeMissing(MeterBandType.OFPMBTDSCPREMARK);
115                     }
116                 } else if (meterBandHeader.getMeterBandTypes().getFlags().getOfpmbtExperimenter()) {
117                     if (meterBandHeader.getBandType() != null) {
118                         MeterBandExperimenterBuilder meterBandExperimenterBuilder = new MeterBandExperimenterBuilder();
119                         meterBandExperimenterBuilder.setType(MeterBandType.OFPMBTEXPERIMENTER);
120                         Experimenter experimenter = (Experimenter) meterBandHeader.getBandType();
121                         meterBandExperimenterBuilder.setBurstSize(experimenter.getExperimenterBurstSize());
122                         meterBandExperimenterBuilder.setRate(experimenter.getExperimenterRate());
123                         meterBandExperimenterBuilder.addAugmentation(new ExperimenterIdMeterBandBuilder()
124                             .setExperimenter(new ExperimenterId(experimenter.getExperimenter()))
125                             .build());
126                         // TODO - implement / finish experimenter meter band translation
127                         MeterBandExperimenterCaseBuilder experimenterCaseBuilder =
128                                 new MeterBandExperimenterCaseBuilder();
129                         experimenterCaseBuilder.setMeterBandExperimenter(meterBandExperimenterBuilder.build());
130                         MeterBand meterBandItem = experimenterCaseBuilder.build();
131                         BandsBuilder bandsB = new BandsBuilder();
132                         bandsB.setMeterBand(meterBandItem);
133                         // Bands list
134                         bands.add(bandsB.build());
135                     } else {
136                         logBandTypeMissing(MeterBandType.OFPMBTEXPERIMENTER);
137                     }
138                 }
139             } else {
140                 LOG.error("Invalid meter band data found.");
141             }
142         }
143
144     }
145
146     private static void logBandTypeMissing(final MeterBandType meterBandType) {
147         LOG.error("BandType: {} No Band Data found", meterBandType);
148     }
149
150     @Override
151     public Collection<Class<?>> getTypes() {
152         return  TYPES;
153     }
154
155     @Override
156     public MeterModInputBuilder convert(final Meter source, final VersionConvertorData data) {
157         MeterModInputBuilder meterModInputBuilder = new MeterModInputBuilder();
158         List<Bands> bands = new ArrayList<>();
159
160         if (source instanceof AddMeterInput) {
161             meterModInputBuilder.setCommand(MeterModCommand.OFPMCADD);
162         } else if (source instanceof RemoveMeterInput) {
163             meterModInputBuilder.setCommand(MeterModCommand.OFPMCDELETE);
164         } else if (source instanceof UpdatedMeter) {
165             meterModInputBuilder.setCommand(MeterModCommand.OFPMCMODIFY);
166         }
167
168         meterModInputBuilder.setMeterId(new MeterId(source.getMeterId().getValue()));
169         final var sourceFlags = source.getFlags();
170         if (sourceFlags == null) {
171             /*
172              * As per 0F1.3.1,The rate field indicates the rate value above
173              * which the corresponding band may apply to packets (see 5.7.1).
174              * The rate value is in kilobit per seconds, unless the flags eld
175              * includes OFPMF_PKTPS, in which case the rate is in packets per
176              * seconds.
177              */
178             meterModInputBuilder.setFlags(new MeterFlags(false, false, true, false));
179         } else {
180             meterModInputBuilder.setFlags(new MeterFlags(sourceFlags.getMeterBurst(), sourceFlags.getMeterKbps(),
181                 sourceFlags.getMeterPktps(), sourceFlags.getMeterStats()));
182         }
183
184         if (source.getMeterBandHeaders() != null) {
185             getBandsFromSAL(source.getMeterBandHeaders(), bands);
186             meterModInputBuilder.setBands(bands);
187         } else {
188             LOG.error("For this meter Id {}, no associated band data found!", source.getMeterId().getValue());
189         }
190
191         meterModInputBuilder.setVersion(data.getVersion());
192         return meterModInputBuilder;
193     }
194 }