Constants introduced
[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  * Serializes ofp_instruction (OpenFlow v 1.3) structure\r
26  * @author michal.polkorab\r
27  * @author timotej.kubas\r
28  */\r
29 public abstract class InstructionsSerializer {\r
30 \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
48     \r
49     /**\r
50      * Encodes instructions\r
51      * @param instructions List of instructions\r
52      * @param out output buffer\r
53      */\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
84                 }\r
85             }\r
86         }\r
87         \r
88     }\r
89 \r
90     private static void writeTypeAndLength(ByteBuf out, int type, int length) {\r
91         out.writeShort(type);\r
92         out.writeShort(length);\r
93     }\r
94 \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
104     }\r
105     \r
106     /**\r
107      * Computes length of instructions\r
108      * @param instructions List of instructions\r
109      * @return length of instructions (in bytes)\r
110      */\r
111     public static int computeInstructionsLength(List<Instructions> instructions) {\r
112         int length = 0;\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
134                 }\r
135             }\r
136         }\r
137         return length;\r
138     }\r
139 }\r