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 java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.List;
14 import io.netty.buffer.ByteBuf;
16 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionLearn;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCase;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromFieldCaseBuilder;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModAddMatchFromValueCaseBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyFieldIntoFieldCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModCopyValueIntoFieldCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.flow.mod.spec.flow.mod.spec.FlowModOutputToPortCaseBuilder;
28 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;
29 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;
30 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;
31 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;
32 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;
33 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;
34 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;
35 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;
36 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;
37 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;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.NxActionLearnBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowMods;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.learn.grouping.nx.action.learn.FlowModsBuilder;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
44 public class LearnCodecUtil {
46 private static final Logger logger = LoggerFactory.getLogger(LearnCodecUtil.class);
47 public static final int HEADER_LENGTH = 32;
48 private static final short SRC_MASK = 0x2000;
49 private static final short DST_MASK = 0x1800;
50 private static final short NUM_BITS_MASK = 0x07FF;
51 private static final int SRC_POS = 13;
52 private static final int DST_POS = 11;
53 private static final int FROM_FIELD_LENGTH = 14;
54 private static final int FROM_VALUE_LENGTH = 10;
55 private static final int TO_PORT_LENGTH = 8;
56 private static final int EMPTY_FLOW_MOD_LENGTH = 2;
57 private static short length;
60 static short deserializeHeader(ByteBuf message) {
61 // size of experimenter type
62 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
64 short length = 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.getFlowModSpec()).getFlowModAddMatchFromField();
93 toFlowModSpecHeader(flowModSpecFromField, outBuffer);
94 outBuffer.writeInt(flowModSpecFromField.getSrcField().intValue());
95 outBuffer.writeShort(flowModSpecFromField.getSrcOfs().shortValue());
96 outBuffer.writeInt(flowModSpecFromField.getDstField().intValue());
97 outBuffer.writeShort(flowModSpecFromField.getDstOfs().shortValue());
98 }else if( flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase){
99 FlowModAddMatchFromValue flowModSpec = ((FlowModAddMatchFromValueCase)flowMod.getFlowModSpec()).getFlowModAddMatchFromValue();
100 toFlowModSpecHeader(flowModSpec, outBuffer);
101 outBuffer.writeShort(flowModSpec.getValue().shortValue());
102 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
103 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
105 }else if( flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase){
106 FlowModCopyFieldIntoField flowModSpec = ((FlowModCopyFieldIntoFieldCase)flowMod.getFlowModSpec()).getFlowModCopyFieldIntoField();
107 toFlowModSpecHeader(flowModSpec, outBuffer);
108 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
109 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
110 outBuffer.writeInt(flowModSpec.getDstField().intValue());
111 outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
113 }else if( flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase){
114 FlowModCopyValueIntoField flowModSpec = ((FlowModCopyValueIntoFieldCase)flowMod.getFlowModSpec()).getFlowModCopyValueIntoField();
115 toFlowModSpecHeader(flowModSpec, outBuffer);
116 outBuffer.writeShort(flowModSpec.getValue().shortValue());
117 outBuffer.writeInt(flowModSpec.getDstField().intValue());
118 outBuffer.writeShort(flowModSpec.getDstOfs().shortValue());
120 }else if( flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase){
121 FlowModOutputToPort flowModSpec = ((FlowModOutputToPortCase)flowMod.getFlowModSpec()).getFlowModOutputToPort();
122 toFlowModSpecHeader(flowModSpec, outBuffer);
123 outBuffer.writeInt(flowModSpec.getSrcField().intValue());
124 outBuffer.writeShort(flowModSpec.getSrcOfs().shortValue());
130 private static void toFlowModSpecHeader(FlowModOutputToPort flowModSpec, ByteBuf outBuffer) {
131 serializeFlowModSpecHeader(0,2,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
134 private static void toFlowModSpecHeader(FlowModCopyValueIntoField flowModSpec, ByteBuf outBuffer) {
135 serializeFlowModSpecHeader(1,1,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
138 private static void toFlowModSpecHeader(FlowModCopyFieldIntoField flowModSpec, ByteBuf outBuffer) {
139 serializeFlowModSpecHeader(0,1,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
142 private static void toFlowModSpecHeader(FlowModAddMatchFromValue flowModSpec, ByteBuf outBuffer) {
143 serializeFlowModSpecHeader(1,0,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
146 private static void toFlowModSpecHeader(FlowModAddMatchFromField flowModSpec, ByteBuf outBuffer) {
147 serializeFlowModSpecHeader(0,0,(short)(int)flowModSpec.getFlowModNumBits(), outBuffer);
150 private static void serializeFlowModSpecHeader(int src, int dst, short bitNum, ByteBuf outBuffer) {
152 s |= (src << SRC_POS);
153 s |= (dst << DST_POS);
155 outBuffer.writeShort(s);
158 static int calcLength(ActionLearn action) {
159 int length = HEADER_LENGTH;
160 if(action.getNxActionLearn().getFlowMods() == null){
163 for(FlowMods flowMod : action.getNxActionLearn().getFlowMods()){
164 if(flowMod.getFlowModSpec() instanceof FlowModAddMatchFromFieldCase){
165 length += FROM_FIELD_LENGTH;
166 } else if( flowMod.getFlowModSpec() instanceof FlowModAddMatchFromValueCase){
167 length += FROM_VALUE_LENGTH;
168 } else if( flowMod.getFlowModSpec() instanceof FlowModCopyFieldIntoFieldCase){
169 length += FROM_FIELD_LENGTH;
170 } else if( flowMod.getFlowModSpec() instanceof FlowModCopyValueIntoFieldCase){
171 length += FROM_VALUE_LENGTH;
172 } else if( flowMod.getFlowModSpec() instanceof FlowModOutputToPortCase){
173 length += TO_PORT_LENGTH;
184 static void deserializeLearnHeader(final ByteBuf message, NxActionLearnBuilder nxActionLearnBuilder) {
185 nxActionLearnBuilder.setIdleTimeout(message.readUnsignedShort());
186 nxActionLearnBuilder.setHardTimeout(message.readUnsignedShort());
187 nxActionLearnBuilder.setPriority(message.readUnsignedShort());
188 nxActionLearnBuilder.setCookie(BigInteger.valueOf(message.readLong()));
189 nxActionLearnBuilder.setFlags(message.readUnsignedShort());
190 nxActionLearnBuilder.setTableId(message.readUnsignedByte());
191 message.skipBytes(1);
192 nxActionLearnBuilder.setFinIdleTimeout(message.readUnsignedShort());
193 nxActionLearnBuilder.setFinHardTimeout(message.readUnsignedShort());
196 static synchronized void buildFlowModSpecs(NxActionLearnBuilder nxActionLearnBuilder, ByteBuf message, short length) {
197 LearnCodecUtil.length = length;
198 List<FlowMods> flowModeList = new ArrayList<FlowMods>();
200 while(LearnCodecUtil.length > 0){
201 FlowMods flowMod = readFlowMod(message);
204 flowModeList.add(flowMod);
206 logger.trace("skipping padding bytes");
210 if(LearnCodecUtil.length != 0){
211 logger.error("Learn Codec read " + Math.abs(length) + " bytes more than needed from stream. Packet might be corrupted");
213 nxActionLearnBuilder.setFlowMods(flowModeList);
216 private static FlowMods readFlowMod(ByteBuf message) {
217 short header = message.readShort();
218 length -= EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
223 short src = (short) ((header & SRC_MASK) >> SRC_POS);
224 short dst = (short) ((header & DST_MASK) >> DST_POS);
225 short numBits = (short) (header & NUM_BITS_MASK);
227 if(src == 0 && dst == 0 && numBits != 0){
228 return readFlowModAddMatchFromField(message, numBits);
229 } else if(src == 0 && dst == 0){
230 message.skipBytes(EMPTY_FLOW_MOD_LENGTH);
231 length -= EMPTY_FLOW_MOD_LENGTH;
232 } else if(src == 1 && dst == 0){
233 return readFlowModAddMatchFromValue(message, numBits);
234 } else if(src == 0 && dst == 1){
235 return readFlowModCopyFromField(message, numBits);
236 } else if(src == 1 && dst == 1){
237 return readFlowModCopyFromValue(message, numBits);
238 } else if(src == 0 && dst == 2){
239 return readFlowToPort(message, numBits);
246 private static FlowMods readFlowModAddMatchFromField(ByteBuf message, short numBits) {
247 FlowModAddMatchFromFieldBuilder builder = new FlowModAddMatchFromFieldBuilder();
248 builder.setSrcField((long) message.readInt());
249 builder.setSrcOfs((int) message.readShort());
250 builder.setDstField((long) message.readInt());
251 builder.setDstOfs((int) message.readShort());
252 builder.setFlowModNumBits((int) numBits);
253 length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
255 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
256 FlowModAddMatchFromFieldCaseBuilder caseBuilder = new FlowModAddMatchFromFieldCaseBuilder();
257 caseBuilder.setFlowModAddMatchFromField(builder.build());
258 flowModsBuilder.setFlowModSpec(caseBuilder.build());
259 return flowModsBuilder.build();
262 private static FlowMods readFlowModAddMatchFromValue(ByteBuf message, short numBits) {
263 FlowModAddMatchFromValueBuilder builder = new FlowModAddMatchFromValueBuilder();
264 builder.setValue((int) message.readUnsignedShort());
265 builder.setSrcField((long) message.readInt());
266 builder.setSrcOfs((int) message.readShort());
267 builder.setFlowModNumBits((int) numBits);
268 length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
270 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
271 FlowModAddMatchFromValueCaseBuilder caseBuilder = new FlowModAddMatchFromValueCaseBuilder();
272 caseBuilder.setFlowModAddMatchFromValue(builder.build());
273 flowModsBuilder.setFlowModSpec(caseBuilder.build());
274 return flowModsBuilder.build();
277 private static FlowMods readFlowModCopyFromField(ByteBuf message, short numBits) {
278 FlowModCopyFieldIntoFieldBuilder builder = new FlowModCopyFieldIntoFieldBuilder();
279 builder.setSrcField((long) message.readInt());
280 builder.setSrcOfs((int) message.readShort());
281 builder.setDstField((long) message.readInt());
282 builder.setDstOfs((int) message.readShort());
283 builder.setFlowModNumBits((int) numBits);
284 length -= FROM_FIELD_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
286 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
287 FlowModCopyFieldIntoFieldCaseBuilder caseBuilder = new FlowModCopyFieldIntoFieldCaseBuilder();
288 caseBuilder.setFlowModCopyFieldIntoField(builder.build());
289 flowModsBuilder.setFlowModSpec(caseBuilder.build());
290 return flowModsBuilder.build();
293 private static FlowMods readFlowModCopyFromValue(ByteBuf message, short numBits) {
294 FlowModCopyValueIntoFieldBuilder builder = new FlowModCopyValueIntoFieldBuilder();
295 builder.setValue((int) message.readUnsignedShort());
296 builder.setDstField((long) message.readInt());
297 builder.setDstOfs((int) message.readShort());
298 builder.setFlowModNumBits((int) numBits);
299 length -= FROM_VALUE_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
301 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
302 FlowModCopyValueIntoFieldCaseBuilder caseBuilder = new FlowModCopyValueIntoFieldCaseBuilder();
303 caseBuilder.setFlowModCopyValueIntoField(builder.build());
304 flowModsBuilder.setFlowModSpec(caseBuilder.build());
305 return flowModsBuilder.build();
308 private static FlowMods readFlowToPort(ByteBuf message, short numBits) {
309 FlowModOutputToPortBuilder builder = new FlowModOutputToPortBuilder();
310 builder.setSrcField((long) message.readInt());
311 builder.setSrcOfs((int) message.readShort());
312 builder.setFlowModNumBits((int) numBits);
313 length -= TO_PORT_LENGTH - EncodeConstants.SIZE_OF_SHORT_IN_BYTES;
315 FlowModsBuilder flowModsBuilder = new FlowModsBuilder();
316 FlowModOutputToPortCaseBuilder caseBuilder = new FlowModOutputToPortCaseBuilder();
317 caseBuilder.setFlowModOutputToPort(builder.build());
318 flowModsBuilder.setFlowModSpec(caseBuilder.build());
319 return flowModsBuilder.build();