* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
package org.opendaylight.openflowjava.nx.codec.action;
-import io.netty.buffer.ByteBuf;
+import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint16;
+import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint32;
+import static org.opendaylight.yangtools.yang.common.netty.ByteBufUtils.readUint8;
-import java.net.InetAddress;
+import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
-
import org.opendaylight.openflowjava.nx.api.NiciraActionDeserializerKey;
import org.opendaylight.openflowjava.nx.api.NiciraActionSerializerKey;
import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.ActionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.NxActionNatRangePresent;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionConntrackBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.aug.nx.action.ActionConntrack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.aug.nx.action.ActionConntrackBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.NxActionConntrackBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.nx.action.conntrack.CtActions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofj.nx.action.conntrack.grouping.nx.action.conntrack.CtActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionCtMarkCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionCtMarkCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionNatCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.NxActionNatCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.ct.mark._case.NxActionCtMark;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.ct.mark._case.NxActionCtMarkBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.nat._case.NxActionNat;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.ofpact.actions.ofpact.actions.nx.action.nat._case.NxActionNatBuilder;
+import org.opendaylight.yangtools.yang.common.Uint16;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.net.InetAddresses;
-
/**
+ * Action codec for conntrack.
+ *
* @author Aswin Suryanarayanan.
*/
-
public class ConntrackCodec extends AbstractActionCodec {
- private static final Logger LOG = LoggerFactory.getLogger( ConntrackCodec.class);
+ private static final Logger LOG = LoggerFactory.getLogger(ConntrackCodec.class);
public static final int CT_LENGTH = 24;
public static final int NX_NAT_LENGTH = 16;
public static final int SHORT_LENGTH = 2;
public static final int INT_LENGTH = 4;
+ private static final int NXM_CT_MARK_FIELD_CODE = 107;
+ private static final int NXM_FIELD_CODE = 1;
+ private static final int SET_FIELD_LENGTH = 16;
+ private static final int SET_FIELD_CODE = 25;
public static final byte NXAST_CONNTRACK_SUBTYPE = 35;
public static final byte NXAST_NAT_SUBTYPE = 36;
public static final NiciraActionSerializerKey SERIALIZER_KEY =
- new NiciraActionSerializerKey(EncodeConstants.OF13_VERSION_ID, ActionConntrack.class);
+ new NiciraActionSerializerKey(EncodeConstants.OF_VERSION_1_3, ActionConntrack.class);
public static final NiciraActionDeserializerKey DESERIALIZER_KEY =
- new NiciraActionDeserializerKey(EncodeConstants.OF13_VERSION_ID, NXAST_CONNTRACK_SUBTYPE);
+ new NiciraActionDeserializerKey(EncodeConstants.OF_VERSION_1_3, NXAST_CONNTRACK_SUBTYPE);
@Override
public void serialize(final Action input, final ByteBuf outBuffer) {
outBuffer.writeShort(action.getNxActionConntrack().getConntrackZone().shortValue());
outBuffer.writeByte(action.getNxActionConntrack().getRecircTable().byteValue());
outBuffer.writeZero(5);
- serializeCtAction(outBuffer,action, length);
+ serializeCtAction(outBuffer,action);
}
- private int getActionLength(final ActionConntrack action) {
+ private static int getActionLength(final ActionConntrack action) {
int length = 0;
List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
if (ctActionsList == null) {
}
for (CtActions ctActions : ctActionsList) {
if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
- length += NX_NAT_LENGTH;
NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
NxActionNat natAction = nxActionNatCase.getNxActionNat();
- short rangePresent = natAction.getRangePresent().shortValue();
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
- length += INT_LENGTH;
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
- length += INT_LENGTH;
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
- length += SHORT_LENGTH;
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
- length += SHORT_LENGTH;
- }
+ int natLength = getNatActionLength(natAction);
+ int pad = 8 - natLength % 8;
+ length += natLength + pad;
+ } else if (ctActions.getOfpactActions() instanceof NxActionCtMarkCase) {
+ length += SET_FIELD_LENGTH;
}
}
LOG.trace("ActionLength :conntrack: length {}",length);
return length;
}
- private void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action, final int length) {
+ private static int getNatActionLength(final NxActionNat natAction) {
+ int natLength = NX_NAT_LENGTH;
+ short rangePresent = natAction.getRangePresent().shortValue();
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
+ natLength += INT_LENGTH;
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
+ natLength += INT_LENGTH;
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
+ natLength += SHORT_LENGTH;
+ }
+ if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
+ natLength += SHORT_LENGTH;
+ }
+ return natLength;
+ }
+
+ private static void serializeCtAction(final ByteBuf outBuffer, final ActionConntrack action) {
List<CtActions> ctActionsList = action.getNxActionConntrack().getCtActions();
if (ctActionsList != null) {
for (CtActions ctActions : ctActionsList) {
- if (ctActions.getOfpactActions() instanceof NxActionNatCase){
+ if (ctActions.getOfpactActions() instanceof NxActionNatCase) {
NxActionNatCase nxActionNatCase = (NxActionNatCase)ctActions.getOfpactActions();
NxActionNat natAction = nxActionNatCase.getNxActionNat();
- int pad = length % 8;
- serializeHeader(length + pad, NXAST_NAT_SUBTYPE, outBuffer);
+ int natLength = getNatActionLength(natAction);
+ int pad = 8 - natLength % 8;
+ serializeHeader(natLength + pad, NXAST_NAT_SUBTYPE, outBuffer);
outBuffer.writeZero(2);
outBuffer.writeShort(natAction.getFlags().shortValue());
short rangePresent = natAction.getRangePresent().shortValue();
outBuffer.writeShort(rangePresent);
if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
- if (null != natAction.getIpAddressMin()) {
- outBuffer.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(natAction
- .getIpAddressMin().getIpv4Address()));
- }
+ writeIpv4Address(outBuffer, natAction.getIpAddressMin());
}
if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
- if (null != natAction.getIpAddressMax()) {
- outBuffer.writeBytes(IetfInetUtil.INSTANCE.ipv4AddressBytes(natAction
- .getIpAddressMax().getIpv4Address()));
- }
+ writeIpv4Address(outBuffer, natAction.getIpAddressMax());
}
if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
- outBuffer.writeShort(natAction.getPortMin());
+ outBuffer.writeShort(natAction.getPortMin().toJava());
}
if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
- outBuffer.writeShort(natAction.getPortMax());
+ outBuffer.writeShort(natAction.getPortMax().toJava());
}
outBuffer.writeZero(pad);
+ } else if (ctActions.getOfpactActions() instanceof NxActionCtMarkCase) {
+ NxActionCtMarkCase nxActionCtMarkCase = (NxActionCtMarkCase)ctActions.getOfpactActions();
+ NxActionCtMark ctMarkAction = nxActionCtMarkCase.getNxActionCtMark();
+
+ // structure:
+ // 00 19 - set field code
+ // 00 10 - set field length
+ // 00 01 d6 04
+ // xx xx xx xx FIELD VALUE (4 bytes)
+ // xx xx xx xx PADDING (4 bytes)
+
+ outBuffer.writeShort(SET_FIELD_CODE);
+ outBuffer.writeShort(SET_FIELD_LENGTH);
+ outBuffer.writeZero(1);
+ outBuffer.writeByte(NXM_FIELD_CODE);
+ outBuffer.writeByte(NXM_CT_MARK_FIELD_CODE << 1);
+ outBuffer.writeByte(INT_LENGTH);
+ outBuffer.writeInt(ctMarkAction.getCtMark().intValue());
+ outBuffer.writeZero(INT_LENGTH);
+
+ // TODO: ct_mark mask is not supported yet
}
}
}
@Override
public Action deserialize(final ByteBuf message) {
- short length = deserializeCtHeader(message);
- NxActionConntrackBuilder nxActionConntrackBuilder = new NxActionConntrackBuilder();
- nxActionConntrackBuilder.setFlags(message.readUnsignedShort());
- nxActionConntrackBuilder.setZoneSrc(message.readUnsignedInt());
- nxActionConntrackBuilder.setConntrackZone(message.readUnsignedShort());
- nxActionConntrackBuilder.setRecircTable(message.readUnsignedByte());
+ final short length = deserializeCtHeader(message);
+ final var nxActionConntrackBuilder = new NxActionConntrackBuilder()
+ .setFlags(readUint16(message))
+ .setZoneSrc(readUint32(message))
+ .setConntrackZone(readUint16(message))
+ .setRecircTable(readUint8(message));
message.skipBytes(5);
- if (length > CT_LENGTH) {
- dserializeCtAction(message,nxActionConntrackBuilder);
+
+ if (length > CT_LENGTH) {
+ deserializeCtAction(message, nxActionConntrackBuilder, length - CT_LENGTH);
}
- ActionBuilder actionBuilder = new ActionBuilder();
- actionBuilder.setExperimenterId(getExperimenterId());
- ActionConntrackBuilder actionConntrackBuilder = new ActionConntrackBuilder();
- actionConntrackBuilder.setNxActionConntrack(nxActionConntrackBuilder.build());
- actionBuilder.setActionChoice(actionConntrackBuilder.build());
- return actionBuilder.build();
+ return new ActionBuilder()
+ .setExperimenterId(getExperimenterId())
+ .setActionChoice(new ActionConntrackBuilder()
+ .setNxActionConntrack(nxActionConntrackBuilder.build())
+ .build())
+ .build();
}
- private void dserializeCtAction(final ByteBuf message, final NxActionConntrackBuilder nxActionConntrackBuilder) {
- deserializeCtHeader(message);
+ private static void deserializeCtAction(final ByteBuf message,
+ final NxActionConntrackBuilder nxActionConntrackBuilder, final int ctActionsLength) {
+ List<CtActions> ctActionsList = new ArrayList<>();
+ int processedCtActionsLength = ctActionsLength;
- NxActionNatBuilder nxActionNatBuilder = new NxActionNatBuilder();
- message.skipBytes(2);
- nxActionNatBuilder.setFlags(message.readUnsignedShort());
+ while (processedCtActionsLength > 0) {
+ final int startReaderIndex = message.readerIndex();
- int rangePresent = message.readUnsignedShort();
- nxActionNatBuilder.setRangePresent(rangePresent);
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue())) {
- InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
- nxActionNatBuilder.setIpAddressMin(new IpAddress(address.getHostAddress().toCharArray()));
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue())) {
- InetAddress address = InetAddresses.fromInteger((int)message.readUnsignedInt());
- nxActionNatBuilder.setIpAddressMax(new IpAddress(address.getHostAddress().toCharArray()));
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue())) {
- nxActionNatBuilder.setPortMin(message.readUnsignedShort());
- }
- if (0 != (rangePresent & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue())) {
- nxActionNatBuilder.setPortMax(message.readUnsignedShort());
+ if (EncodeConstants.EXPERIMENTER_VALUE == message.readUnsignedShort()) {
+ // NAT action
+ // reset indices
+ message.setIndex(startReaderIndex, message.writerIndex());
+
+ final int startIndex = message.readerIndex();
+ final int length = deserializeCtHeader(message);
+
+ processedCtActionsLength = processedCtActionsLength - length;
+ message.skipBytes(2);
+ final var nxActionNatBuilder = new NxActionNatBuilder()
+ .setFlags(readUint16(message));
+
+ final Uint16 rangePresent = readUint16(message);
+ nxActionNatBuilder.setRangePresent(rangePresent);
+
+ final int rangeBits = rangePresent.toJava();
+ if ((rangeBits & NxActionNatRangePresent.NXNATRANGEIPV4MIN.getIntValue()) != 0) {
+ nxActionNatBuilder.setIpAddressMin(readIpv4Address(message));
+ }
+ if ((rangeBits & NxActionNatRangePresent.NXNATRANGEIPV4MAX.getIntValue()) != 0) {
+ nxActionNatBuilder.setIpAddressMax(readIpv4Address(message));
+ }
+ if ((rangeBits & NxActionNatRangePresent.NXNATRANGEPROTOMIN.getIntValue()) != 0) {
+ nxActionNatBuilder.setPortMin(readUint16(message));
+ }
+ if ((rangeBits & NxActionNatRangePresent.NXNATRANGEPROTOMAX.getIntValue()) != 0) {
+ nxActionNatBuilder.setPortMax(readUint16(message));
+ }
+
+ ctActionsList.add(new CtActionsBuilder()
+ .setOfpactActions(new NxActionNatCaseBuilder()
+ .setNxActionNat(nxActionNatBuilder.build()).build())
+ .build());
+
+ // Padding
+ message.skipBytes(length - (message.readerIndex() - startIndex));
+ } else {
+ // only other possible action here is currently ct_mark
+ // reset indices
+ message.setIndex(startReaderIndex, message.writerIndex());
+ processedCtActionsLength = processedCtActionsLength - SET_FIELD_LENGTH;
+
+ deserializeCtHeaderWithoutSubtype(message);
+
+ ctActionsList.add(new CtActionsBuilder()
+ .setOfpactActions(new NxActionCtMarkCaseBuilder()
+ .setNxActionCtMark(new NxActionCtMarkBuilder()
+ .setCtMark(readUint32(message))
+ .build())
+ .build())
+ .build());
+
+ // Padding
+ message.skipBytes(Integer.BYTES);
+ }
}
- NxActionNatCaseBuilder caseBuilder = new NxActionNatCaseBuilder();
- caseBuilder.setNxActionNat(nxActionNatBuilder.build());
- CtActionsBuilder ctActionsBuilder = new CtActionsBuilder();
- ctActionsBuilder.setOfpactActions(caseBuilder.build());
- List<CtActions> ctActionsList = new ArrayList<>();
- ctActionsList.add(ctActionsBuilder.build());
+
nxActionConntrackBuilder.setCtActions(ctActionsList);
}
- private short deserializeCtHeader(final ByteBuf message) {
- // size of experimenter type
- message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ private static IpAddress readIpv4Address(final ByteBuf message) {
+ return new IpAddress(IetfInetUtil.ipv4AddressFor(message.readInt()));
+ }
+
+ private static void writeIpv4Address(final ByteBuf outBuffer, final IpAddress ipAddress) {
+ if (ipAddress != null) {
+ outBuffer.writeBytes(IetfInetUtil.ipv4AddressBytes(ipAddress.getIpv4Address()));
+ }
+ }
+
+ private static short deserializeCtHeaderWithoutSubtype(final ByteBuf message) {
+ // size of experimenter type / size of set field code (in case of ct_mark)
+ message.skipBytes(Short.BYTES);
// size of length
short length = message.readShort();
- // vendor id
- message.skipBytes(EncodeConstants.SIZE_OF_INT_IN_BYTES);
- // subtype
- message.skipBytes(EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
+ // vendor id / 00 01 d6 04 (in case of ct_mark)
+ message.skipBytes(Integer.BYTES);
return length;
}
-
-
+ private static short deserializeCtHeader(final ByteBuf message) {
+ short length = deserializeCtHeaderWithoutSubtype(message);
+ // subtype
+ message.skipBytes(Short.BYTES);
+ return length;
+ }
}