Minor model refactor
[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 io.netty.buffer.ByteBuf;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstructionBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterInstruction;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterInstructionBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstructionBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstructionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstructionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ApplyActions;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.ClearActions;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Experimenter;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.GotoTable;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.Meter;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteActions;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.WriteMetadata;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.Instruction;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.instruction.rev130731.instructions.grouping.InstructionBuilder;
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<Instruction> createInstructions(ByteBuf input, int length) {
56         List<Instruction> instructions = new ArrayList<>();
57         if (input.readableBytes() != 0) {
58             int lengthOfInstructions = length;
59             while (lengthOfInstructions > 0) {
60                 InstructionBuilder builder = new InstructionBuilder();
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<Instruction> createInstructionIds(ByteBuf input, int length) {
117         List<Instruction> instructions = new ArrayList<>();
118         if (input.readableBytes() != 0) {
119             int lengthOfInstructions = length;
120             while (lengthOfInstructions > 0) {
121                 InstructionBuilder builder = new InstructionBuilder();
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                     ExperimenterInstructionBuilder expBuilder = new ExperimenterInstructionBuilder();
147                     expBuilder.setExperimenter(input.readUnsignedInt());
148                     builder.addAugmentation(ExperimenterInstruction.class, expBuilder.build());
149                     break;
150                 default:
151                     break;
152                 }
153                 instructions.add(builder.build());
154             }
155         }
156         return instructions;
157     }
158
159     private static void createGotoTableInstruction(InstructionBuilder builder,
160             ByteBuf input) {
161         builder.setType(GotoTable.class);
162         TableIdInstructionBuilder tableBuilder = new TableIdInstructionBuilder();
163         tableBuilder.setTableId(input.readUnsignedByte());
164         builder.addAugmentation(TableIdInstruction.class, tableBuilder.build());
165         input.skipBytes(GOTO_TABLE_PADDING);
166     }
167     
168     private static void createMetadataInstruction(InstructionBuilder builder,
169             ByteBuf input) {
170         input.skipBytes(WRITE_METADATA_PADDING);
171         builder.setType(WriteMetadata.class);
172         MetadataInstructionBuilder metadataBuilder = new MetadataInstructionBuilder();
173         byte[] metadata = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
174         input.readBytes(metadata);
175         metadataBuilder.setMetadata(metadata);
176         byte[] metadata_mask = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
177         input.readBytes(metadata_mask);
178         metadataBuilder.setMetadataMask(metadata_mask);
179         builder.addAugmentation(MetadataInstruction.class, metadataBuilder.build());
180     }
181     
182     private static void createActionRelatedInstruction(ByteBuf input,
183             InstructionBuilder builder, int actionsLength) {
184         input.skipBytes(ACTIONS_RELATED_INSTRUCTION_PADDING);
185         ActionsInstructionBuilder actionsBuilder = new ActionsInstructionBuilder();
186         actionsBuilder.setAction(ActionsDeserializer.createActions(input, actionsLength));
187         builder.addAugmentation(ActionsInstruction.class, actionsBuilder.build());
188     }
189
190 }