3fa354f0a3982505e1e1eb62473b7b22e9b17519
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / protocol / deserialization / messages / FlowMessageDeserializer.java
1 /*
2  * Copyright (c) 2016 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 package org.opendaylight.openflowplugin.impl.protocol.deserialization.messages;
9
10 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint16;
11 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint32;
12 import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint8;
13
14 import com.google.common.base.Preconditions;
15 import io.netty.buffer.ByteBuf;
16 import java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.List;
19 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
20 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
21 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
22 import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
23 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
24 import org.opendaylight.openflowjava.protocol.impl.util.InstructionConstants;
25 import org.opendaylight.openflowplugin.api.openflow.protocol.deserialization.MessageCodeExperimenterKey;
26 import org.opendaylight.openflowplugin.extension.api.path.ActionPath;
27 import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
28 import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeActionExperimenterKey;
29 import org.opendaylight.openflowplugin.impl.protocol.deserialization.key.MessageCodeMatchKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessage;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowMessageBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowModCommand;
41
42 public class FlowMessageDeserializer implements OFDeserializer<FlowMessage>, DeserializerRegistryInjector {
43
44     private static final byte PADDING = 2;
45
46     private static final MessageCodeKey MATCH_KEY = new MessageCodeMatchKey(EncodeConstants.OF13_VERSION_ID,
47             EncodeConstants.EMPTY_VALUE, Match.class,
48             MatchPath.FLOWS_STATISTICS_UPDATE_MATCH);
49
50     private DeserializerRegistry registry;
51
52     @Override
53     @SuppressWarnings("checkstyle:LineLength")
54     public FlowMessage deserialize(ByteBuf message) {
55         final FlowMessageBuilder builder = new FlowMessageBuilder()
56             .setVersion((short) EncodeConstants.OF13_VERSION_ID)
57             .setXid(readUint32(message))
58             .setCookie(new FlowCookie(BigInteger.valueOf(message.readLong())))
59             .setCookieMask(new FlowCookie(BigInteger.valueOf(message.readLong())))
60             .setTableId(readUint8(message))
61             .setCommand(FlowModCommand.forValue(message.readUnsignedByte()))
62             .setIdleTimeout(readUint16(message))
63             .setHardTimeout(readUint16(message))
64             .setPriority(readUint16(message))
65             .setBufferId(readUint32(message))
66             .setOutPort(BigInteger.valueOf(message.readUnsignedInt()))
67             .setOutGroup(readUint32(message))
68             .setFlags(createFlowModFlagsFromBitmap(message.readUnsignedShort()));
69
70         message.skipBytes(PADDING);
71
72         final OFDeserializer<Match> matchDeserializer = Preconditions.checkNotNull(registry).getDeserializer(MATCH_KEY);
73         builder.setMatch(new MatchBuilder(matchDeserializer.deserialize(message)).build());
74
75         final int length = message.readableBytes();
76
77         if (length > 0) {
78             final List<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list
79                 .Instruction> instructions = new ArrayList<>();
80             final int startIndex = message.readerIndex();
81             int offset = 0;
82
83             while (message.readerIndex() - startIndex < length) {
84                 final int type = message.getUnsignedShort(message.readerIndex());
85                 OFDeserializer<Instruction> deserializer = null;
86
87                 if (InstructionConstants.APPLY_ACTIONS_TYPE == type) {
88                     deserializer = Preconditions.checkNotNull(registry).getDeserializer(
89                             new MessageCodeActionExperimenterKey(
90                                 EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
91                                 ActionPath.INVENTORY_FLOWNODE_TABLE_APPLY_ACTIONS,
92                                 null));
93                 } else if (InstructionConstants.WRITE_ACTIONS_TYPE == type) {
94                     deserializer = Preconditions.checkNotNull(registry).getDeserializer(
95                             new MessageCodeActionExperimenterKey(
96                                 EncodeConstants.OF13_VERSION_ID, type, Instruction.class,
97                                 ActionPath.INVENTORY_FLOWNODE_TABLE_WRITE_ACTIONS,
98                                 null));
99                 } else {
100                     Long expId = null;
101
102                     if (EncodeConstants.EXPERIMENTER_VALUE == type) {
103                         expId = message.getUnsignedInt(message.readerIndex()
104                                 + 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
105                     }
106
107                     deserializer = Preconditions.checkNotNull(registry).getDeserializer(
108                             new MessageCodeExperimenterKey(
109                                 EncodeConstants.OF13_VERSION_ID, type, Instruction.class, expId));
110                 }
111
112                 instructions.add(new InstructionBuilder()
113                         .withKey(new InstructionKey(offset))
114                         .setOrder(offset)
115                         .setInstruction(deserializer.deserialize(message))
116                         .build());
117
118                 offset++;
119             }
120
121             builder.setInstructions(new InstructionsBuilder()
122                     .setInstruction(instructions)
123                     .build());
124         }
125
126         return builder.build();
127     }
128
129     private static FlowModFlags createFlowModFlagsFromBitmap(int input) {
130         final Boolean ofp_FF_SendFlowRem = (input & 1 << 0) != 0;
131         final Boolean ofp_FF_CheckOverlap = (input & 1 << 1) != 0;
132         final Boolean ofp_FF_ResetCounts = (input & 1 << 2) != 0;
133         final Boolean ofp_FF_NoPktCounts = (input & 1 << 3) != 0;
134         final Boolean ofp_FF_NoBytCounts = (input & 1 << 4) != 0;
135         return new FlowModFlags(ofp_FF_CheckOverlap, ofp_FF_NoBytCounts, ofp_FF_NoPktCounts, ofp_FF_ResetCounts,
136                 ofp_FF_SendFlowRem);
137     }
138
139     @Override
140     public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
141         registry = deserializerRegistry;
142     }
143
144 }