/* * Copyright (c) 2014 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.RemoveMeterInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.meter.update.UpdatedMeter; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.Meter; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Drop; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.DscpRemark; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.band.type.band.type.Experimenter; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.MeterBandHeaders; import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.meter.band.headers.MeterBandHeader; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ExperimenterIdMeterBand; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.ExperimenterIdMeterBandBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterBandType; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterFlags; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterId; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MeterModCommand; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.MeterBand; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDropCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandDscpRemarkCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.MeterBandExperimenterCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.drop._case.MeterBandDropBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.dscp.remark._case.MeterBandDscpRemarkBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.band.header.meter.band.meter.band.experimenter._case.MeterBandExperimenterBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.mod.Bands; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.mod.BandsBuilder; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Converts a MD-SAL meter mod command into the OF library meter mod command. * <p> * Example usage: * <pre> * {@code * VersionConvertorData data = new VersionConvertorData(version); * Optional<MeterModInputBuilder> ofMeter = convertorManager.convert(salMeter, data); * } * </pre> */ public class MeterConvertor extends Convertor<Meter, MeterModInputBuilder, VersionConvertorData> { private static final Logger LOG = LoggerFactory.getLogger(MeterConvertor.class); private static final List<Class<? extends DataContainer>> TYPES = Arrays.asList(Meter.class, AddMeterInput.class, RemoveMeterInput.class, UpdatedMeter.class); /** * Create default empty meter mot input builder. * Use this method, if result from convertor is empty. * * @param version Openflow version * @return default empty meter mod input builder */ public static MeterModInputBuilder defaultResult(short version) { return new MeterModInputBuilder() .setVersion(version) .setFlags(new MeterFlags(false, false, true, false)); } private static void getBandsFromSAL(MeterBandHeaders meterBandHeaders, List<Bands> bands) { for (MeterBandHeader meterBandHeader : meterBandHeaders.getMeterBandHeader()) { // The band types :drop,DSCP_Remark or experimenter. if (null != meterBandHeader.getMeterBandTypes() && null != meterBandHeader.getMeterBandTypes().getFlags()) { if (meterBandHeader.getMeterBandTypes().getFlags().isOfpmbtDrop()) { if (meterBandHeader.getBandType() != null) { MeterBandDropCaseBuilder dropCaseBuilder = new MeterBandDropCaseBuilder(); MeterBandDropBuilder meterBandDropBuilder = new MeterBandDropBuilder(); meterBandDropBuilder.setType(MeterBandType.OFPMBTDROP); Drop drop = (Drop) meterBandHeader.getBandType(); meterBandDropBuilder.setBurstSize(drop.getDropBurstSize()); meterBandDropBuilder.setRate(drop.getDropRate()); dropCaseBuilder.setMeterBandDrop(meterBandDropBuilder.build()); MeterBand meterBandItem = dropCaseBuilder.build(); BandsBuilder bandsB = new BandsBuilder(); bandsB.setMeterBand(meterBandItem); // Bands list bands.add(bandsB.build()); } else { logBandTypeMissing(MeterBandType.OFPMBTDROP); } } else if (meterBandHeader.getMeterBandTypes().getFlags().isOfpmbtDscpRemark()) { if (meterBandHeader.getBandType() != null) { MeterBandDscpRemarkCaseBuilder dscpCaseBuilder = new MeterBandDscpRemarkCaseBuilder(); MeterBandDscpRemarkBuilder meterBandDscpRemarkBuilder = new MeterBandDscpRemarkBuilder(); meterBandDscpRemarkBuilder.setType(MeterBandType.OFPMBTDSCPREMARK); DscpRemark dscpRemark = (DscpRemark) meterBandHeader.getBandType(); meterBandDscpRemarkBuilder.setBurstSize(dscpRemark.getDscpRemarkBurstSize()); meterBandDscpRemarkBuilder.setRate(dscpRemark.getDscpRemarkRate()); meterBandDscpRemarkBuilder.setPrecLevel(dscpRemark.getPrecLevel()); dscpCaseBuilder.setMeterBandDscpRemark(meterBandDscpRemarkBuilder.build()); MeterBand meterBandItem = dscpCaseBuilder.build(); BandsBuilder bandsB = new BandsBuilder(); bandsB.setMeterBand(meterBandItem); // Bands list bands.add(bandsB.build()); } else { logBandTypeMissing(MeterBandType.OFPMBTDSCPREMARK); } } else if (meterBandHeader.getMeterBandTypes().getFlags().isOfpmbtExperimenter()) { if (meterBandHeader.getBandType() != null) { MeterBandExperimenterCaseBuilder experimenterCaseBuilder = new MeterBandExperimenterCaseBuilder(); MeterBandExperimenterBuilder meterBandExperimenterBuilder = new MeterBandExperimenterBuilder(); meterBandExperimenterBuilder.setType(MeterBandType.OFPMBTEXPERIMENTER); Experimenter experimenter = (Experimenter) meterBandHeader.getBandType(); meterBandExperimenterBuilder.setBurstSize(experimenter.getExperimenterBurstSize()); meterBandExperimenterBuilder.setRate(experimenter.getExperimenterRate()); ExperimenterIdMeterBandBuilder expBuilder = new ExperimenterIdMeterBandBuilder(); expBuilder.setExperimenter(new ExperimenterId(experimenter.getExperimenter())); meterBandExperimenterBuilder.addAugmentation(ExperimenterIdMeterBand.class, expBuilder.build()); // TODO - implement / finish experimenter meter band translation experimenterCaseBuilder.setMeterBandExperimenter(meterBandExperimenterBuilder.build()); MeterBand meterBandItem = experimenterCaseBuilder.build(); BandsBuilder bandsB = new BandsBuilder(); bandsB.setMeterBand(meterBandItem); // Bands list bands.add(bandsB.build()); } else { logBandTypeMissing(MeterBandType.OFPMBTEXPERIMENTER); } } } else { LOG.error("Invalid meter band data found."); } } } private static void logBandTypeMissing(final MeterBandType meterBandType) { LOG.error("BandType: {} No Band Data found", meterBandType); } @Override public Collection<Class<? extends DataContainer>> getTypes() { return TYPES; } @Override public MeterModInputBuilder convert(Meter source, VersionConvertorData data) { MeterModInputBuilder meterModInputBuilder = new MeterModInputBuilder(); List<Bands> bands = new ArrayList<>(); if (source instanceof AddMeterInput) { meterModInputBuilder.setCommand(MeterModCommand.OFPMCADD); } else if (source instanceof RemoveMeterInput) { meterModInputBuilder.setCommand(MeterModCommand.OFPMCDELETE); } else if (source instanceof UpdatedMeter) { meterModInputBuilder.setCommand(MeterModCommand.OFPMCMODIFY); } meterModInputBuilder.setMeterId(new MeterId(source.getMeterId().getValue())); if (null != source.getFlags()) { meterModInputBuilder.setFlags(new MeterFlags(source.getFlags().isMeterBurst(), source.getFlags() .isMeterKbps(), source.getFlags().isMeterPktps(), source.getFlags().isMeterStats())); } else { /* * As per 0F1.3.1,The rate field indicates the rate value above * which the corresponding band may apply to packets (see 5.7.1). * The rate value is in kilobit per seconds, unless the flags eld * includes OFPMF_PKTPS, in which case the rate is in packets per * seconds. */ meterModInputBuilder.setFlags(new MeterFlags(false, false, true, false)); } if (source.getMeterBandHeaders() != null) { getBandsFromSAL(source.getMeterBandHeaders(), bands); meterModInputBuilder.setBands(bands); } else { LOG.error("For this meter Id" + source.getMeterId().getValue() + ",no associated band data found!"); } meterModInputBuilder.setVersion(data.getVersion()); return meterModInputBuilder; } }