a8cb2803b25a5a37a8b92ffc927e28df8f8425e4
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / InstructionsDeserializer.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowjava.protocol.impl.util;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstructionBuilder;
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.ExperimenterInstructionBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstructionBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstructionBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstructionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Experimenter;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.Instructions;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.InstructionsBuilder;
33
34 import io.netty.buffer.ByteBuf;
35
36 /**
37  * Deserializes ofp_instruction (OpenFlow v1.3) structures
38  * @author michal.polkorab
39  * @author timotej.kubas
40  */
41 public abstract class InstructionsDeserializer {
42     
43     private static final byte WRITE_APPLY_CLEAR_ACTION_LENGTH = 8;
44     private static final byte EXPERIMENTER_HEADER_LENGTH = 8;
45     private static final byte GOTO_TABLE_PADDING = 3;
46     private static final byte WRITE_METADATA_PADDING = 4;
47     private static final byte ACTIONS_RELATED_INSTRUCTION_PADDING = 4;
48
49     /**
50      * Creates list of instructions
51      * @param input
52      * @param length
53      * @return list of ofp_instruction
54      */
55     public static List<Instructions> createInstructions(ByteBuf input, int length) {
56         List<Instructions> instructions = new ArrayList<>();
57         if (input.readableBytes() != 0) {
58             int lengthOfInstructions = length;
59             while (lengthOfInstructions > 0) {
60                 InstructionsBuilder builder = new InstructionsBuilder();
61                 int type = input.readUnsignedShort();
62                 int instructionLength = input.readUnsignedShort();
63                 lengthOfInstructions -= instructionLength;
64                 switch (type) {
65                 case 1:
66                     createGotoTableInstruction(builder, input);
67                     break;
68                 case 2:
69                     createMetadataInstruction(builder, input);
70                     break;
71                 case 3:
72                     builder.setType(WriteActions.class);
73                     createActionRelatedInstruction(input, builder, instructionLength - WRITE_APPLY_CLEAR_ACTION_LENGTH);
74                     break;
75                 case 4:
76                     builder.setType(ApplyActions.class);
77                     createActionRelatedInstruction(input, builder, instructionLength - WRITE_APPLY_CLEAR_ACTION_LENGTH);
78                     break;
79                 case 5:
80                     builder.setType(ClearActions.class);
81                     createActionRelatedInstruction(input, builder, instructionLength - WRITE_APPLY_CLEAR_ACTION_LENGTH);
82                     break;
83                 case 6:
84                     builder.setType(Meter.class);
85                     MeterIdInstructionBuilder meterBuilder = new MeterIdInstructionBuilder();
86                     meterBuilder.setMeterId(input.readUnsignedInt());
87                     builder.addAugmentation(MeterIdInstruction.class, meterBuilder.build());
88                     break;
89                 case 65535:
90                     builder.setType(Experimenter.class);
91                     ExperimenterInstructionBuilder expBuilder = new ExperimenterInstructionBuilder();
92                     expBuilder.setExperimenter(input.readUnsignedInt());
93                     int dataLength = instructionLength - EXPERIMENTER_HEADER_LENGTH;
94                     if (dataLength > 0) {
95                         byte[] data = new byte[dataLength];
96                         input.readBytes(data);
97                         expBuilder.setData(data);
98                     }
99                     builder.addAugmentation(ExperimenterInstruction.class, expBuilder.build());
100                     break;
101                 default:
102                     break;
103                 }
104                 instructions.add(builder.build());
105             }
106         }
107         return instructions;
108     }
109
110     /**
111      * Creates instruction ids (instructions without values)
112      * @param input
113      * @param length
114      * @return list of ofp_instruction without values
115      */
116     public static List<Instructions> createInstructionIds(ByteBuf input, int length) {
117         List<Instructions> instructions = new ArrayList<>();
118         if (input.readableBytes() != 0) {
119             int lengthOfInstructions = length;
120             while (lengthOfInstructions > 0) {
121                 InstructionsBuilder builder = new InstructionsBuilder();
122                 int type = input.readUnsignedShort();
123                 int instructionLength = input.readUnsignedShort();
124                 lengthOfInstructions -= instructionLength;
125                 switch (type) {
126                 case 1:
127                     builder.setType(GotoTable.class);
128                     break;
129                 case 2:
130                     builder.setType(WriteMetadata.class);
131                     break;
132                 case 3:
133                     builder.setType(WriteActions.class);
134                     break;
135                 case 4:
136                     builder.setType(ApplyActions.class);
137                     break;
138                 case 5:
139                     builder.setType(ClearActions.class);
140                     break;
141                 case 6:
142                     builder.setType(Meter.class);
143                     break;
144                 case 65535:
145                     builder.setType(Experimenter.class);
146                     break;
147                 default:
148                     break;
149                 }
150                 instructions.add(builder.build());
151             }
152         }
153         return instructions;
154     }
155
156     private static void createGotoTableInstruction(InstructionsBuilder builder,
157             ByteBuf input) {
158         builder.setType(GotoTable.class);
159         TableIdInstructionBuilder tableBuilder = new TableIdInstructionBuilder();
160         tableBuilder.setTableId(input.readUnsignedByte());
161         builder.addAugmentation(TableIdInstruction.class, tableBuilder.build());
162         input.skipBytes(GOTO_TABLE_PADDING);
163     }
164     
165     private static void createMetadataInstruction(InstructionsBuilder builder,
166             ByteBuf input) {
167         input.skipBytes(WRITE_METADATA_PADDING);
168         builder.setType(WriteMetadata.class);
169         MetadataInstructionBuilder metadataBuilder = new MetadataInstructionBuilder();
170         byte[] metadata = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
171         input.readBytes(metadata);
172         metadataBuilder.setMetadata(metadata);
173         byte[] metadata_mask = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
174         input.readBytes(metadata_mask);
175         metadataBuilder.setMetadataMask(metadata_mask);
176         builder.addAugmentation(MetadataInstruction.class, metadataBuilder.build());
177     }
178     
179     private static void createActionRelatedInstruction(ByteBuf input,
180             InstructionsBuilder builder, int actionsLength) {
181         input.skipBytes(ACTIONS_RELATED_INSTRUCTION_PADDING);
182         ActionsInstructionBuilder actionsBuilder = new ActionsInstructionBuilder();
183         actionsBuilder.setActionsList(ActionsDeserializer.createActionsList(input, actionsLength));
184         builder.addAugmentation(ActionsInstruction.class, actionsBuilder.build());
185     }
186
187 }