2 * Copyright (c) 2015, 2017 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
9 package org.opendaylight.openflowjava.nx.codec.action;
11 import com.google.common.net.InetAddresses;
12 import io.netty.buffer.ByteBuf;
13 import java.net.InetAddress;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.openflowjava.nx.api.NiciraActionDeserializerKey;
17 import org.opendaylight.openflowjava.nx.api.NiciraActionSerializerKey;
18 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrack;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrackBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.NxActionConntrackBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.nx.action.conntrack.CtActions;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.nx.action.conntrack.CtActionsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionCtMarkCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionCtMarkCaseBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionNatCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionNatCaseBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.ct.mark._case.NxActionCtMark;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.ct.mark._case.NxActionCtMarkBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.nat._case.NxActionNat;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.nat._case.NxActionNatBuilder;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * Action codec for conntrack.
43 * @author Aswin Suryanarayanan.
45 public class ConntrackCodec extends AbstractActionCodec {
46 private static final Logger LOG = LoggerFactory.getLogger(ConntrackCodec.class);
47 public static final int CT_LENGTH = 24;
48 public static final int NX_NAT_LENGTH = 16;
49 public static final int SHORT_LENGTH = 2;
50 public static final int INT_LENGTH = 4;
51 private static final int NXM_CT_MARK_FIELD_CODE = 107;
52 private static final int NXM_FIELD_CODE = 1;
53 private static final int SET_FIELD_LENGTH = 16;
54 private static final int SET_FIELD_CODE = 25;
56 public static final byte NXAST_CONNTRACK_SUBTYPE = 35;
57 public static final byte NXAST_NAT_SUBTYPE = 36;
58 public static final NiciraActionSerializerKey SERIALIZER_KEY =
59 new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionConntrack.class);
60 public static final NiciraActionDeserializerKey DESERIALIZER_KEY =
61 new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, NXAST_CONNTRACK_SUBTYPE);
64 public void serialize(final Action input, final ByteBuf outBuffer) {
65 LOG.trace("serialize :conntrack");
66 ActionConntrack action = (ActionConntrack) input.getActionChoice();
67 int length = getActionLength(action);
69 serializeHeader(length + pad + CT_LENGTH, NXAST_CONNTRACK_SUBTYPE, outBuffer);
71 outBuffer.writeShort(action.getNxActionConntrack().getFlags().shortValue());
72 outBuffer.writeInt(action.getNxActionConntrack().getZoneSrc().intValue());
73 outBuffer.writeShort(action.getNxActionConntrack().getConntrackZone().shortValue());
74 outBuffer.writeByte(action.getNxActionConntrack().getRecircTable().byteValue());
75 outBuffer.writeZero(5);
76 serializeCtAction(outBuffer,action);
79 private int getActionLength(final ActionConntrack action) {
81 List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
82 if (ctActionsList == null) {
85 for (CtActions ctActions : ctActionsList) {
86 if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
87 NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
88 NxActionNat natAction = nxActionNatCase.getNxActionNat();
89 int natLength = getNatActionLength(natAction);
90 int pad = 8 - natLength % 8;
91 length += natLength + pad;
92 } else if (ctActions.getOfpactActions() instanceof NxActionCtMarkCase) {
93 length += SET_FIELD_LENGTH;
96 LOG.trace("ActionLength :conntrack: length {}",length);
100 private int getNatActionLength(final NxActionNat natAction) {
101 int natLength = NX_NAT_LENGTH;
102 short rangePresent = natAction.getRangePresent().shortValue();
103 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
104 natLength += INT_LENGTH;
106 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
107 natLength += INT_LENGTH;
109 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
110 natLength += SHORT_LENGTH;
112 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
113 natLength += SHORT_LENGTH;
119 private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action) {
120 List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
121 if (ctActionsList != null) {
122 for (CtActions ctActions : ctActionsList) {
123 if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
124 NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
125 NxActionNat natAction = nxActionNatCase.getNxActionNat();
126 int natLength = getNatActionLength(natAction);
127 int pad = 8 - natLength % 8;
128 serializeHeader(natLength + pad, NXAST_NAT_SUBTYPE, outBuffer);
129 outBuffer.writeZero(2);
130 outBuffer.writeShort(natAction.getFlags().shortValue());
131 short rangePresent = natAction.getRangePresent().shortValue();
132 outBuffer.writeShort(rangePresent);
133 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
134 if (null != natAction.getIpAddressMin()) {
135 outBuffer.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(natAction
136 .getIpAddressMin().getIpv4Address()));
139 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
140 if (null != natAction.getIpAddressMax()) {
141 outBuffer.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(natAction
142 .getIpAddressMax().getIpv4Address()));
145 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
146 outBuffer.writeShort(natAction.getPortMin());
148 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
149 outBuffer.writeShort(natAction.getPortMax());
151 outBuffer.writeZero(pad);
152 } else if (ctActions.getOfpactActions() instanceof NxActionCtMarkCase) {
153 NxActionCtMarkCase nxActionCtMarkCase = (NxActionCtMarkCase)ctActions.getOfpactActions();
154 NxActionCtMark ctMarkAction = nxActionCtMarkCase.getNxActionCtMark();
157 // 00 19 - set field code
158 // 00 10 - set field length
160 // xx xx xx xx FIELD VALUE (4 bytes)
161 // xx xx xx xx PADDING (4 bytes)
163 outBuffer.writeShort(SET_FIELD_CODE);
164 outBuffer.writeShort(SET_FIELD_LENGTH);
165 outBuffer.writeZero(1);
166 outBuffer.writeByte(NXM_FIELD_CODE);
167 outBuffer.writeByte(NXM_CT_MARK_FIELD_CODE << 1);
168 outBuffer.writeByte(INT_LENGTH);
169 outBuffer.writeInt(ctMarkAction.getCtMark().intValue());
170 outBuffer.writeZero(INT_LENGTH);
172 // TODO: ct_mark mask is not supported yet
179 public Action deserialize(final ByteBuf message) {
180 final short length = deserializeCtHeader(message);
181 NxActionConntrackBuilder nxActionConntrackBuilder = new NxActionConntrackBuilder();
182 nxActionConntrackBuilder.setFlags(message.readUnsignedShort());
183 nxActionConntrackBuilder.setZoneSrc(message.readUnsignedInt());
184 nxActionConntrackBuilder.setConntrackZone(message.readUnsignedShort());
185 nxActionConntrackBuilder.setRecircTable(message.readUnsignedByte());
186 message.skipBytes(5);
188 if (length > CT_LENGTH) {
189 deserializeCtAction(message,nxActionConntrackBuilder, length - CT_LENGTH);
191 ActionBuilder actionBuilder = new ActionBuilder();
192 actionBuilder.setExperimenterId(getExperimenterId());
193 ActionConntrackBuilder actionConntrackBuilder = new ActionConntrackBuilder();
194 actionConntrackBuilder.setNxActionConntrack(nxActionConntrackBuilder.build());
195 actionBuilder.setActionChoice(actionConntrackBuilder.build());
196 return actionBuilder.build();
199 private void deserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder,
200 final int ctActionsLength) {
201 List<CtActions> ctActionsList = new ArrayList<>();
202 int processedCtActionsLength = ctActionsLength;
204 while (processedCtActionsLength > 0) {
205 int startReaderIndex = message.readerIndex();
207 if (EncodeConstants.EXPERIMENTER_VALUE == message.readUnsignedShort()) {
210 message.setIndex(startReaderIndex, message.writerIndex());
212 final int startIndex = message.readerIndex();
213 int length = deserializeCtHeader(message);
215 processedCtActionsLength = processedCtActionsLength - length;
216 NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
217 message.skipBytes(2);
218 nxActionNatBuilder.setFlags(message.readUnsignedShort());
220 int rangePresent = message.readUnsignedShort();
221 nxActionNatBuilder.setRangePresent(rangePresent);
222 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
223 InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
224 nxActionNatBuilder.setIpAddressMin(IpAddressBuilder.getDefaultInstance(address.getHostAddress()));
226 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
227 InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
228 nxActionNatBuilder.setIpAddressMax(IpAddressBuilder.getDefaultInstance(address.getHostAddress()));
230 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
231 nxActionNatBuilder.setPortMin(message.readUnsignedShort());
233 if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
234 nxActionNatBuilder.setPortMax(message.readUnsignedShort());
237 NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
238 caseBuilder.setNxActionNat(nxActionNatBuilder.build());
239 CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
240 ctActionsBuilder.setOfpactActions(caseBuilder.build());
241 ctActionsList.add(ctActionsBuilder.build());
242 int pad = length - (message.readerIndex() - startIndex);
243 message.skipBytes(pad);
245 // only other possible action here is currently ct_mark
247 message.setIndex(startReaderIndex, message.writerIndex());
248 processedCtActionsLength = processedCtActionsLength - SET_FIELD_LENGTH;
250 deserializeCtHeaderWithoutSubtype(message);
252 NxActionCtMarkBuilder nxActionCtMarkBuilder = new NxActionCtMarkBuilder();
253 nxActionCtMarkBuilder.setCtMark(message.readUnsignedInt());
255 NxActionCtMarkCaseBuilder caseBuilder = new NxActionCtMarkCaseBuilder();
256 caseBuilder.setNxActionCtMark(nxActionCtMarkBuilder.build());
257 CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
258 ctActionsBuilder.setOfpactActions(caseBuilder.build());
259 ctActionsList.add(ctActionsBuilder.build());
261 message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
265 nxActionConntrackBuilder.setCtActions(ctActionsList);
268 private short deserializeCtHeaderWithoutSubtype(final ByteBuf message) {
269 // size of experimenter type / size of set field code (in case of ct_mark)
270 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
272 short length = message.readShort();
273 // vendor id / 00 01 d6 04 (in case of ct_mark)
274 message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
278 private short deserializeCtHeader(final ByteBuf message) {
279 short length = deserializeCtHeaderWithoutSubtype(message);
281 message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);