Extensibility support (serialization part)
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / OF13InstructionsSerializer.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.List;
14
15 import org.opendaylight.openflowjava.protocol.api.extensibility.HeaderSerializer;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.MessageTypeKey;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.OFSerializer;
18 import org.opendaylight.openflowjava.protocol.api.extensibility.RegistryInjector;
19 import org.opendaylight.openflowjava.protocol.api.extensibility.SerializerRegistry;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ActionsInstruction;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ExperimenterInstruction;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataInstruction;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MeterIdInstruction;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TableIdInstruction;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev130731.actions.grouping.Action;
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.types.rev130731.InstructionBase;
35
36 /**
37  * Serializes ofp_instruction (OpenFlow v 1.3) structure
38  * @author michal.polkorab
39  * @author timotej.kubas
40  */
41 public class OF13InstructionsSerializer implements OFSerializer<Instruction>,
42         HeaderSerializer<Instruction>, RegistryInjector {
43
44     private static final byte GOTO_TABLE_TYPE = 1;
45     private static final byte WRITE_METADATA_TYPE = 2;
46     private static final byte WRITE_ACTIONS_TYPE = 3;
47     private static final byte APPLY_ACTIONS_TYPE = 4;
48     private static final byte CLEAR_ACTIONS_TYPE = 5;
49     private static final byte METER_TYPE = 6;
50     private static final byte GOTO_TABLE_LENGTH = 8;
51     private static final byte WRITE_METADATA_LENGTH = 24;
52     private static final byte METER_LENGTH = 8;
53     private static final byte ACTIONS_INSTRUCTION_LENGTH = 8;
54     private static final byte PADDING_IN_GOTO_TABLE = 3;
55     private static final byte PADDING_IN_WRITE_METADATA = 4;
56     private static final byte PADDING_IN_CLEAR_ACTIONS = 4;
57     private static final byte INSTRUCTION_IDS_LENGTH = 4;
58     private static final byte PADDING_IN_ACTIONS_INSTRUCTION = 4;
59     private SerializerRegistry registry;
60
61     private static void writeTypeAndLength(ByteBuf out, int type, int length) {
62         out.writeShort(type);
63         out.writeShort(length);
64     }
65
66     private void writeActionsInstruction(ByteBuf out,
67             Instruction instruction, int type) {
68         int instructionStartIndex = out.writerIndex();
69         out.writeShort(type);
70         if (instruction.getAugmentation(ActionsInstruction.class) != null) {
71             List<Action> actions = instruction.getAugmentation(ActionsInstruction.class).getAction();
72             int instructionLengthIndex = out.writerIndex();
73             out.writeShort(EncodeConstants.EMPTY_LENGTH);
74             ByteBufUtils.padBuffer(PADDING_IN_ACTIONS_INSTRUCTION, out);
75             OFSerializer<Action> serializer = registry.getSerializer(
76                     new MessageTypeKey<>(EncodeConstants.OF13_VERSION_ID, Action.class));
77             CodingUtils.serializeList(actions, serializer, out);
78             int instructionLength = out.writerIndex() - instructionStartIndex;
79             out.setShort(instructionLengthIndex, instructionLength);
80         } else {
81             out.writeShort(ACTIONS_INSTRUCTION_LENGTH);
82             ByteBufUtils.padBuffer(PADDING_IN_ACTIONS_INSTRUCTION, out);
83         }
84     }
85
86     @Override
87     public void serialize(Instruction instruction, ByteBuf outBuffer) {
88         Class<? extends InstructionBase> type = instruction.getType();
89         if (type.isAssignableFrom(GotoTable.class)) {
90             writeTypeAndLength(outBuffer, GOTO_TABLE_TYPE, GOTO_TABLE_LENGTH);
91             outBuffer.writeByte(instruction.getAugmentation(TableIdInstruction.class).getTableId());
92             ByteBufUtils.padBuffer(PADDING_IN_GOTO_TABLE, outBuffer);
93         } else if (type.isAssignableFrom(WriteMetadata.class)) {
94             writeTypeAndLength(outBuffer, WRITE_METADATA_TYPE, WRITE_METADATA_LENGTH);
95             ByteBufUtils.padBuffer(PADDING_IN_WRITE_METADATA, outBuffer);
96             MetadataInstruction metadata = instruction.getAugmentation(MetadataInstruction.class);
97             outBuffer.writeBytes(metadata.getMetadata());
98             outBuffer.writeBytes(metadata.getMetadataMask());
99         } else if (type.isAssignableFrom(WriteActions.class)) {
100             writeActionsInstruction(outBuffer, instruction, WRITE_ACTIONS_TYPE);
101         } else if (type.isAssignableFrom(ApplyActions.class)) {
102             writeActionsInstruction(outBuffer, instruction, APPLY_ACTIONS_TYPE);
103         } else if (type.isAssignableFrom(ClearActions.class)) {
104             writeTypeAndLength(outBuffer, CLEAR_ACTIONS_TYPE, ACTIONS_INSTRUCTION_LENGTH);
105             ByteBufUtils.padBuffer(PADDING_IN_CLEAR_ACTIONS, outBuffer);
106         } else if (type.isAssignableFrom(Meter.class)) {
107             writeTypeAndLength(outBuffer, METER_TYPE, METER_LENGTH);
108             outBuffer.writeInt(instruction.getAugmentation(MeterIdInstruction.class).getMeterId().intValue());
109         } else if (type.isAssignableFrom(Experimenter.class)) {
110             OFSerializer<ExperimenterInstruction> serializer = registry.getSerializer(new MessageTypeKey<>(
111                     EncodeConstants.OF13_VERSION_ID, Experimenter.class));
112             serializer.serialize((ExperimenterInstruction) instruction, outBuffer);
113         }
114     }
115
116     @Override
117     public void injectSerializerRegistry(SerializerRegistry serializerRegistry) {
118         this.registry = serializerRegistry;
119     }
120
121     @Override
122     public void serializeHeader(Instruction instruction, ByteBuf outBuffer) {
123         Class<? extends InstructionBase> type = instruction.getType();
124         if (type.isAssignableFrom(GotoTable.class)) {
125             writeTypeAndLength(outBuffer, GOTO_TABLE_TYPE, INSTRUCTION_IDS_LENGTH);
126         } else if (type.isAssignableFrom(WriteMetadata.class)) {
127             writeTypeAndLength(outBuffer, WRITE_METADATA_TYPE, INSTRUCTION_IDS_LENGTH);
128         } else if (type.isAssignableFrom(WriteActions.class)) {
129             writeTypeAndLength(outBuffer, WRITE_ACTIONS_TYPE, INSTRUCTION_IDS_LENGTH);
130         } else if (type.isAssignableFrom(ApplyActions.class)) {
131             writeTypeAndLength(outBuffer, APPLY_ACTIONS_TYPE, INSTRUCTION_IDS_LENGTH);
132         } else if (type.isAssignableFrom(ClearActions.class)) {
133             writeTypeAndLength(outBuffer, CLEAR_ACTIONS_TYPE, INSTRUCTION_IDS_LENGTH);
134         } else if (type.isAssignableFrom(Meter.class)) {
135             writeTypeAndLength(outBuffer, METER_TYPE, INSTRUCTION_IDS_LENGTH);
136         } else if (type.isAssignableFrom(Experimenter.class)) {
137             HeaderSerializer<ExperimenterInstruction> serializer = registry.getSerializer(new MessageTypeKey<>(
138                     EncodeConstants.OF13_VERSION_ID, Experimenter.class));
139             serializer.serializeHeader((ExperimenterInstruction) instruction, outBuffer);
140         }
141     }
142
143 }