Fixing OF Multipart messages
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / InstructionsSerializer.java
1 /* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */\r
2 package org.opendaylight.openflowjava.protocol.impl.util;\r
3 \r
4 import io.netty.buffer.ByteBuf;\r
5 \r
6 import java.util.List;\r
7 \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
23 \r
24 /**\r
25  * @author michal.polkorab\r
26  *\r
27  */\r
28 public abstract class InstructionsSerializer {\r
29 \r
30     /**\r
31      * Encodes instructions\r
32      * @param instructions List of instructions\r
33      * @param out output buffer\r
34      */\r
35     public static void encodeInstructions(List<Instructions> instructions, ByteBuf out) {\r
36         if (instructions != null) {\r
37             for (Instructions instruction : instructions) {\r
38                 Class<? extends Instruction> type = instruction.getType();\r
39                 if (type.equals(GotoTable.class)) {\r
40                     final byte GOTO_TABLE_TYPE = 1;\r
41                     final byte GOTO_TABLE_LENGTH = 8;\r
42                     final byte PADDING_IN_GOTO_TABLE = 3;\r
43                     writeTypeAndLength(out, GOTO_TABLE_TYPE, GOTO_TABLE_LENGTH);\r
44                     out.writeByte(instruction.getAugmentation(TableIdInstruction.class).getTableId());\r
45                     ByteBufUtils.padBuffer(PADDING_IN_GOTO_TABLE, out);\r
46                 } else if (type.equals(WriteMetadata.class)) {\r
47                     final byte WRITE_METADATA_TYPE = 2;\r
48                     final byte WRITE_METADATA_LENGTH = 24;\r
49                     final byte PADDING_IN_WRITE_METADATA = 4;\r
50                     writeTypeAndLength(out, WRITE_METADATA_TYPE, WRITE_METADATA_LENGTH);\r
51                     ByteBufUtils.padBuffer(PADDING_IN_WRITE_METADATA, out);\r
52                     MetadataInstruction metadata = instruction.getAugmentation(MetadataInstruction.class);\r
53                     out.writeBytes(metadata.getMetadata());\r
54                     out.writeBytes(metadata.getMetadataMask());\r
55                 } else if (type.equals(WriteActions.class)) {\r
56                     final byte WRITE_ACTIONS_TYPE = 3;\r
57                     writeActionsInstruction(out, instruction, WRITE_ACTIONS_TYPE);\r
58                 } else if (type.equals(ApplyActions.class)) {\r
59                     final byte APPLY_ACTIONS_TYPE = 4;\r
60                     writeActionsInstruction(out, instruction, APPLY_ACTIONS_TYPE);\r
61                 } else if (type.equals(ClearActions.class)) {\r
62                     final byte CLEAR_ACTIONS_TYPE = 5;\r
63                     final byte CLEAR_ACTIONS_LENGTH = 8;\r
64                     final byte PADDING_IN_CLEAR_ACTIONS = 4;\r
65                     writeTypeAndLength(out, CLEAR_ACTIONS_TYPE, CLEAR_ACTIONS_LENGTH);\r
66                     ByteBufUtils.padBuffer(PADDING_IN_CLEAR_ACTIONS, out);\r
67                 } else if (type.equals(Meter.class)) {\r
68                     final byte METER_TYPE = 6;\r
69                     final byte METER_LENGTH = 8;\r
70                     writeTypeAndLength(out, METER_TYPE, METER_LENGTH);\r
71                     out.writeInt(instruction.getAugmentation(MeterIdInstruction.class).getMeterId().intValue());\r
72                 } else if (type.equals(Experimenter.class)) {\r
73                     final byte EXPERIMENTER_TYPE = 7;\r
74                     final byte EXPERIMENTER_LENGTH = 8;\r
75                     ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);\r
76                     byte[] data = experimenter.getData();\r
77                     writeTypeAndLength(out, EXPERIMENTER_TYPE, EXPERIMENTER_LENGTH + data.length);\r
78                     out.writeInt(experimenter.getExperimenter().intValue());\r
79                     out.writeBytes(data);\r
80                 }\r
81             }\r
82         }\r
83         \r
84     }\r
85 \r
86     private static void writeTypeAndLength(ByteBuf out, int type, int length) {\r
87         out.writeShort(type);\r
88         out.writeShort(length);\r
89     }\r
90 \r
91     private static void writeActionsInstruction(ByteBuf out,\r
92             Instructions instruction, int type) {\r
93         final byte ACTIONS_INSTRUCTION_LENGTH = 8;\r
94         final byte PADDING_IN_ACTIONS_INSTRUCTION = 4;\r
95         out.writeShort(type);\r
96         List<ActionsList> actions = instruction.getAugmentation(ActionsInstruction.class).getActionsList();\r
97         out.writeShort(ACTIONS_INSTRUCTION_LENGTH + ActionsSerializer.computeLengthOfActions(actions));\r
98         ByteBufUtils.padBuffer(PADDING_IN_ACTIONS_INSTRUCTION, out);\r
99         ActionsSerializer.encodeActions(actions, out);\r
100     }\r
101     \r
102     /**\r
103      * Computes length of instructions\r
104      * @param instructions List of instructions\r
105      * @return length of instructions(in bytes)\r
106      */\r
107     public static int computeInstructionsLength(List<Instructions> instructions) {\r
108         int length = 0;\r
109         if (instructions != null) {\r
110             for (Instructions instruction : instructions) {\r
111                 Class<? extends Instruction> type = instruction.getType();\r
112                 if (type.equals(GotoTable.class)) {\r
113                     final byte GOTO_TABLE_LENGTH = 8;\r
114                     length += GOTO_TABLE_LENGTH;\r
115                 } else if (type.equals(WriteMetadata.class)) {\r
116                     final byte WRITE_METADATA_LENGTH = 24;\r
117                     length += WRITE_METADATA_LENGTH;\r
118                 } else if (type.equals(WriteActions.class)) {\r
119                     final byte WRITE_ACTIONS_LENGTH = 8;\r
120                     length += WRITE_ACTIONS_LENGTH + ActionsSerializer.computeLengthOfActions(\r
121                             instruction.getAugmentation(ActionsInstruction.class).getActionsList());\r
122                 } else if (type.equals(ApplyActions.class)) {\r
123                     final byte APPLY_ACTIONS_LENGTH = 8;\r
124                     length += APPLY_ACTIONS_LENGTH + ActionsSerializer.computeLengthOfActions(\r
125                             instruction.getAugmentation(ActionsInstruction.class).getActionsList());\r
126                 } else if (type.equals(ClearActions.class)) {\r
127                     final byte CLEAR_ACTIONS_LENGTH = 8;\r
128                     length += CLEAR_ACTIONS_LENGTH;\r
129                 } else if (type.equals(Meter.class)) {\r
130                     final byte METER_LENGTH = 8;\r
131                     length += METER_LENGTH;\r
132                 } else if (type.equals(Experimenter.class)) {\r
133                     final byte EXPERIMENTER_LENGTH = 8;\r
134                     ExperimenterInstruction experimenter = instruction.getAugmentation(ExperimenterInstruction.class);\r
135                     byte[] data = experimenter.getData();\r
136                     length += EXPERIMENTER_LENGTH + data.length;\r
137                 }\r
138             }\r
139         }\r
140         return length;\r
141     }\r
142 }\r