2 * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowjava.protocol.impl.util;
11 import io.netty.buffer.ByteBuf;
13 import java.util.List;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterInstruction;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Experimenter;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Instruction;
32 * Serializes ofp_instruction (OpenFlow v 1.3) structure
33 * @author michal.polkorab
34 * @author timotej.kubas
36 public abstract class InstructionsSerializer {
38 private static final byte GOTO_TABLE_TYPE = 1;
39 private static final byte WRITE_METADATA_TYPE = 2;
40 private static final byte WRITE_ACTIONS_TYPE = 3;
41 private static final byte APPLY_ACTIONS_TYPE = 4;
42 private static final byte CLEAR_ACTIONS_TYPE = 5;
43 private static final byte METER_TYPE = 6;
44 private static final byte EXPERIMENTER_TYPE = 7;
45 private static final byte GOTO_TABLE_LENGTH = 8;
46 private static final byte WRITE_METADATA_LENGTH = 24;
47 private static final byte METER_LENGTH = 8;
48 private static final byte EXPERIMENTER_LENGTH = 8;
49 private static final byte ACTIONS_INSTRUCTION_LENGTH = 8;
50 private static final byte PADDING_IN_GOTO_TABLE = 3;
51 private static final byte PADDING_IN_WRITE_METADATA = 4;
52 private static final byte PADDING_IN_CLEAR_ACTIONS = 4;
53 private static final byte INSTRUCTION_IDS_LENGTH = 4;
54 private static final byte PADDING_IN_ACTIONS_INSTRUCTION = 4;
57 * Encodes instructions
58 * @param instructions List of instructions
59 * @param out output buffer
61 public static void encodeInstructions(List<Instructions> instructions, ByteBuf out) {
62 if (instructions != null) {
63 for (Instructions instruction : instructions) {
64 Class<? extends Instruction> type = instruction.getType();
65 if (type.isAssignableFrom(GotoTable.class)) {
66 writeTypeAndLength(out, GOTO_TABLE_TYPE, GOTO_TABLE_LENGTH);
67 out.writeByte(instruction.getAugmentation(TableIdInstruction.class).getTableId());
68 ByteBufUtils.padBuffer(PADDING_IN_GOTO_TABLE, out);
69 } else if (type.isAssignableFrom(WriteMetadata.class)) {
70 writeTypeAndLength(out, WRITE_METADATA_TYPE, WRITE_METADATA_LENGTH);
71 ByteBufUtils.padBuffer(PADDING_IN_WRITE_METADATA, out);
72 MetadataInstruction metadata = instruction.getAugmentation(MetadataInstruction.class);
73 out.writeBytes(metadata.getMetadata());
74 out.writeBytes(metadata.getMetadataMask());
75 } else if (type.isAssignableFrom(WriteActions.class)) {
76 writeActionsInstruction(out, instruction, WRITE_ACTIONS_TYPE);
77 } else if (type.isAssignableFrom(ApplyActions.class)) {
78 writeActionsInstruction(out, instruction, APPLY_ACTIONS_TYPE);
79 } else if (type.isAssignableFrom(ClearActions.class)) {
80 writeTypeAndLength(out, CLEAR_ACTIONS_TYPE, ACTIONS_INSTRUCTION_LENGTH);
81 ByteBufUtils.padBuffer(PADDING_IN_CLEAR_ACTIONS, out);
82 } else if (type.isAssignableFrom(Meter.class)) {
83 writeTypeAndLength(out, METER_TYPE, METER_LENGTH);
84 out.writeInt(instruction.getAugmentation(MeterIdInstruction.class).getMeterId().intValue());
85 } else if (type.isAssignableFrom(Experimenter.class)) {
86 ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);
87 byte[] data = experimenter.getData();
88 writeTypeAndLength(out, EXPERIMENTER_TYPE, EXPERIMENTER_LENGTH + data.length);
89 out.writeInt(experimenter.getExperimenter().intValue());
98 * Encodes instruction ids (for Multipart - TableFeatures messages)
99 * @param instructions List of instruction identifiers (without values)
100 * @param out output buffer
102 public static void encodeInstructionIds(List<Instructions> instructions, ByteBuf out) {
103 if (instructions != null) {
104 for (Instructions instruction : instructions) {
105 Class<? extends Instruction> type = instruction.getType();
106 if (type.isAssignableFrom(GotoTable.class)) {
107 writeTypeAndLength(out, GOTO_TABLE_TYPE, INSTRUCTION_IDS_LENGTH);
108 } else if (type.isAssignableFrom(WriteMetadata.class)) {
109 writeTypeAndLength(out, WRITE_METADATA_TYPE, INSTRUCTION_IDS_LENGTH);
110 } else if (type.isAssignableFrom(WriteActions.class)) {
111 writeTypeAndLength(out, WRITE_ACTIONS_TYPE, INSTRUCTION_IDS_LENGTH);
112 } else if (type.isAssignableFrom(ApplyActions.class)) {
113 writeTypeAndLength(out, APPLY_ACTIONS_TYPE, INSTRUCTION_IDS_LENGTH);
114 } else if (type.isAssignableFrom(ClearActions.class)) {
115 writeTypeAndLength(out, CLEAR_ACTIONS_TYPE, INSTRUCTION_IDS_LENGTH);
116 } else if (type.isAssignableFrom(Meter.class)) {
117 writeTypeAndLength(out, METER_TYPE, INSTRUCTION_IDS_LENGTH);
118 } else if (type.isAssignableFrom(Experimenter.class)) {
119 ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);
120 writeTypeAndLength(out, EXPERIMENTER_TYPE, EncodeConstants.EXPERIMENTER_IDS_LENGTH);
121 out.writeInt(experimenter.getExperimenter().intValue());
127 private static void writeTypeAndLength(ByteBuf out, int type, int length) {
128 out.writeShort(type);
129 out.writeShort(length);
132 private static void writeActionsInstruction(ByteBuf out,
133 Instructions instruction, int type) {
134 out.writeShort(type);
135 if (instruction.getAugmentation(ActionsInstruction.class) != null) {
136 List<ActionsList> actions = instruction.getAugmentation(ActionsInstruction.class).getActionsList();
137 out.writeShort(ACTIONS_INSTRUCTION_LENGTH + ActionsSerializer.computeLengthOfActions(actions));
138 ByteBufUtils.padBuffer(PADDING_IN_ACTIONS_INSTRUCTION, out);
139 ActionsSerializer.encodeActions(actions, out);
141 out.writeShort(ACTIONS_INSTRUCTION_LENGTH);
142 ByteBufUtils.padBuffer(PADDING_IN_ACTIONS_INSTRUCTION, out);
147 * Computes length of instructions
148 * @param instructions List of instructions
149 * @return length of instructions (in bytes)
151 public static int computeInstructionsLength(List<Instructions> instructions) {
153 if (instructions != null) {
154 for (Instructions instruction : instructions) {
155 Class<? extends Instruction> type = instruction.getType();
156 if (type.isAssignableFrom(GotoTable.class)) {
157 length += GOTO_TABLE_LENGTH;
158 } else if (type.isAssignableFrom(WriteMetadata.class)) {
159 length += WRITE_METADATA_LENGTH;
160 } else if (type.isAssignableFrom(WriteActions.class)) {
161 length += ACTIONS_INSTRUCTION_LENGTH;
162 if (instruction.getAugmentation(ActionsInstruction.class) != null) {
163 length += ActionsSerializer.computeLengthOfActions(
164 instruction.getAugmentation(ActionsInstruction.class).getActionsList());
166 } else if (type.isAssignableFrom(ApplyActions.class)) {
167 length += ACTIONS_INSTRUCTION_LENGTH;
168 if (instruction.getAugmentation(ActionsInstruction.class) != null) {
169 length += ActionsSerializer.computeLengthOfActions(
170 instruction.getAugmentation(ActionsInstruction.class).getActionsList());
172 } else if (type.isAssignableFrom(ClearActions.class)) {
173 length += ACTIONS_INSTRUCTION_LENGTH;
174 } else if (type.isAssignableFrom(Meter.class)) {
175 length += METER_LENGTH;
176 } else if (type.isAssignableFrom(Experimenter.class)) {
177 ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);
178 byte[] data = experimenter.getData();
179 length += EXPERIMENTER_LENGTH + data.length;