/*
* Copyright (c) 2015 NetIDE Consortium 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.openflowjava.protocol.impl.deserialization.factories;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
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.MeterModInput;
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.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.MeterBandExperimenterCase;
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.mod.Bands;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.meter.mod.BandsBuilder;
/**
* @author giuseppex.petralia@intel.com
*
*/
public class MeterModInputMessageFactory implements OFDeserializer<MeterModInput>, DeserializerRegistryInjector {
private DeserializerRegistry registry;
private static final byte PADDING_IN_METER_BAND_DROP_HEADER = 4;
private static final byte PADDING_IN_METER_BAND_DSCP_HEADER = 3;
@Override
public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
registry = deserializerRegistry;
}
@Override
public MeterModInput deserialize(ByteBuf rawMessage) {
MeterModInputBuilder builder = new MeterModInputBuilder();
builder.setVersion((short) EncodeConstants.OF13_VERSION_ID);
builder.setXid(rawMessage.readUnsignedInt());
builder.setCommand(MeterModCommand.forValue(rawMessage.readUnsignedShort()));
builder.setFlags(createMeterFlags(rawMessage.readUnsignedShort()));
builder.setMeterId(new MeterId(rawMessage.readUnsignedInt()));
List<Bands> bandsList = new ArrayList<>();
while (rawMessage.readableBytes() > 0) {
BandsBuilder bandsBuilder = new BandsBuilder();
int bandStartIndex = rawMessage.readerIndex();
int bandType = rawMessage.readUnsignedShort();
switch (bandType) {
case 1:
MeterBandDropCaseBuilder bandDropCaseBuilder = new MeterBandDropCaseBuilder();
MeterBandDropBuilder bandDropBuilder = new MeterBandDropBuilder();
bandDropBuilder.setType(MeterBandType.forValue(bandType));
rawMessage.readUnsignedShort();
bandDropBuilder.setRate(rawMessage.readUnsignedInt());
bandDropBuilder.setBurstSize(rawMessage.readUnsignedInt());
rawMessage.skipBytes(PADDING_IN_METER_BAND_DROP_HEADER);
bandDropCaseBuilder.setMeterBandDrop(bandDropBuilder.build());
bandsBuilder.setMeterBand(bandDropCaseBuilder.build());
break;
case 2:
MeterBandDscpRemarkCaseBuilder bandDscpRemarkCaseBuilder = new MeterBandDscpRemarkCaseBuilder();
MeterBandDscpRemarkBuilder bandDscpRemarkBuilder = new MeterBandDscpRemarkBuilder();
bandDscpRemarkBuilder.setType(MeterBandType.forValue(bandType));
rawMessage.readUnsignedShort();
bandDscpRemarkBuilder.setRate(rawMessage.readUnsignedInt());
bandDscpRemarkBuilder.setBurstSize(rawMessage.readUnsignedInt());
bandDscpRemarkBuilder.setPrecLevel(rawMessage.readUnsignedByte());
rawMessage.skipBytes(PADDING_IN_METER_BAND_DSCP_HEADER);
bandDscpRemarkCaseBuilder.setMeterBandDscpRemark(bandDscpRemarkBuilder.build());
bandsBuilder.setMeterBand(bandDscpRemarkCaseBuilder.build());
break;
case 0xFFFF:
long expId = rawMessage
.getUnsignedInt(rawMessage.readerIndex() + 2 * EncodeConstants.SIZE_OF_INT_IN_BYTES);
rawMessage.readerIndex(bandStartIndex);
OFDeserializer<MeterBandExperimenterCase> deserializer = registry
.getDeserializer(ExperimenterDeserializerKeyFactory
.createMeterBandDeserializerKey(EncodeConstants.OF13_VERSION_ID, expId));
bandsBuilder.setMeterBand(deserializer.deserialize(rawMessage));
break;
}
bandsList.add(bandsBuilder.build());
}
builder.setBands(bandsList);
return builder.build();
}
private static MeterFlags createMeterFlags(int input) {
final Boolean mfKBPS = (input & (1 << 0)) != 0;
final Boolean mfPKTPS = (input & (1 << 1)) != 0;
final Boolean mfBURST = (input & (1 << 2)) != 0;
final Boolean mfSTATS = (input & (1 << 3)) != 0;
return new MeterFlags(mfBURST, mfKBPS, mfPKTPS, mfSTATS);
}
}