package org.opendaylight.openflowjava.protocol.impl.deserialization.factories;
import io.netty.buffer.ByteBuf;
-
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
-
-import org.opendaylight.openflowjava.protocol.impl.deserialization.OFDeserializer;
-import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;
-import org.opendaylight.openflowjava.protocol.impl.util.EncodeConstants;
-import org.opendaylight.openflowjava.protocol.impl.util.OF10ActionsDeserializer;
+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.keys.MessageCodeKey;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.openflowjava.protocol.impl.util.CodeKeyMaker;
+import org.opendaylight.openflowjava.protocol.impl.util.CodeKeyMakerFactory;
+import org.opendaylight.openflowjava.protocol.impl.util.ListDeserializer;
import org.opendaylight.openflowjava.protocol.impl.util.OF10MatchDeserializer;
+import org.opendaylight.openflowjava.util.ByteBufUtils;
+import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
+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.MultipartRequestFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
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.experimenter.core.ExperimenterDataOfChoice;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
/**
* Translates StatsReply messages (OpenFlow v1.0)
+ *
* @author michal.polkorab
*/
-public class OF10StatsReplyMessageFactory implements OFDeserializer<MultipartReplyMessage> {
+public class OF10StatsReplyMessageFactory implements OFDeserializer<MultipartReplyMessage>,
+ DeserializerRegistryInjector {
private static final int DESC_STR_LEN = 256;
private static final int SERIAL_NUM_LEN = 32;
private static final byte PADDING_IN_PORT_STATS_HEADER = 6;
private static final byte PADDING_IN_QUEUE_HEADER = 2;
private static final byte LENGTH_OF_FLOW_STATS = 88;
-
- private static OF10StatsReplyMessageFactory instance;
-
- private OF10StatsReplyMessageFactory() {
- // singleton
- }
-
- /**
- * @return singleton factory
- */
- public static synchronized OF10StatsReplyMessageFactory getInstance() {
- if (instance == null){
- instance = new OF10StatsReplyMessageFactory();
- }
- return instance;
- }
+ private static final int TABLE_STATS_LENGTH = 64;
+ 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.OF10_VERSION_ID);
builder.setXid(rawMessage.readUnsignedInt());
int type = rawMessage.readUnsignedShort();
builder.setType(MultipartType.forValue(type));
builder.setFlags(new MultipartRequestFlags((rawMessage.readUnsignedShort() & 0x01) != 0));
- switch (type) {
- case 0: builder.setMultipartReplyBody(setDesc(rawMessage));
- break;
- case 1: builder.setMultipartReplyBody(setFlow(rawMessage));
- break;
- case 2: builder.setMultipartReplyBody(setAggregate(rawMessage));
- break;
- case 3: builder.setMultipartReplyBody(setTable(rawMessage));
- break;
- case 4: builder.setMultipartReplyBody(setPortStats(rawMessage));
- break;
- case 5: builder.setMultipartReplyBody(setQueue(rawMessage));
- break;
- case 0xFFFF: builder.setMultipartReplyBody(setExperimenter(rawMessage));
- break;
- default:
- break;
+ switch (MultipartType.forValue(type)) {
+ case OFPMPDESC:
+ builder.setMultipartReplyBody(setDesc(rawMessage));
+ break;
+ case OFPMPFLOW:
+ builder.setMultipartReplyBody(setFlow(rawMessage));
+ break;
+ case OFPMPAGGREGATE:
+ builder.setMultipartReplyBody(setAggregate(rawMessage));
+ break;
+ case OFPMPTABLE:
+ builder.setMultipartReplyBody(setTable(rawMessage));
+ break;
+ case OFPMPPORTSTATS:
+ builder.setMultipartReplyBody(setPortStats(rawMessage));
+ break;
+ case OFPMPQUEUE:
+ builder.setMultipartReplyBody(setQueue(rawMessage));
+ break;
+ case OFPMPEXPERIMENTER:
+ builder.setMultipartReplyBody(setExperimenter(rawMessage));
+ break;
+ default:
+ break;
}
return builder.build();
}
-
+
private static MultipartReplyDescCase setDesc(ByteBuf input) {
MultipartReplyDescCaseBuilder caseBuilder = new MultipartReplyDescCaseBuilder();
MultipartReplyDescBuilder descBuilder = new MultipartReplyDescBuilder();
caseBuilder.setMultipartReplyDesc(descBuilder.build());
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<>();
int length = input.readUnsignedShort();
flowStatsBuilder.setTableId(input.readUnsignedByte());
input.skipBytes(PADDING_IN_FLOW_STATS_HEADER);
- flowStatsBuilder.setMatchV10(OF10MatchDeserializer.createMatchV10(input));
+ OFDeserializer<MatchV10> matchDeserializer = registry.getDeserializer(
+ new MessageCodeKey(EncodeConstants.OF10_VERSION_ID, EncodeConstants.EMPTY_VALUE, MatchV10.class));
+ flowStatsBuilder.setMatchV10(matchDeserializer.deserialize(input));
flowStatsBuilder.setDurationSec(input.readUnsignedInt());
flowStatsBuilder.setDurationNsec(input.readUnsignedInt());
flowStatsBuilder.setPriority(input.readUnsignedShort());
byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
input.readBytes(byteCount);
flowStatsBuilder.setByteCount(new BigInteger(1, byteCount));
- flowStatsBuilder.setActionsList(OF10ActionsDeserializer
- .createActionsList(input, length - LENGTH_OF_FLOW_STATS));
+ CodeKeyMaker keyMaker = CodeKeyMakerFactory.createActionsKeyMaker(EncodeConstants.OF10_VERSION_ID);
+ List<Action> actions = ListDeserializer.deserializeList(EncodeConstants.OF10_VERSION_ID,
+ length - LENGTH_OF_FLOW_STATS, input, keyMaker, registry);
+ flowStatsBuilder.setAction(actions);
flowStatsList.add(flowStatsBuilder.build());
}
flowBuilder.setFlowStats(flowStatsList);
caseBuilder.setMultipartReplyFlow(flowBuilder.build());
return caseBuilder.build();
}
-
+
private static MultipartReplyAggregateCase setAggregate(ByteBuf input) {
MultipartReplyAggregateCaseBuilder caseBuilder = new MultipartReplyAggregateCaseBuilder();
MultipartReplyAggregateBuilder builder = new MultipartReplyAggregateBuilder();
caseBuilder.setMultipartReplyAggregate(builder.build());
return caseBuilder.build();
}
-
+
private static MultipartReplyTableCase setTable(ByteBuf input) {
MultipartReplyTableCaseBuilder caseBuilder = new MultipartReplyTableCaseBuilder();
MultipartReplyTableBuilder builder = new MultipartReplyTableBuilder();
List<TableStats> tableStatsList = new ArrayList<>();
- while (input.readableBytes() > 0) {
+ // TODO - replace ">= TABLE_STATS_LENGTH" with "> 0" after fix in OVS switch
+ while (input.readableBytes() >= TABLE_STATS_LENGTH) {
TableStatsBuilder tableStatsBuilder = new TableStatsBuilder();
tableStatsBuilder.setTableId(input.readUnsignedByte());
input.skipBytes(PADDING_IN_TABLE_HEADER);
tableStatsBuilder.setMatchedCount(new BigInteger(1, matchedCount));
tableStatsList.add(tableStatsBuilder.build());
}
+ input.skipBytes(input.readableBytes());
builder.setTableStats(tableStatsList);
caseBuilder.setMultipartReplyTable(builder.build());
return caseBuilder.build();
}
-
+
private static MultipartReplyPortStatsCase setPortStats(ByteBuf input) {
MultipartReplyPortStatsCaseBuilder caseBuilder = new MultipartReplyPortStatsCaseBuilder();
MultipartReplyPortStatsBuilder builder = new MultipartReplyPortStatsBuilder();
caseBuilder.setMultipartReplyPortStats(builder.build());
return caseBuilder.build();
}
-
+
private static MultipartReplyQueueCase setQueue(ByteBuf input) {
MultipartReplyQueueCaseBuilder caseBuilder = new MultipartReplyQueueCaseBuilder();
MultipartReplyQueueBuilder builder = new MultipartReplyQueueBuilder();
caseBuilder.setMultipartReplyQueue(builder.build());
return caseBuilder.build();
}
-
- private static MultipartReplyExperimenterCase setExperimenter(ByteBuf input) {
- MultipartReplyExperimenterCaseBuilder caseBuilder = new MultipartReplyExperimenterCaseBuilder();
- MultipartReplyExperimenterBuilder builder = new MultipartReplyExperimenterBuilder();
- builder.setExperimenter(input.readUnsignedInt());
- byte[] data = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
- input.readBytes(data);
- builder.setData(data);
- caseBuilder.setMultipartReplyExperimenter(builder.build());
- return caseBuilder.build();
+
+ private MultipartReplyExperimenterCase setExperimenter(ByteBuf input) {
+ final long expId = input.readUnsignedInt();
+ final OFDeserializer<ExperimenterDataOfChoice> deserializer = registry.getDeserializer(ExperimenterDeserializerKeyFactory.createMultipartReplyVendorMessageDeserializerKey(
+ EncodeConstants.OF10_VERSION_ID, expId));
+
+ final MultipartReplyExperimenterBuilder mpExperimenterBld = new MultipartReplyExperimenterBuilder()
+ .setExperimenter(new ExperimenterId(expId))
+ .setExperimenterDataOfChoice(deserializer.deserialize(input));
+ final MultipartReplyExperimenterCaseBuilder mpReplyExperimenterCaseBld = new MultipartReplyExperimenterCaseBuilder()
+ .setMultipartReplyExperimenter(mpExperimenterBld.build());
+ return mpReplyExperimenterCaseBld.build();
+ }
+
+ @Override
+ public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+ registry = deserializerRegistry;
}
}