2 * Copyright (c) 2016 Hewlett-Packard Enterprise and others. All rights reserved.
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
8 package org.opendaylight.openflowjava.nx.codec.action;
10 import io.netty.buffer.ByteBuf;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromField;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.field._case.FlowModAddMatchFromFieldBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValue;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.add.match.from.value._case.FlowModAddMatchFromValueBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoField;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.field.into.field._case.FlowModCopyFieldIntoFieldBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoField;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.copy.value.into.field._case.FlowModCopyValueIntoFieldBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPort;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.flow.mod.output.to.port._case.FlowModOutputToPortBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
42 public final class LearnCodecUtil {
44 private static final Logger LOG = LoggerFactory.getLogger(LearnCodecUtil.class);
45 public static final int HEADER_LENGTH = 32;
46 private static final short SRC_MASK = 0x2000;
47 private static final short DST_MASK = 0x1800;
48 private static final short NUM_BITS_MASK = 0x07FF;
49 private static final int SRC_POS = 13;
50 private static final int DST_POS = 11;
51 private static final int FROM_FIELD_LENGTH = 14;
52 private static final int FROM_VALUE_LENGTH = 10;
53 private static final int TO_PORT_LENGTH = 8;
54 private static final int EMPTY_FLOW_MOD_LENGTH = 2;
55 private static short length;
57 private LearnCodecUtil() {
60 static short deserializeHeader(ByteBuf message) {
61 // size of experimenter type
62 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
64 short messageLength = message.readShort();
66 message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
68 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
76 static void serializeLearnHeader(final ByteBuf outBuffer, ActionLearn action) {
77 outBuffer.writeShort(action.getNxActionLearn().getIdleTimeout().shortValue());
78 outBuffer.writeShort(action.getNxActionLearn().getHardTimeout().shortValue());
79 outBuffer.writeShort(action.getNxActionLearn().getPriority().shortValue());
80 outBuffer.writeLong(action.getNxActionLearn().getCookie().longValue());
81 outBuffer.writeShort(action.getNxActionLearn().getFlags().shortValue());
82 outBuffer.writeByte(action.getNxActionLearn().getTableId().byteValue());
83 outBuffer.writeZero(1);
84 outBuffer.writeShort(action.getNxActionLearn().getFinIdleTimeout().shortValue());
85 outBuffer.writeShort(action.getNxActionLearn().getFinHardTimeout().shortValue());
88 static void serializeFlowMods(final ByteBuf outBuffer, ActionLearn action) {
89 if (action.getNxActionLearn().getFlowMods() != null) {
90 for (FlowMods flowMod : action.getNxActionLearn().getFlowMods()) {
91 if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase) {
92 FlowModAddMatchFromField flowModSpecFromField = ((FlowModAddMatchFromFieldCase) flowMod
93 .getFlowModSpec()).getFlowModAddMatchFromField();
94 toFlowModSpecHeader(flowModSpecFromField, outBuffer);
95 outBuffer.writeInt(flowModSpecFromField.getSrcField().intValue());
96 outBuffer.writeShort(flowModSpecFromField.getSrcOfs().shortValue());
97 outBuffer.writeInt(flowModSpecFromField.getDstField().intValue());
98 outBuffer.writeShort(flowModSpecFromField.getDstOfs().shortValue());
99 } else if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase) {
100 FlowModAddMatchFromValue flowModSpec = ((FlowModAddMatchFromValueCase) flowMod.getFlowModSpec())
101 .getFlowModAddMatchFromValue();
102 toFlowModSpecHeader(flowModSpec, outBuffer);
103 outBuffer.writeShort(flowModSpec.getValue().shortValue());
104 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
105 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
107 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase) {
108 FlowModCopyFieldIntoField flowModSpec = ((FlowModCopyFieldIntoFieldCase) flowMod.getFlowModSpec())
109 .getFlowModCopyFieldIntoField();
110 toFlowModSpecHeader(flowModSpec, outBuffer);
111 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
112 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
113 outBuffer.writeInt(flowModSpec.getDstField().intValue());
114 outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
116 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase) {
117 FlowModCopyValueIntoField flowModSpec = ((FlowModCopyValueIntoFieldCase) flowMod.getFlowModSpec())
118 .getFlowModCopyValueIntoField();
119 toFlowModSpecHeader(flowModSpec, outBuffer);
120 outBuffer.writeShort(flowModSpec.getValue().shortValue());
121 outBuffer.writeInt(flowModSpec.getDstField().intValue());
122 outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
124 } else if (flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase) {
125 FlowModOutputToPort flowModSpec = ((FlowModOutputToPortCase) flowMod.getFlowModSpec())
126 .getFlowModOutputToPort();
127 toFlowModSpecHeader(flowModSpec, outBuffer);
128 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
129 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
135 private static void toFlowModSpecHeader(FlowModOutputToPort flowModSpec, ByteBuf outBuffer) {
136 serializeFlowModSpecHeader(0,2,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
139 private static void toFlowModSpecHeader(FlowModCopyValueIntoField flowModSpec, ByteBuf outBuffer) {
140 serializeFlowModSpecHeader(1,1,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
143 private static void toFlowModSpecHeader(FlowModCopyFieldIntoField flowModSpec, ByteBuf outBuffer) {
144 serializeFlowModSpecHeader(0,1,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
147 private static void toFlowModSpecHeader(FlowModAddMatchFromValue flowModSpec, ByteBuf outBuffer) {
148 serializeFlowModSpecHeader(1,0,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
151 private static void toFlowModSpecHeader(FlowModAddMatchFromField flowModSpec, ByteBuf outBuffer) {
152 serializeFlowModSpecHeader(0,0,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
155 private static void serializeFlowModSpecHeader(int src, int dst, short bitNum, ByteBuf outBuffer) {
157 value |= src << SRC_POS;
158 value |= dst << DST_POS;
160 outBuffer.writeShort(value);
163 static int calcLength(ActionLearn action) {
164 int actionLength = HEADER_LENGTH;
165 if (action.getNxActionLearn().getFlowMods() == null) {
168 for (FlowMods flowMod : action.getNxActionLearn().getFlowMods()) {
169 if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase) {
170 actionLength += FROM_FIELD_LENGTH;
171 } else if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase) {
172 actionLength += FROM_VALUE_LENGTH;
173 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase) {
174 actionLength += FROM_FIELD_LENGTH;
175 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase) {
176 actionLength += FROM_VALUE_LENGTH;
177 } else if (flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase) {
178 actionLength += TO_PORT_LENGTH;
189 static void deserializeLearnHeader(final ByteBuf message, NxActionLearnBuilder nxActionLearnBuilder) {
190 nxActionLearnBuilder.setIdleTimeout(message.readUnsignedShort());
191 nxActionLearnBuilder.setHardTimeout(message.readUnsignedShort());
192 nxActionLearnBuilder.setPriority(message.readUnsignedShort());
193 nxActionLearnBuilder.setCookie(BigInteger.valueOf(message.readLong()));
194 nxActionLearnBuilder.setFlags(message.readUnsignedShort());
195 nxActionLearnBuilder.setTableId(message.readUnsignedByte());
196 message.skipBytes(1);
197 nxActionLearnBuilder.setFinIdleTimeout(message.readUnsignedShort());
198 nxActionLearnBuilder.setFinHardTimeout(message.readUnsignedShort());
201 static synchronized void buildFlowModSpecs(NxActionLearnBuilder nxActionLearnBuilder, ByteBuf message,
202 short messageLength) {
203 LearnCodecUtil.length = messageLength;
204 List<FlowMods> flowModeList = new ArrayList<>();
206 while (LearnCodecUtil.length > 0) {
207 FlowMods flowMod = readFlowMod(message);
209 if (flowMod != null) {
210 flowModeList.add(flowMod);
212 LOG.trace("skipping padding bytes");
216 if (LearnCodecUtil.length != 0) {
217 LOG.error("Learn Codec read {} bytes more than needed from stream. Packet might be corrupted",
218 Math.abs(messageLength));
220 nxActionLearnBuilder.setFlowMods(flowModeList);
223 private static FlowMods readFlowMod(ByteBuf message) {
224 short header = message.readShort();
225 length -= EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
230 short src = (short) ((header & SRC_MASK) >> SRC_POS);
231 short dst = (short) ((header & DST_MASK) >> DST_POS);
232 short numBits = (short) (header & NUM_BITS_MASK);
234 if (src == 0 && dst == 0 && numBits != 0) {
235 return readFlowModAddMatchFromField(message, numBits);
236 } else if (src == 0 && dst == 0) {
237 message.skipBytes(EMPTY_FLOW_MOD_LENGTH);
238 length -= EMPTY_FLOW_MOD_LENGTH;
239 } else if (src == 1 && dst == 0) {
240 return readFlowModAddMatchFromValue(message, numBits);
241 } else if (src == 0 && dst == 1) {
242 return readFlowModCopyFromField(message, numBits);
243 } else if (src == 1 && dst == 1) {
244 return readFlowModCopyFromValue(message, numBits);
245 } else if (src == 0 && dst == 2) {
246 return readFlowToPort(message, numBits);
253 private static FlowMods readFlowModAddMatchFromField(ByteBuf message, short numBits) {
254 FlowModAddMatchFromFieldBuilder builder = new FlowModAddMatchFromFieldBuilder();
255 builder.setSrcField(message.readUnsignedInt());
256 builder.setSrcOfs((int) message.readShort());
257 builder.setDstField(message.readUnsignedInt());
258 builder.setDstOfs((int) message.readShort());
259 builder.setFlowModNumBits((int) numBits);
260 length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
262 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
263 FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
264 caseBuilder.setFlowModAddMatchFromField(builder.build());
265 flowModsBuilder.setFlowModSpec(caseBuilder.build());
266 return flowModsBuilder.build();
269 private static FlowMods readFlowModAddMatchFromValue(ByteBuf message, short numBits) {
270 FlowModAddMatchFromValueBuilder builder = new FlowModAddMatchFromValueBuilder();
271 builder.setValue(message.readUnsignedShort());
272 builder.setSrcField(message.readUnsignedInt());
273 builder.setSrcOfs((int) message.readShort());
274 builder.setFlowModNumBits((int) numBits);
275 length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
277 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
278 FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
279 caseBuilder.setFlowModAddMatchFromValue(builder.build());
280 flowModsBuilder.setFlowModSpec(caseBuilder.build());
281 return flowModsBuilder.build();
284 private static FlowMods readFlowModCopyFromField(ByteBuf message, short numBits) {
285 FlowModCopyFieldIntoFieldBuilder builder = new FlowModCopyFieldIntoFieldBuilder();
286 builder.setSrcField(message.readUnsignedInt());
287 builder.setSrcOfs((int) message.readShort());
288 builder.setDstField(message.readUnsignedInt());
289 builder.setDstOfs((int) message.readShort());
290 builder.setFlowModNumBits((int) numBits);
291 length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
293 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
294 FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
295 caseBuilder.setFlowModCopyFieldIntoField(builder.build());
296 flowModsBuilder.setFlowModSpec(caseBuilder.build());
297 return flowModsBuilder.build();
300 private static FlowMods readFlowModCopyFromValue(ByteBuf message, short numBits) {
301 FlowModCopyValueIntoFieldBuilder builder = new FlowModCopyValueIntoFieldBuilder();
302 builder.setValue(message.readUnsignedShort());
303 builder.setDstField(message.readUnsignedInt());
304 builder.setDstOfs((int) message.readShort());
305 builder.setFlowModNumBits((int) numBits);
306 length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
308 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
309 FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
310 caseBuilder.setFlowModCopyValueIntoField(builder.build());
311 flowModsBuilder.setFlowModSpec(caseBuilder.build());
312 return flowModsBuilder.build();
315 private static FlowMods readFlowToPort(ByteBuf message, short numBits) {
316 FlowModOutputToPortBuilder builder = new FlowModOutputToPortBuilder();
317 builder.setSrcField(message.readUnsignedInt());
318 builder.setSrcOfs((int) message.readShort());
319 builder.setFlowModNumBits((int) numBits);
320 length -= TO_PORT_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
322 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
323 FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
324 caseBuilder.setFlowModOutputToPort(builder.build());
325 flowModsBuilder.setFlowModSpec(caseBuilder.build());
326 return flowModsBuilder.build();