import java.util.ArrayList;
import java.util.List;
-import org.opendaylight.openflowjava.protocol.impl.deserialization.OFDeserializer;
-import org.opendaylight.openflowjava.protocol.impl.util.ActionsDeserializer;
-import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;
-import org.opendaylight.openflowjava.protocol.impl.util.EncodeConstants;
-import org.opendaylight.openflowjava.protocol.impl.util.InstructionsDeserializer;
-import org.opendaylight.openflowjava.protocol.impl.util.MatchDeserializer;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.openflowjava.protocol.impl.util.CodeKeyMaker;
+import org.opendaylight.openflowjava.protocol.impl.util.CodeKeyMakerFactory;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.ListDeserializer;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionRelatedTableFeatureProperty;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionRelatedTableFeaturePropertyBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterRelatedTableFeatureProperty;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterRelatedTableFeaturePropertyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.InstructionRelatedTableFeatureProperty;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.InstructionRelatedTableFeaturePropertyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NextTableRelatedTableFeatureProperty;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmRelatedTableFeaturePropertyBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.table.features.properties.container.table.feature.properties.NextTableIds;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.table.features.properties.container.table.feature.properties.NextTableIdsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ActionType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.GroupCapabilities;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableConfig;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.grouping.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.grouping.MatchEntries;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.BucketsListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.buckets.grouping.BucketsListBuilder;
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.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.MultipartReplyTableFeaturesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.multipart.reply.table.features.TableFeatures;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table.features._case.multipart.reply.table.features.TableFeaturesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.TableFeatureProperties;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.TableFeaturePropertiesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeatureProperties;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.grouping.TableFeaturePropertiesBuilder;
/**
* Translates MultipartReply messages
* @author timotej.kubas
* @author michal.polkorab
*/
-public class MultipartReplyMessageFactory implements OFDeserializer<MultipartReplyMessage> {
+public class MultipartReplyMessageFactory implements OFDeserializer<MultipartReplyMessage>,
+ DeserializerRegistryInjector {
private static final byte PADDING_IN_MULTIPART_REPLY_HEADER = 4;
private static final int DESC_STR_LEN = 256;
private static final byte PADDING_IN_BUCKETS_HEADER = 4;
private static final byte GROUP_DESC_HEADER_LENGTH = 8;
private static final byte BUCKETS_HEADER_LENGTH = 16;
-
-
- private static MultipartReplyMessageFactory instance;
-
- private MultipartReplyMessageFactory() {
- // singleton
- }
-
- /**
- * @return singleton factory
- */
- public static synchronized MultipartReplyMessageFactory getInstance() {
- if (instance == null){
- instance = new MultipartReplyMessageFactory();
- }
- return instance;
- }
+ private DeserializerRegistry registry;
@Override
- public MultipartReplyMessage bufferToMessage(ByteBuf rawMessage, short version) {
+ public MultipartReplyMessage deserialize(ByteBuf rawMessage) {
MultipartReplyMessageBuilder builder = new MultipartReplyMessageBuilder();
- builder.setVersion(version);
+ builder.setVersion((short) EncodeConstants.OF13_VERSION_ID);
builder.setXid(rawMessage.readUnsignedInt());
int type = rawMessage.readUnsignedShort();
builder.setType(MultipartType.forValue(type));
return caseBuilder.build();
}
- private static MultipartReplyFlowCase setFlow(ByteBuf input) {
+ private MultipartReplyFlowCase setFlow(ByteBuf input) {
MultipartReplyFlowCaseBuilder caseBuilder = new MultipartReplyFlowCaseBuilder();
MultipartReplyFlowBuilder flowBuilder = new MultipartReplyFlowBuilder();
List<FlowStats> flowStatsList = new ArrayList<>();
while (input.readableBytes() > 0) {
FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder();
- input.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
- flowStatsBuilder.setTableId(input.readUnsignedByte());
- input.skipBytes(PADDING_IN_FLOW_STATS_HEADER_01);
- flowStatsBuilder.setDurationSec(input.readUnsignedInt());
- flowStatsBuilder.setDurationNsec(input.readUnsignedInt());
- flowStatsBuilder.setPriority(input.readUnsignedShort());
- flowStatsBuilder.setIdleTimeout(input.readUnsignedShort());
- flowStatsBuilder.setHardTimeout(input.readUnsignedShort());
- flowStatsBuilder.setFlags(createFlowModFlagsFromBitmap(input.readShort()));
- input.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
+ int flowRecordLength = input.readUnsignedShort();
+ ByteBuf subInput = input.readSlice(flowRecordLength - EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ flowStatsBuilder.setTableId(subInput.readUnsignedByte());
+ subInput.skipBytes(PADDING_IN_FLOW_STATS_HEADER_01);
+ flowStatsBuilder.setDurationSec(subInput.readUnsignedInt());
+ flowStatsBuilder.setDurationNsec(subInput.readUnsignedInt());
+ flowStatsBuilder.setPriority(subInput.readUnsignedShort());
+ flowStatsBuilder.setIdleTimeout(subInput.readUnsignedShort());
+ flowStatsBuilder.setHardTimeout(subInput.readUnsignedShort());
+ flowStatsBuilder.setFlags(createFlowModFlagsFromBitmap(subInput.readUnsignedShort()));
+ subInput.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
byte[] cookie = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
- input.readBytes(cookie);
+ subInput.readBytes(cookie);
flowStatsBuilder.setCookie(new BigInteger(1, cookie));
byte[] packetCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
- input.readBytes(packetCount);
+ subInput.readBytes(packetCount);
flowStatsBuilder.setPacketCount(new BigInteger(1, packetCount));
byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
- input.readBytes(byteCount);
+ subInput.readBytes(byteCount);
flowStatsBuilder.setByteCount(new BigInteger(1, byteCount));
- flowStatsBuilder.setMatch(MatchDeserializer.createMatch(input));
- flowStatsBuilder.setInstructions(InstructionsDeserializer.createInstructions(input, input.readableBytes()));
+ OFDeserializer<Match> matchDeserializer = registry.getDeserializer(new MessageCodeKey(
+ EncodeConstants.OF13_VERSION_ID, EncodeConstants.EMPTY_VALUE, Match.class));
+ flowStatsBuilder.setMatch(matchDeserializer.deserialize(subInput));
+ CodeKeyMaker keyMaker = CodeKeyMakerFactory
+ .createInstructionsKeyMaker(EncodeConstants.OF13_VERSION_ID);
+ List<Instruction> instructions = ListDeserializer.deserializeList(
+ EncodeConstants.OF13_VERSION_ID, subInput.readableBytes(), subInput, keyMaker, registry);
+ flowStatsBuilder.setInstruction(instructions);
flowStatsList.add(flowStatsBuilder.build());
}
flowBuilder.setFlowStats(flowStatsList);
return caseBuilder.build();
}
- private static FlowModFlags createFlowModFlagsFromBitmap(short input){
+ private static FlowModFlags createFlowModFlagsFromBitmap(int input){
final Boolean _oFPFFSENDFLOWREM = (input & (1 << 0)) != 0;
final Boolean _oFPFFCHECKOVERLAP = (input & (1 << 1)) != 0;
final Boolean _oFPFFRESETCOUNTS = (input & (1 << 2)) != 0;
return caseBuilder.build();
}
- private static MultipartReplyTableFeaturesCase setTableFeatures(ByteBuf input) {
+ private MultipartReplyTableFeaturesCase setTableFeatures(ByteBuf input) {
MultipartReplyTableFeaturesCaseBuilder caseBuilder = new MultipartReplyTableFeaturesCaseBuilder();
MultipartReplyTableFeaturesBuilder builder = new MultipartReplyTableFeaturesBuilder();
List<TableFeatures> features = new ArrayList<>();
return new TableConfig(deprecated);
}
- private static List<TableFeatureProperties> createTableFeaturesProperties(ByteBuf input, int length) {
+ private List<TableFeatureProperties> createTableFeaturesProperties(ByteBuf input, int length) {
List<TableFeatureProperties> properties = new ArrayList<>();
int tableFeaturesLength = length;
while (tableFeaturesLength > 0) {
if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONS)
|| type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS)) {
InstructionRelatedTableFeaturePropertyBuilder insBuilder = new InstructionRelatedTableFeaturePropertyBuilder();
- insBuilder.setInstructions(InstructionsDeserializer.createInstructionIds(input, propertyLength - COMMON_PROPERTY_LENGTH));
+ CodeKeyMaker keyMaker = CodeKeyMakerFactory.createInstructionsKeyMaker(EncodeConstants.OF13_VERSION_ID);
+ List<Instruction> instructions = ListDeserializer.deserializeHeaders(EncodeConstants.OF13_VERSION_ID,
+ propertyLength - COMMON_PROPERTY_LENGTH, input, keyMaker, registry);
+ insBuilder.setInstruction(instructions);
builder.addAugmentation(InstructionRelatedTableFeatureProperty.class, insBuilder.build());
} else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLES)
|| type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS)) {
|| type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONS)
|| type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS)) {
ActionRelatedTableFeaturePropertyBuilder actionBuilder = new ActionRelatedTableFeaturePropertyBuilder();
- actionBuilder.setActionsList(ActionsDeserializer.createActionIds(input, propertyLength - COMMON_PROPERTY_LENGTH));
+ CodeKeyMaker keyMaker = CodeKeyMakerFactory.createActionsKeyMaker(EncodeConstants.OF13_VERSION_ID);
+ List<Action> actions = ListDeserializer.deserializeHeaders(EncodeConstants.OF13_VERSION_ID,
+ propertyLength - COMMON_PROPERTY_LENGTH, input, keyMaker, registry);
+ actionBuilder.setAction(actions);
builder.addAugmentation(ActionRelatedTableFeatureProperty.class, actionBuilder.build());
} else if (type.equals(TableFeaturesPropType.OFPTFPTMATCH)
|| type.equals(TableFeaturesPropType.OFPTFPTWILDCARDS)
|| type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD)
|| type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS)) {
OxmRelatedTableFeaturePropertyBuilder oxmBuilder = new OxmRelatedTableFeaturePropertyBuilder();
- oxmBuilder.setMatchEntries(MatchDeserializer.createMatchIds(input, propertyLength - COMMON_PROPERTY_LENGTH));
+ CodeKeyMaker keyMaker = CodeKeyMakerFactory
+ .createMatchEntriesKeyMaker(EncodeConstants.OF13_VERSION_ID);
+ List<MatchEntries> entries = ListDeserializer.deserializeHeaders(EncodeConstants.OF13_VERSION_ID,
+ propertyLength - COMMON_PROPERTY_LENGTH, input, keyMaker, registry);
+ oxmBuilder.setMatchEntries(entries);
builder.addAugmentation(OxmRelatedTableFeatureProperty.class, oxmBuilder.build());
} else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTER)
|| type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTERMISS)) {
- ExperimenterRelatedTableFeaturePropertyBuilder expBuilder = new ExperimenterRelatedTableFeaturePropertyBuilder();
- expBuilder.setExperimenter(input.readUnsignedInt());
- expBuilder.setExpType(input.readUnsignedInt());
- int dataLength = propertyLength - COMMON_PROPERTY_LENGTH - 2 * EncodeConstants.SIZE_OF_INT_IN_BYTES;
- if (dataLength > 0) {
- byte[] data = new byte[dataLength];
- input.readBytes(data);
- expBuilder.setData(data);
- }
- builder.addAugmentation(ExperimenterRelatedTableFeatureProperty.class, expBuilder.build());
+ // return index to property start, so that the experimenter properties are deserialized
+ // correctly - as whole ofp_table_feature_prop_experimenter property
+ input.readerIndex(input.readerIndex() - 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ OFDeserializer<TableFeatureProperties> propDeserializer = registry.getDeserializer(
+ new MessageCodeKey(EncodeConstants.OF13_VERSION_ID,
+ type.getIntValue(), TableFeatureProperties.class));
+ TableFeatureProperties expProp = propDeserializer.deserialize(input);
+ properties.add(expProp);
+ continue;
}
if (paddingRemainder != 0) {
input.skipBytes(EncodeConstants.PADDING - paddingRemainder);
bandsBuilder.setMeterBand(bandDscpRemarkCaseBuilder.build());
break;
case 0xFFFF:
- MeterBandExperimenterCaseBuilder bandExperimenterCaseBuilder = new MeterBandExperimenterCaseBuilder();
+ MeterBandExperimenterCaseBuilder bandExperimenterCaseBuilder = new MeterBandExperimenterCaseBuilder();
MeterBandExperimenterBuilder bandExperimenterBuilder = new MeterBandExperimenterBuilder();
- bandExperimenterBuilder.setType(MeterBandType.forValue(bandType));
- actualLength += input.readUnsignedShort();
- bandExperimenterBuilder.setRate(input.readUnsignedInt());
- bandExperimenterBuilder.setBurstSize(input.readUnsignedInt());
- bandExperimenterBuilder.setExperimenter(input.readUnsignedInt());
- bandExperimenterCaseBuilder.setMeterBandExperimenter(bandExperimenterBuilder.build());
+ // TODO - implement lookup into registry
+// bandExperimenterBuilder.setType(MeterBandType.forValue(bandType));
+// actualLength += input.readUnsignedShort();
+// bandExperimenterBuilder.setRate(input.readUnsignedInt());
+// bandExperimenterBuilder.setBurstSize(input.readUnsignedInt());
+// bandExperimenterBuilder.setExperimenter(input.readUnsignedInt());
+// bandExperimenterCaseBuilder.setMeterBandExperimenter(bandExperimenterBuilder.build());
bandsBuilder.setMeterBand(bandExperimenterCaseBuilder.build());
break;
default:
}
private static MultipartReplyExperimenterCase setExperimenter(ByteBuf input) {
+ // TODO - implement lookup into registry
MultipartReplyExperimenterCaseBuilder caseBuilder = new MultipartReplyExperimenterCaseBuilder();
MultipartReplyExperimenterBuilder builder = new MultipartReplyExperimenterBuilder();
- builder.setExperimenter(input.readUnsignedInt());
- builder.setExpType(input.readUnsignedInt());
- byte[] data = new byte[input.readableBytes()];
- input.readBytes(data);
- builder.setData(data);
+// builder.setExperimenter(input.readUnsignedInt());
+// builder.setExpType(input.readUnsignedInt());
+// byte[] data = new byte[input.readableBytes()];
+// input.readBytes(data);
+// builder.setData(data);
caseBuilder.setMultipartReplyExperimenter(builder.build());
return caseBuilder.build();
}
return new GroupTypes(OFPGT_ALL, OFPGT_FF, OFPGT_INDIRECT, OFPGT_SELECT);
}
- private static MultipartReplyGroupDescCase setGroupDesc(ByteBuf input) {
+ private MultipartReplyGroupDescCase setGroupDesc(ByteBuf input) {
MultipartReplyGroupDescCaseBuilder caseBuilder = new MultipartReplyGroupDescCaseBuilder();
MultipartReplyGroupDescBuilder builder = new MultipartReplyGroupDescBuilder();
List<GroupDesc> groupDescsList = new ArrayList<>();
bucketsBuilder.setWatchPort(new PortNumber(input.readUnsignedInt()));
bucketsBuilder.setWatchGroup(input.readUnsignedInt());
input.skipBytes(PADDING_IN_BUCKETS_HEADER);
- List<ActionsList> actionsList = ActionsDeserializer
- .createActionsList(input, bucketsLength - BUCKETS_HEADER_LENGTH);
- bucketsBuilder.setActionsList(actionsList);
+ CodeKeyMaker keyMaker = CodeKeyMakerFactory.createActionsKeyMaker(EncodeConstants.OF13_VERSION_ID);
+ List<Action> actions = ListDeserializer.deserializeList(EncodeConstants.OF13_VERSION_ID,
+ bucketsLength - BUCKETS_HEADER_LENGTH, input, keyMaker, registry);
+ bucketsBuilder.setAction(actions);
bucketsList.add(bucketsBuilder.build());
actualLength += bucketsLength;
}
caseBuilder.setMultipartReplyGroupDesc(builder.build());
return caseBuilder.build();
}
-
+
+ @Override
+ public void injectDeserializerRegistry(
+ DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
+ }
}