--- /dev/null
+/* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */\r
+package org.opendaylight.openflowjava.protocol.impl.serialization.factories;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.opendaylight.openflowjava.protocol.impl.serialization.OFSerializer;\r
+import org.opendaylight.openflowjava.protocol.impl.util.ActionsSerializer;\r
+import org.opendaylight.openflowjava.protocol.impl.util.ByteBufUtils;\r
+import org.opendaylight.openflowjava.protocol.impl.util.InstructionsSerializer;\r
+import org.opendaylight.openflowjava.protocol.impl.util.MatchSerializer;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.InstructionRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.NextTableRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OxmRelatedTableFeatureProperty;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.table.features.properties.container.table.feature.properties.NextTableIds;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableConfig;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.TableFeaturesPropType;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SendMultipartRequestMessageInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.MultipartRequestBody;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestAggregate;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestDesc;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestExperimenter;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestFlow;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestGroup;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeter;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestMeterConfig;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestPortStats;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestQueue;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.MultipartRequestTableFeatures;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.request.multipart.request.body.multipart.request.table.features.TableFeatures;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.table.features.properties.TableFeatureProperties;\r
+\r
+/**\r
+ * Translates MultipartRequest messages\r
+ * @author timotej.kubas\r
+ * @author michal.polkorab\r
+ */\r
+public class SendMultipartRequestMessageInputFactory implements OFSerializer<SendMultipartRequestMessageInput> {\r
+ private static final byte MESSAGE_TYPE = 18;\r
+ private static final int MESSAGE_LENGTH = 16;\r
+ private static final byte PADDING_IN_MULTIPART_REQUEST_MESSAGE = 4;\r
+ private static final byte TABLE_FEAT_HEADER_LENGTH = 4;\r
+ private static SendMultipartRequestMessageInputFactory instance;\r
+\r
+ private SendMultipartRequestMessageInputFactory() {\r
+ // singleton\r
+ }\r
+\r
+ /**\r
+ * @return singleton factory\r
+ */\r
+ public static synchronized SendMultipartRequestMessageInputFactory getInstance() {\r
+ if (instance == null) {\r
+ instance = new SendMultipartRequestMessageInputFactory();\r
+ }\r
+ return instance;\r
+ }\r
+\r
+ @Override\r
+ public void messageToBuffer(short version, ByteBuf out,\r
+ SendMultipartRequestMessageInput message) {\r
+ ByteBufUtils.writeOFHeader(instance, message, out);\r
+ out.writeShort(message.getType().getIntValue());\r
+ out.writeShort(createMultipartRequestFlagsBitmask(message.getFlags()));\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_MESSAGE, out);\r
+\r
+ if (message.getMultipartRequestBody() instanceof MultipartRequestDesc ){\r
+ encodeDescBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestFlow) {\r
+ encodeFlowBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestAggregate) {\r
+ encodeAggregateBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestPortStats) {\r
+ encodePortStatsBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestQueue) {\r
+ encodeQueueBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestGroup) {\r
+ encodeGroupStatsBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeter) {\r
+ encodeMeterBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestMeterConfig) {\r
+ encodeMeterConfigBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestTableFeatures) {\r
+ encodeTableFeaturesBody(message.getMultipartRequestBody(), out);\r
+ } else if (message.getMultipartRequestBody() instanceof MultipartRequestExperimenter) {\r
+ encodeExperimenterBody(message.getMultipartRequestBody(), out);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public int computeLength(SendMultipartRequestMessageInput message) {\r
+ return MESSAGE_LENGTH + computeBodyLength(message);\r
+ }\r
+ @Override\r
+ public byte getMessageType() {\r
+ return MESSAGE_TYPE;\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @param message\r
+ * @return length of SendMultipartRequestMessageInput\r
+ */\r
+ public int computeBodyLength(SendMultipartRequestMessageInput message) {\r
+ int length = 0;\r
+ MultipartType type = message.getType();\r
+ if (type.equals(MultipartType.OFPMPFLOW)) {\r
+ final byte FLOW_BODY_LENGTH = 32;\r
+ MultipartRequestFlow body = (MultipartRequestFlow) message.getMultipartRequestBody();\r
+ length += FLOW_BODY_LENGTH + MatchSerializer.computeMatchLength(body.getMatch());\r
+ } else if (type.equals(MultipartType.OFPMPAGGREGATE)) {\r
+ final byte AGGREGATE_BODY_LENGTH = 32;\r
+ MultipartRequestAggregate body = (MultipartRequestAggregate) message.getMultipartRequestBody();\r
+ length += AGGREGATE_BODY_LENGTH + MatchSerializer.computeMatchLength(body.getMatch());\r
+ } else if (type.equals(MultipartType.OFPMPPORTSTATS)) {\r
+ final byte PORT_STATS_BODY_LENGTH = 8;\r
+ length += PORT_STATS_BODY_LENGTH;\r
+ } else if (type.equals(MultipartType.OFPMPQUEUE)) {\r
+ final byte QUEUE_BODY_LENGTH = 8;\r
+ length += QUEUE_BODY_LENGTH;\r
+ } else if (type.equals(MultipartType.OFPMPGROUP)) {\r
+ final byte GROUP_BODY_LENGTH = 8;\r
+ length += GROUP_BODY_LENGTH;\r
+ } else if (type.equals(MultipartType.OFPMPMETER)) {\r
+ final byte METER_BODY_LENGTH = 8;\r
+ length += METER_BODY_LENGTH;\r
+ } else if (type.equals(MultipartType.OFPMPMETERCONFIG)) {\r
+ final byte METER_CONFIG_BODY_LENGTH = 8;\r
+ length += METER_CONFIG_BODY_LENGTH;\r
+ } else if (type.equals(MultipartType.OFPMPTABLEFEATURES)) {\r
+ MultipartRequestTableFeatures body = (MultipartRequestTableFeatures) message.getMultipartRequestBody();\r
+ length += computeTableFeaturesLength(body);\r
+ } else if (type.equals(MultipartType.OFPMPEXPERIMENTER)) {\r
+ final byte EXPERIMENTER_BODY_LENGTH = 8;\r
+ MultipartRequestExperimenter body = (MultipartRequestExperimenter) message.getMultipartRequestBody();\r
+ length += EXPERIMENTER_BODY_LENGTH;\r
+ if (body.getData() != null) {\r
+ length += body.getData().length;\r
+ }\r
+ }\r
+ return length;\r
+ }\r
+\r
+ private static int computeTableFeaturesLength(MultipartRequestTableFeatures body) {\r
+ final byte TABLE_FEATURES_LENGTH = 64;\r
+ final byte STRUCTURE_HEADER_LENGTH = 4;\r
+ int length = 0;\r
+ if (body != null) {\r
+ List<TableFeatures> tableFeatures = body.getTableFeatures();\r
+ for (TableFeatures feature : tableFeatures) {\r
+ length += TABLE_FEATURES_LENGTH;\r
+ List<TableFeatureProperties> featureProperties = feature.getTableFeatureProperties();\r
+ if (featureProperties != null) {\r
+ for (TableFeatureProperties featProp : featureProperties) {\r
+ length += TABLE_FEAT_HEADER_LENGTH;\r
+ if (featProp.getAugmentation(InstructionRelatedTableFeatureProperty.class) != null) {\r
+ InstructionRelatedTableFeatureProperty property =\r
+ featProp.getAugmentation(InstructionRelatedTableFeatureProperty.class);\r
+ length += property.getInstructions().size() * STRUCTURE_HEADER_LENGTH;\r
+ } else if (featProp.getAugmentation(NextTableRelatedTableFeatureProperty.class) != null) {\r
+ NextTableRelatedTableFeatureProperty property =\r
+ featProp.getAugmentation(NextTableRelatedTableFeatureProperty.class);\r
+ length += property.getNextTableIds().size();\r
+ } else if (featProp.getAugmentation(ActionRelatedTableFeatureProperty.class) != null) {\r
+ ActionRelatedTableFeatureProperty property =\r
+ featProp.getAugmentation(ActionRelatedTableFeatureProperty.class);\r
+ length += property.getActionsList().size() * STRUCTURE_HEADER_LENGTH;\r
+ } else if (featProp.getAugmentation(OxmRelatedTableFeatureProperty.class) != null) {\r
+ OxmRelatedTableFeatureProperty property =\r
+ featProp.getAugmentation(OxmRelatedTableFeatureProperty.class);\r
+ length += property.getMatchEntries().size() * STRUCTURE_HEADER_LENGTH;\r
+ } else if (featProp.getAugmentation(ExperimenterRelatedTableFeatureProperty.class) != null) {\r
+ ExperimenterRelatedTableFeatureProperty property =\r
+ featProp.getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
+ length += 2 * (Integer.SIZE / Byte.SIZE);\r
+ if (property.getData() != null) {\r
+ length += property.getData().length;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return length;\r
+ }\r
+\r
+ private static int createMultipartRequestFlagsBitmask(MultipartRequestFlags flags) {\r
+ int multipartRequestFlagsBitmask = 0;\r
+ Map<Integer, Boolean> multipartRequestFlagsMap = new HashMap<>();\r
+ multipartRequestFlagsMap.put(0, flags.isOFPMPFREQMORE());\r
+\r
+ multipartRequestFlagsBitmask = ByteBufUtils.fillBitMaskFromMap(multipartRequestFlagsMap);\r
+ return multipartRequestFlagsBitmask;\r
+ }\r
+\r
+ private void encodeDescBody(MultipartRequestBody multipartRequestBody,\r
+ ByteBuf output) {\r
+ // The body of MultiPartRequestDesc is empty\r
+\r
+ }\r
+\r
+ private static void encodeFlowBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_01 = 3;\r
+ final byte PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_02 = 4;\r
+ MultipartRequestFlow flow = (MultipartRequestFlow) multipartRequestBody;\r
+ output.writeByte(flow.getTableId().byteValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_01, output);\r
+ output.writeInt(flow.getOutPort().intValue());\r
+ output.writeInt(flow.getOutGroup().intValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_FLOW_BODY_02, output);\r
+ output.writeLong(flow.getCookie().longValue());\r
+ output.writeLong(flow.getCookieMask().longValue());\r
+ MatchSerializer.encodeMatch(flow.getMatch(), output);\r
+ }\r
+\r
+ private static void encodeAggregateBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_01 = 3;\r
+ final byte PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_02 = 4;\r
+ MultipartRequestAggregate aggregate = (MultipartRequestAggregate) multipartRequestBody;\r
+ output.writeByte(aggregate.getTableId().byteValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_01, output);\r
+ output.writeInt(aggregate.getOutPort().intValue());\r
+ output.writeInt(aggregate.getOutGroup().intValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_AGREGGATE_BODY_02, output);\r
+ output.writeLong(aggregate.getCookie().longValue());\r
+ output.writeLong(aggregate.getCookieMask().longValue());\r
+ MatchSerializer.encodeMatch(aggregate.getMatch(), output);\r
+ }\r
+\r
+ private static void encodePortStatsBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_PORTSTATS_BODY = 4;\r
+ MultipartRequestPortStats portstats = (MultipartRequestPortStats) multipartRequestBody;\r
+ output.writeInt(portstats.getPortNo().intValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_PORTSTATS_BODY, output);\r
+ }\r
+\r
+ private static void encodeQueueBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ MultipartRequestQueue queue = (MultipartRequestQueue) multipartRequestBody;\r
+ output.writeInt(queue.getPortNo().intValue());\r
+ output.writeInt(queue.getQueueId().intValue());\r
+ }\r
+\r
+ private static void encodeGroupStatsBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_GROUP_BODY = 4;\r
+ MultipartRequestGroup groupStats = (MultipartRequestGroup) multipartRequestBody;\r
+ output.writeInt(groupStats.getGroupId().intValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_GROUP_BODY, output);\r
+ }\r
+\r
+ private static void encodeMeterBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_METER_BODY = 4;\r
+ MultipartRequestMeter meter = (MultipartRequestMeter) multipartRequestBody;\r
+ output.writeInt(meter.getMeterId().intValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_METER_BODY, output);\r
+ }\r
+\r
+ private static void encodeMeterConfigBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_METER_CONFIG_BODY = 4;\r
+ MultipartRequestMeterConfig meterConfig = (MultipartRequestMeterConfig) multipartRequestBody;\r
+ output.writeInt(meterConfig.getMeterId().intValue());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_METER_CONFIG_BODY, output);\r
+ }\r
+\r
+ private static void encodeExperimenterBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ MultipartRequestExperimenter experimenter = (MultipartRequestExperimenter) multipartRequestBody;\r
+ output.writeInt(experimenter.getExperimenter().intValue());\r
+ output.writeInt(experimenter.getExpType().intValue());\r
+ byte[] data = experimenter.getData();\r
+ if (data != null) {\r
+ output.writeBytes(data);\r
+ }\r
+ }\r
+\r
+ private static void encodeTableFeaturesBody(MultipartRequestBody multipartRequestBody, ByteBuf output) {\r
+ if (multipartRequestBody != null) {\r
+ MultipartRequestTableFeatures tableFeatures = (MultipartRequestTableFeatures) multipartRequestBody;\r
+ for (TableFeatures currTableFeature : tableFeatures.getTableFeatures()) {\r
+ final byte PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY = 5;\r
+ output.writeByte(currTableFeature.getTableId());\r
+ ByteBufUtils.padBuffer(PADDING_IN_MULTIPART_REQUEST_TABLE_FEATURES_BODY, output);\r
+ output.writeBytes(currTableFeature.getName().getBytes());\r
+ ByteBufUtils.padBuffer((32 - currTableFeature.getName().getBytes().length), output);\r
+ output.writeLong(currTableFeature.getMetadataMatch().longValue());\r
+ output.writeLong(currTableFeature.getMetadataWrite().longValue());\r
+ output.writeInt(createTableConfigBitmask(currTableFeature.getConfig()));\r
+ output.writeInt(currTableFeature.getMaxEntries().intValue());\r
+ writeTableFeatureProperties(output, currTableFeature.getTableFeatureProperties());\r
+ }\r
+ }\r
+ }\r
+\r
+ private static void writeTableFeatureProperties(ByteBuf output, List<TableFeatureProperties> props) {\r
+ if (props != null) {\r
+ for (TableFeatureProperties property : props) {\r
+ TableFeaturesPropType type = property.getType();\r
+ if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONS)) {\r
+ final byte INSTRUCTIONS_CODE = 0;\r
+ writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTINSTRUCTIONSMISS)) {\r
+ final byte INSTRUCTIONS_MISS_CODE = 1;\r
+ writeInstructionRelatedTableProperty(output, property, INSTRUCTIONS_MISS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLES)) {\r
+ final byte NEXT_TABLE_CODE = 2;\r
+ writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTNEXTTABLESMISS)) {\r
+ final byte NEXT_TABLE_MISS_CODE = 3;\r
+ writeNextTableRelatedTableProperty(output, property, NEXT_TABLE_MISS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONS)) {\r
+ final byte WRITE_ACTIONS_CODE = 4;\r
+ writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITEACTIONSMISS)) {\r
+ final byte WRITE_ACTIONS_MISS_CODE = 5;\r
+ writeActionsRelatedTableProperty(output, property, WRITE_ACTIONS_MISS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONS)) {\r
+ final byte APPLY_ACTIONS_CODE = 6;\r
+ writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYACTIONSMISS)) {\r
+ final byte APPLY_ACTIONS_MISS_CODE = 7;\r
+ writeActionsRelatedTableProperty(output, property, APPLY_ACTIONS_MISS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTMATCH)) {\r
+ final byte MATCH_CODE = 8;\r
+ writeOxmRelatedTableProperty(output, property, MATCH_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTWILDCARDS)) {\r
+ final byte WILDCARDS_CODE = 10;\r
+ writeOxmRelatedTableProperty(output, property, WILDCARDS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELD)) {\r
+ final byte WRITE_SETFIELD_CODE = 12;\r
+ writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTWRITESETFIELDMISS)) {\r
+ final byte WRITE_SETFIELD_MISS_CODE = 13;\r
+ writeOxmRelatedTableProperty(output, property, WRITE_SETFIELD_MISS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELD)) {\r
+ final byte APPLY_SETFIELD_CODE = 14;\r
+ writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTAPPLYSETFIELDMISS)) {\r
+ final byte APPLY_SETFIELD_MISS_CODE = 15;\r
+ writeOxmRelatedTableProperty(output, property, APPLY_SETFIELD_MISS_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTER)) {\r
+ final int EXPERIMENTER_CODE = 65534; // 0xFFFE\r
+ writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_CODE);\r
+ } else if (type.equals(TableFeaturesPropType.OFPTFPTEXPERIMENTERMISS)) {\r
+ final int EXPERIMENTER_MISS_CODE = 65535; // 0xFFFF\r
+ writeExperimenterRelatedTableProperty(output, property, EXPERIMENTER_MISS_CODE);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private static void writeInstructionRelatedTableProperty(ByteBuf output,\r
+ TableFeatureProperties property, byte code) {\r
+ output.writeShort(code);\r
+ List<Instructions> instructions = property.\r
+ getAugmentation(InstructionRelatedTableFeatureProperty.class).getInstructions();\r
+ int length = TABLE_FEAT_HEADER_LENGTH;\r
+ if (instructions != null) {\r
+ output.writeShort(InstructionsSerializer.computeInstructionsLength(instructions)\r
+ + TABLE_FEAT_HEADER_LENGTH);\r
+ InstructionsSerializer.encodeInstructions(instructions, output);\r
+ } else {\r
+ output.writeShort(length);\r
+ }\r
+ }\r
+\r
+ private static void writeNextTableRelatedTableProperty(ByteBuf output,\r
+ TableFeatureProperties property, byte code) {\r
+ output.writeShort(code);\r
+ List<NextTableIds> nextTableIds = property.\r
+ getAugmentation(NextTableRelatedTableFeatureProperty.class).getNextTableIds();\r
+ int length = TABLE_FEAT_HEADER_LENGTH;\r
+ if (nextTableIds != null) {\r
+ output.writeShort(length + nextTableIds.size());\r
+ for (NextTableIds next : nextTableIds) {\r
+ output.writeByte(next.getTableId());\r
+ }\r
+ } else {\r
+ output.writeShort(length);\r
+ }\r
+ }\r
+\r
+ private static void writeActionsRelatedTableProperty(ByteBuf output,\r
+ TableFeatureProperties property, byte code) {\r
+ output.writeShort(code);\r
+ List<ActionsList> actions = property.\r
+ getAugmentation(ActionRelatedTableFeatureProperty.class).getActionsList();\r
+ int length = TABLE_FEAT_HEADER_LENGTH;\r
+ if (actions != null) {\r
+ output.writeShort(ActionsSerializer.computeLengthOfActions(actions)\r
+ + TABLE_FEAT_HEADER_LENGTH);\r
+ ActionsSerializer.encodeActions(actions, output);\r
+ } else {\r
+ output.writeShort(length);\r
+ }\r
+ }\r
+\r
+ private static void writeOxmRelatedTableProperty(ByteBuf output,\r
+ TableFeatureProperties property, byte code) {\r
+ output.writeShort(code);\r
+ List<MatchEntries> entries = property.\r
+ getAugmentation(OxmRelatedTableFeatureProperty.class).getMatchEntries();\r
+ int length = TABLE_FEAT_HEADER_LENGTH;\r
+ if (entries != null) {\r
+ output.writeShort(MatchSerializer.computeMatchEntriesLength(entries)\r
+ + TABLE_FEAT_HEADER_LENGTH);\r
+ MatchSerializer.encodeMatchEntries(entries, output);\r
+ } else {\r
+ output.writeShort(length);\r
+ }\r
+ }\r
+\r
+ private static void writeExperimenterRelatedTableProperty(ByteBuf output,\r
+ TableFeatureProperties property, int code) {\r
+ output.writeShort(code);\r
+ ExperimenterRelatedTableFeatureProperty exp = property.\r
+ getAugmentation(ExperimenterRelatedTableFeatureProperty.class);\r
+ byte[] data = exp.getData();\r
+ int length = TABLE_FEAT_HEADER_LENGTH + 2 * (Integer.SIZE / Byte.SIZE);\r
+ if (data != null) {\r
+ output.writeShort(length + data.length);\r
+ output.writeInt(exp.getExperimenter().intValue());\r
+ output.writeInt(exp.getExpType().intValue());\r
+ output.writeBytes(data);\r
+ } else {\r
+ output.writeShort(length);\r
+ output.writeInt(exp.getExperimenter().intValue());\r
+ output.writeInt(exp.getExpType().intValue());\r
+ }\r
+ }\r
+\r
+ private static int createTableConfigBitmask(TableConfig tableConfig) {\r
+ int tableConfigBitmask = 0;\r
+ Map<Integer, Boolean> tableConfigMap = new HashMap<>();\r
+ tableConfigMap.put(3, tableConfig.isOFPTCDEPRECATEDMASK());\r
+\r
+ tableConfigBitmask = ByteBufUtils.fillBitMaskFromMap(tableConfigMap);\r
+ return tableConfigBitmask;\r
+ }\r
+}\r