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 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;
14 import io.netty.buffer.ByteBuf;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
30 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;
31 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;
32 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;
33 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;
34 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;
35 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;
36 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;
37 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;
38 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;
39 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;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 public final class LearnCodecUtil {
48 private static final Logger LOG = LoggerFactory.getLogger(LearnCodecUtil.class);
49 public static final int HEADER_LENGTH = 32;
50 private static final short SRC_MASK = 0x2000;
51 private static final short DST_MASK = 0x1800;
52 private static final short NUM_BITS_MASK = 0x07FF;
53 private static final int SRC_POS = 13;
54 private static final int DST_POS = 11;
55 private static final int FROM_FIELD_LENGTH = 14;
56 private static final int FROM_VALUE_LENGTH = 10;
57 private static final int TO_PORT_LENGTH = 8;
58 private static final int EMPTY_FLOW_MOD_LENGTH = 2;
59 private static short length;
61 private LearnCodecUtil() {
64 static short deserializeHeader(ByteBuf message) {
65 // size of experimenter type
66 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
68 short messageLength = message.readShort();
70 message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
72 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
80 static void serializeLearnHeader(final ByteBuf outBuffer, ActionLearn action) {
81 outBuffer.writeShort(action.getNxActionLearn().getIdleTimeout().shortValue());
82 outBuffer.writeShort(action.getNxActionLearn().getHardTimeout().shortValue());
83 outBuffer.writeShort(action.getNxActionLearn().getPriority().shortValue());
84 outBuffer.writeLong(action.getNxActionLearn().getCookie().longValue());
85 outBuffer.writeShort(action.getNxActionLearn().getFlags().shortValue());
86 outBuffer.writeByte(action.getNxActionLearn().getTableId().byteValue());
87 outBuffer.writeZero(1);
88 outBuffer.writeShort(action.getNxActionLearn().getFinIdleTimeout().shortValue());
89 outBuffer.writeShort(action.getNxActionLearn().getFinHardTimeout().shortValue());
92 static void serializeFlowMods(final ByteBuf outBuffer, ActionLearn action) {
93 if (action.getNxActionLearn().getFlowMods() != null) {
94 for (FlowMods flowMod : action.getNxActionLearn().getFlowMods()) {
95 if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase) {
96 FlowModAddMatchFromField flowModSpecFromField = ((FlowModAddMatchFromFieldCase) flowMod
97 .getFlowModSpec()).getFlowModAddMatchFromField();
98 toFlowModSpecHeader(flowModSpecFromField, outBuffer);
99 outBuffer.writeInt(flowModSpecFromField.getSrcField().intValue());
100 outBuffer.writeShort(flowModSpecFromField.getSrcOfs().shortValue());
101 outBuffer.writeInt(flowModSpecFromField.getDstField().intValue());
102 outBuffer.writeShort(flowModSpecFromField.getDstOfs().shortValue());
103 } else if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase) {
104 FlowModAddMatchFromValue flowModSpec = ((FlowModAddMatchFromValueCase) flowMod.getFlowModSpec())
105 .getFlowModAddMatchFromValue();
106 toFlowModSpecHeader(flowModSpec, outBuffer);
107 outBuffer.writeShort(flowModSpec.getValue().shortValue());
108 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
109 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
111 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase) {
112 FlowModCopyFieldIntoField flowModSpec = ((FlowModCopyFieldIntoFieldCase) flowMod.getFlowModSpec())
113 .getFlowModCopyFieldIntoField();
114 toFlowModSpecHeader(flowModSpec, outBuffer);
115 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
116 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
117 outBuffer.writeInt(flowModSpec.getDstField().intValue());
118 outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
120 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase) {
121 FlowModCopyValueIntoField flowModSpec = ((FlowModCopyValueIntoFieldCase) flowMod.getFlowModSpec())
122 .getFlowModCopyValueIntoField();
123 toFlowModSpecHeader(flowModSpec, outBuffer);
124 outBuffer.writeShort(flowModSpec.getValue().shortValue());
125 outBuffer.writeInt(flowModSpec.getDstField().intValue());
126 outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
128 } else if (flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase) {
129 FlowModOutputToPort flowModSpec = ((FlowModOutputToPortCase) flowMod.getFlowModSpec())
130 .getFlowModOutputToPort();
131 toFlowModSpecHeader(flowModSpec, outBuffer);
132 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
133 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
139 private static void toFlowModSpecHeader(FlowModOutputToPort flowModSpec, ByteBuf outBuffer) {
140 serializeFlowModSpecHeader(0,2,(short)flowModSpec.getFlowModNumBits().toJava(), outBuffer);
143 private static void toFlowModSpecHeader(FlowModCopyValueIntoField flowModSpec, ByteBuf outBuffer) {
144 serializeFlowModSpecHeader(1,1,(short)flowModSpec.getFlowModNumBits().toJava(), outBuffer);
147 private static void toFlowModSpecHeader(FlowModCopyFieldIntoField flowModSpec, ByteBuf outBuffer) {
148 serializeFlowModSpecHeader(0,1,(short)flowModSpec.getFlowModNumBits().toJava(), outBuffer);
151 private static void toFlowModSpecHeader(FlowModAddMatchFromValue flowModSpec, ByteBuf outBuffer) {
152 serializeFlowModSpecHeader(1,0,(short)flowModSpec.getFlowModNumBits().toJava(), outBuffer);
155 private static void toFlowModSpecHeader(FlowModAddMatchFromField flowModSpec, ByteBuf outBuffer) {
156 serializeFlowModSpecHeader(0,0,(short)flowModSpec.getFlowModNumBits().toJava(), outBuffer);
159 private static void serializeFlowModSpecHeader(int src, int dst, short bitNum, ByteBuf outBuffer) {
161 value |= src << SRC_POS;
162 value |= dst << DST_POS;
164 outBuffer.writeShort(value);
167 static int calcLength(ActionLearn action) {
168 int actionLength = HEADER_LENGTH;
169 if (action.getNxActionLearn().getFlowMods() == null) {
172 for (FlowMods flowMod : action.getNxActionLearn().getFlowMods()) {
173 if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase) {
174 actionLength += FROM_FIELD_LENGTH;
175 } else if (flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase) {
176 actionLength += FROM_VALUE_LENGTH;
177 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase) {
178 actionLength += FROM_FIELD_LENGTH;
179 } else if (flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase) {
180 actionLength += FROM_VALUE_LENGTH;
181 } else if (flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase) {
182 actionLength += TO_PORT_LENGTH;
193 static void deserializeLearnHeader(final ByteBuf message, NxActionLearnBuilder nxActionLearnBuilder) {
194 nxActionLearnBuilder.setIdleTimeout(readUint16(message));
195 nxActionLearnBuilder.setHardTimeout(readUint16(message));
196 nxActionLearnBuilder.setPriority(readUint16(message));
197 nxActionLearnBuilder.setCookie(BigInteger.valueOf(message.readLong()));
198 nxActionLearnBuilder.setFlags(readUint16(message));
199 nxActionLearnBuilder.setTableId(readUint8(message));
200 message.skipBytes(1);
201 nxActionLearnBuilder.setFinIdleTimeout(readUint16(message));
202 nxActionLearnBuilder.setFinHardTimeout(readUint16(message));
205 static synchronized void buildFlowModSpecs(NxActionLearnBuilder nxActionLearnBuilder, ByteBuf message,
206 short messageLength) {
207 LearnCodecUtil.length = messageLength;
208 List<FlowMods> flowModeList = new ArrayList<>();
210 while (LearnCodecUtil.length > 0) {
211 FlowMods flowMod = readFlowMod(message);
213 if (flowMod != null) {
214 flowModeList.add(flowMod);
216 LOG.trace("skipping padding bytes");
220 if (LearnCodecUtil.length != 0) {
221 LOG.error("Learn Codec read {} bytes more than needed from stream. Packet might be corrupted",
222 Math.abs(messageLength));
224 nxActionLearnBuilder.setFlowMods(flowModeList);
227 private static FlowMods readFlowMod(ByteBuf message) {
228 short header = message.readShort();
229 length -= EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
234 short src = (short) ((header & SRC_MASK) >> SRC_POS);
235 short dst = (short) ((header & DST_MASK) >> DST_POS);
236 short numBits = (short) (header & NUM_BITS_MASK);
238 if (src == 0 && dst == 0 && numBits != 0) {
239 return readFlowModAddMatchFromField(message, numBits);
240 } else if (src == 0 && dst == 0) {
241 message.skipBytes(EMPTY_FLOW_MOD_LENGTH);
242 length -= EMPTY_FLOW_MOD_LENGTH;
243 } else if (src == 1 && dst == 0) {
244 return readFlowModAddMatchFromValue(message, numBits);
245 } else if (src == 0 && dst == 1) {
246 return readFlowModCopyFromField(message, numBits);
247 } else if (src == 1 && dst == 1) {
248 return readFlowModCopyFromValue(message, numBits);
249 } else if (src == 0 && dst == 2) {
250 return readFlowToPort(message, numBits);
257 private static FlowMods readFlowModAddMatchFromField(ByteBuf message, short numBits) {
258 FlowModAddMatchFromFieldBuilder builder = new FlowModAddMatchFromFieldBuilder();
259 builder.setSrcField(readUint32(message));
260 builder.setSrcOfs((int) message.readShort());
261 builder.setDstField(readUint32(message));
262 builder.setDstOfs((int) message.readShort());
263 builder.setFlowModNumBits((int) numBits);
264 length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
266 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
267 FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
268 caseBuilder.setFlowModAddMatchFromField(builder.build());
269 flowModsBuilder.setFlowModSpec(caseBuilder.build());
270 return flowModsBuilder.build();
273 private static FlowMods readFlowModAddMatchFromValue(ByteBuf message, short numBits) {
274 FlowModAddMatchFromValueBuilder builder = new FlowModAddMatchFromValueBuilder();
275 builder.setValue(readUint16(message));
276 builder.setSrcField(readUint32(message));
277 builder.setSrcOfs((int) message.readShort());
278 builder.setFlowModNumBits((int) numBits);
279 length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
281 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
282 FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
283 caseBuilder.setFlowModAddMatchFromValue(builder.build());
284 flowModsBuilder.setFlowModSpec(caseBuilder.build());
285 return flowModsBuilder.build();
288 private static FlowMods readFlowModCopyFromField(ByteBuf message, short numBits) {
289 FlowModCopyFieldIntoFieldBuilder builder = new FlowModCopyFieldIntoFieldBuilder();
290 builder.setSrcField(readUint32(message));
291 builder.setSrcOfs((int) message.readShort());
292 builder.setDstField(readUint32(message));
293 builder.setDstOfs((int) message.readShort());
294 builder.setFlowModNumBits((int) numBits);
295 length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
297 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
298 FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
299 caseBuilder.setFlowModCopyFieldIntoField(builder.build());
300 flowModsBuilder.setFlowModSpec(caseBuilder.build());
301 return flowModsBuilder.build();
304 private static FlowMods readFlowModCopyFromValue(ByteBuf message, short numBits) {
305 FlowModCopyValueIntoFieldBuilder builder = new FlowModCopyValueIntoFieldBuilder();
306 builder.setValue(readUint16(message));
307 builder.setDstField(readUint32(message));
308 builder.setDstOfs((int) message.readShort());
309 builder.setFlowModNumBits((int) numBits);
310 length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
312 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
313 FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
314 caseBuilder.setFlowModCopyValueIntoField(builder.build());
315 flowModsBuilder.setFlowModSpec(caseBuilder.build());
316 return flowModsBuilder.build();
319 private static FlowMods readFlowToPort(ByteBuf message, short numBits) {
320 FlowModOutputToPortBuilder builder = new FlowModOutputToPortBuilder();
321 builder.setSrcField(readUint32(message));
322 builder.setSrcOfs((int) message.readShort());
323 builder.setFlowModNumBits((int) numBits);
324 length -= TO_PORT_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
326 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
327 FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
328 caseBuilder.setFlowModOutputToPort(builder.build());
329 flowModsBuilder.setFlowModSpec(caseBuilder.build());
330 return flowModsBuilder.build();