From a0a1b0e2af851e1a15286e5d5eb576eae5769a59 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Fri, 26 Aug 2016 12:37:45 +0200 Subject: HONEYCOMB-139: ietf-acl translation layer. IP6 L3 ACL support Other changes: - documentation update - eth + ip4 writer rafactoring + tests Change-Id: I1ac6a4e99dd4f12c870cbd749af6b98018294dd4 Signed-off-by: Marek Gradzki --- .../v3po/interfaces/acl/AceIp4Writer.java | 113 +++++++++------------ 1 file changed, 49 insertions(+), 64 deletions(-) (limited to 'v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java index ac110f98b..b2a9613fa 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java @@ -19,11 +19,11 @@ package io.fd.honeycomb.translate.v3po.interfaces.acl; import static com.google.common.base.Preconditions.checkArgument; import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.ipv4AddressNoZoneToArray; +import com.google.common.annotations.VisibleForTesting; import com.google.common.primitives.Ints; import javax.annotation.Nonnull; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; @@ -34,52 +34,61 @@ import org.openvpp.jvpp.core.future.FutureJVppCore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class AceIp4Writer extends AbstractAceWriter { +final class AceIp4Writer extends AbstractAceWriter { - private static final Logger LOG = LoggerFactory.getLogger(AceIp4Writer.class); - private static final int TABLE_MASK_LENGTH = 48; // number of bytes + @VisibleForTesting static final int MATCH_N_VECTORS = 3; // number of 16B vectors - static final int TABLE_MEM_SIZE = 8 * 1024; - private static final int IP_MASK_LENGTH = 32; // number of bits - private static final int IP_VERSION_OFFSET = 14; - private static final int DSCP_OFFSET = 15; - private static final int SRC_IP_OFFSET = 26; - private static final int DST_IP_OFFSET = 30; + private static final Logger LOG = LoggerFactory.getLogger(AceIp4Writer.class); + private static final int TABLE_MASK_LENGTH = 48; + private static final int IP4_MASK_BIT_LENGTH = 32; + + private static final int IP_VERSION_OFFSET = 14; // first 14 bytes represent L2 header (2x6 + etherType(2)) private static final int IP_VERSION_MASK = 0xf0; + private static final int DSCP_OFFSET = 15; private static final int DSCP_MASK = 0xfc; + private static final int IP4_LEN = 4; + private static final int SRC_IP_OFFSET = IP_VERSION_OFFSET + 12; + private static final int DST_IP_OFFSET = SRC_IP_OFFSET + IP4_LEN; public AceIp4Writer(@Nonnull final FutureJVppCore futureJVppCore) { super(futureJVppCore); } - @Override - public ClassifyAddDelTable getClassifyAddDelTableRequest(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, - @Nonnull final int nextTableIndex) { - checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); - final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); - - final ClassifyAddDelTable request = new ClassifyAddDelTable(); - request.isAdd = 1; - request.tableIndex = -1; // value not present + private static byte[] toByteMask(final int prefixLength) { + final long mask = ((1L << prefixLength) - 1) << (IP4_MASK_BIT_LENGTH - prefixLength); + return Ints.toByteArray((int) mask); + } - request.nbuckets = 1; // we expect exactly one session per table + private static byte[] toByteMask(final Ipv4Prefix ipv4Prefix) { + final int prefixLength = Byte.valueOf(ipv4Prefix.getValue().split("/")[1]); + return toByteMask(prefixLength); + } - if (action instanceof Permit) { - request.missNextIndex = 0; // for list of permit rules, deny (0) should be default action - } else { // deny is default value - request.missNextIndex = -1; // for list of deny rules, permit (-1) should be default action + private static byte[] toMatchValue(final Ipv4Prefix ipv4Prefix) { + final String[] split = ipv4Prefix.getValue().split("/"); + final byte[] addressBytes = ipv4AddressNoZoneToArray(split[0]); + final byte[] mask = toByteMask(Byte.valueOf(split[1])); + for (int i = 0; i < addressBytes.length; ++i) { + addressBytes[i] &= mask[i]; } + return addressBytes; + } - request.nextTableIndex = nextTableIndex; + @Override + public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, + @Nonnull final AceIp aceIp, + final int nextTableIndex) { + checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); + final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); + + final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); request.skipNVectors = 0; // match entire L2 and L3 header request.matchNVectors = MATCH_N_VECTORS; - request.memorySize = TABLE_MEM_SIZE; boolean aceIsEmpty = true; request.mask = new byte[TABLE_MASK_LENGTH]; - // First 14 bytes represent l2 header (2x6 + etherType(2)_ + // First 14 bytes represent l2 header (2x6 + etherType(2)) if (aceIp.getProtocol() != null) { // Internet Protocol number request.mask[IP_VERSION_OFFSET] = (byte) IP_VERSION_MASK; // first 4 bits } @@ -99,17 +108,18 @@ class AceIp4Writer extends AbstractAceWriter { if (ipVersion.getSourceIpv4Network() != null) { aceIsEmpty = false; - System.arraycopy(toByteMask(ipVersion.getSourceIpv4Network()), 0, request.mask, SRC_IP_OFFSET, 4); + System.arraycopy(toByteMask(ipVersion.getSourceIpv4Network()), 0, request.mask, SRC_IP_OFFSET, IP4_LEN); } if (ipVersion.getDestinationIpv4Network() != null) { aceIsEmpty = false; - System.arraycopy(toByteMask(ipVersion.getDestinationIpv4Network()), 0, request.mask, DST_IP_OFFSET, 4); + System + .arraycopy(toByteMask(ipVersion.getDestinationIpv4Network()), 0, request.mask, DST_IP_OFFSET, IP4_LEN); } if (aceIsEmpty) { throw new IllegalArgumentException( - String.format("Ace %s does not define packet field matches", aceIp.toString())); + String.format("Ace %s does not define packet field match values", aceIp.toString())); } if (LOG.isDebugEnabled()) { @@ -120,19 +130,13 @@ class AceIp4Writer extends AbstractAceWriter { } @Override - public ClassifyAddDelSession getClassifyAddDelSessionRequest(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, - @Nonnull final int tableIndex) { + public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, + @Nonnull final AceIp aceIp, + final int tableIndex) { checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); - final ClassifyAddDelSession request = new ClassifyAddDelSession(); - request.isAdd = 1; - request.tableIndex = tableIndex; - - if (action instanceof Permit) { - request.hitNextIndex = -1; - } // deny (0) is default value + final ClassifyAddDelSession request = createClassifySession(action, tableIndex); request.match = new byte[TABLE_MASK_LENGTH]; boolean noMatch = true; @@ -156,17 +160,18 @@ class AceIp4Writer extends AbstractAceWriter { if (ipVersion.getSourceIpv4Network() != null) { noMatch = false; - System.arraycopy(toMatchValue(ipVersion.getSourceIpv4Network()), 0, request.match, SRC_IP_OFFSET, 4); + System.arraycopy(toMatchValue(ipVersion.getSourceIpv4Network()), 0, request.match, SRC_IP_OFFSET, IP4_LEN); } if (ipVersion.getDestinationIpv4Network() != null) { noMatch = false; - System.arraycopy(toMatchValue(ipVersion.getDestinationIpv4Network()), 0, request.match, DST_IP_OFFSET, 4); + System.arraycopy(toMatchValue(ipVersion.getDestinationIpv4Network()), 0, request.match, DST_IP_OFFSET, + IP4_LEN); } if (noMatch) { throw new IllegalArgumentException( - String.format("Ace %s does not define neither source nor destination MAC address", aceIp.toString())); + String.format("Ace %s does not define packet field match values", aceIp.toString())); } if (LOG.isDebugEnabled()) { @@ -180,24 +185,4 @@ class AceIp4Writer extends AbstractAceWriter { protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { request.ip4TableIndex = tableIndex; } - - private static byte[] toByteMask(final int prefixLength) { - final long mask = ((1L << prefixLength) - 1) << (IP_MASK_LENGTH - prefixLength); - return Ints.toByteArray((int) mask); - } - - private static byte[] toByteMask(final Ipv4Prefix ipv4Prefix) { - final int prefixLength = Byte.valueOf(ipv4Prefix.getValue().split("/")[1]); - return toByteMask(prefixLength); - } - - private static byte[] toMatchValue(final Ipv4Prefix ipv4Prefix) { - final String[] split = ipv4Prefix.getValue().split("/"); - final byte[] addressBytes = ipv4AddressNoZoneToArray(split[0]); - final byte[] mask = toByteMask(Byte.valueOf(split[1])); - for (int i = 0; i < addressBytes.length; ++i) { - addressBytes[i] &= mask[i]; - } - return addressBytes; - } } -- cgit 1.2.3-korg