1 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */
\r
2 package org.opendaylight.openflowjava.protocol.impl.util;
\r
4 import io.netty.buffer.ByteBuf;
\r
6 import java.util.List;
\r
8 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
\r
9 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterInstruction;
\r
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
\r
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
\r
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
\r
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.ActionsList;
\r
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions;
\r
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions;
\r
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Experimenter;
\r
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable;
\r
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter;
\r
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions;
\r
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata;
\r
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions;
\r
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Instruction;
\r
25 * Serializes ofp_instruction (OpenFlow v 1.3) structure
\r
26 * @author michal.polkorab
\r
27 * @author timotej.kubas
\r
29 public abstract class InstructionsSerializer {
\r
31 private static final byte GOTO_TABLE_TYPE = 1;
\r
32 private static final byte WRITE_METADATA_TYPE = 2;
\r
33 private static final byte WRITE_ACTIONS_TYPE = 3;
\r
34 private static final byte APPLY_ACTIONS_TYPE = 4;
\r
35 private static final byte CLEAR_ACTIONS_TYPE = 5;
\r
36 private static final byte METER_TYPE = 6;
\r
37 private static final byte EXPERIMENTER_TYPE = 7;
\r
38 private static final byte GOTO_TABLE_LENGTH = 8;
\r
39 private static final byte WRITE_METADATA_LENGTH = 24;
\r
40 private static final byte WRITE_ACTIONS_LENGTH = 8;
\r
41 private static final byte APPLY_ACTIONS_LENGTH = 8;
\r
42 private static final byte CLEAR_ACTIONS_LENGTH = 8;
\r
43 private static final byte METER_LENGTH = 8;
\r
44 private static final byte EXPERIMENTER_LENGTH = 8;
\r
45 private static final byte PADDING_IN_GOTO_TABLE = 3;
\r
46 private static final byte PADDING_IN_WRITE_METADATA = 4;
\r
47 private static final byte PADDING_IN_CLEAR_ACTIONS = 4;
\r
50 * Encodes instructions
\r
51 * @param instructions List of instructions
\r
52 * @param out output buffer
\r
54 public static void encodeInstructions(List<Instructions> instructions, ByteBuf out) {
\r
55 if (instructions != null) {
\r
56 for (Instructions instruction : instructions) {
\r
57 Class<? extends Instruction> type = instruction.getType();
\r
58 if (type.isAssignableFrom(GotoTable.class)) {
\r
59 writeTypeAndLength(out, GOTO_TABLE_TYPE, GOTO_TABLE_LENGTH);
\r
60 out.writeByte(instruction.getAugmentation(TableIdInstruction.class).getTableId());
\r
61 ByteBufUtils.padBuffer(PADDING_IN_GOTO_TABLE, out);
\r
62 } else if (type.isAssignableFrom(WriteMetadata.class)) {
\r
63 writeTypeAndLength(out, WRITE_METADATA_TYPE, WRITE_METADATA_LENGTH);
\r
64 ByteBufUtils.padBuffer(PADDING_IN_WRITE_METADATA, out);
\r
65 MetadataInstruction metadata = instruction.getAugmentation(MetadataInstruction.class);
\r
66 out.writeBytes(metadata.getMetadata());
\r
67 out.writeBytes(metadata.getMetadataMask());
\r
68 } else if (type.isAssignableFrom(WriteActions.class)) {
\r
69 writeActionsInstruction(out, instruction, WRITE_ACTIONS_TYPE);
\r
70 } else if (type.isAssignableFrom(ApplyActions.class)) {
\r
71 writeActionsInstruction(out, instruction, APPLY_ACTIONS_TYPE);
\r
72 } else if (type.isAssignableFrom(ClearActions.class)) {
\r
73 writeTypeAndLength(out, CLEAR_ACTIONS_TYPE, CLEAR_ACTIONS_LENGTH);
\r
74 ByteBufUtils.padBuffer(PADDING_IN_CLEAR_ACTIONS, out);
\r
75 } else if (type.isAssignableFrom(Meter.class)) {
\r
76 writeTypeAndLength(out, METER_TYPE, METER_LENGTH);
\r
77 out.writeInt(instruction.getAugmentation(MeterIdInstruction.class).getMeterId().intValue());
\r
78 } else if (type.isAssignableFrom(Experimenter.class)) {
\r
79 ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);
\r
80 byte[] data = experimenter.getData();
\r
81 writeTypeAndLength(out, EXPERIMENTER_TYPE, EXPERIMENTER_LENGTH + data.length);
\r
82 out.writeInt(experimenter.getExperimenter().intValue());
\r
83 out.writeBytes(data);
\r
90 private static void writeTypeAndLength(ByteBuf out, int type, int length) {
\r
91 out.writeShort(type);
\r
92 out.writeShort(length);
\r
95 private static void writeActionsInstruction(ByteBuf out,
\r
96 Instructions instruction, int type) {
\r
97 final byte ACTIONS_INSTRUCTION_LENGTH = 8;
\r
98 final byte PADDING_IN_ACTIONS_INSTRUCTION = 4;
\r
99 out.writeShort(type);
\r
100 List<ActionsList> actions = instruction.getAugmentation(ActionsInstruction.class).getActionsList();
\r
101 out.writeShort(ACTIONS_INSTRUCTION_LENGTH + ActionsSerializer.computeLengthOfActions(actions));
\r
102 ByteBufUtils.padBuffer(PADDING_IN_ACTIONS_INSTRUCTION, out);
\r
103 ActionsSerializer.encodeActions(actions, out);
\r
107 * Computes length of instructions
\r
108 * @param instructions List of instructions
\r
109 * @return length of instructions (in bytes)
\r
111 public static int computeInstructionsLength(List<Instructions> instructions) {
\r
113 if (instructions != null) {
\r
114 for (Instructions instruction : instructions) {
\r
115 Class<? extends Instruction> type = instruction.getType();
\r
116 if (type.isAssignableFrom(GotoTable.class)) {
\r
117 length += GOTO_TABLE_LENGTH;
\r
118 } else if (type.isAssignableFrom(WriteMetadata.class)) {
\r
119 length += WRITE_METADATA_LENGTH;
\r
120 } else if (type.isAssignableFrom(WriteActions.class)) {
\r
121 length += WRITE_ACTIONS_LENGTH + ActionsSerializer.computeLengthOfActions(
\r
122 instruction.getAugmentation(ActionsInstruction.class).getActionsList());
\r
123 } else if (type.isAssignableFrom(ApplyActions.class)) {
\r
124 length += APPLY_ACTIONS_LENGTH + ActionsSerializer.computeLengthOfActions(
\r
125 instruction.getAugmentation(ActionsInstruction.class).getActionsList());
\r
126 } else if (type.isAssignableFrom(ClearActions.class)) {
\r
127 length += CLEAR_ACTIONS_LENGTH;
\r
128 } else if (type.isAssignableFrom(Meter.class)) {
\r
129 length += METER_LENGTH;
\r
130 } else if (type.isAssignableFrom(Experimenter.class)) {
\r
131 ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);
\r
132 byte[] data = experimenter.getData();
\r
133 length += EXPERIMENTER_LENGTH + data.length;
\r