HONEYCOMB-238: provide interface mode as a part of ietf-acl configuration
authorMarek Gradzki <[email protected]>
Tue, 4 Oct 2016 11:08:51 +0000 (13:08 +0200)
committerMarek Gradzki <[email protected]>
Wed, 5 Oct 2016 11:54:27 +0000 (11:54 +0000)
- L2 only rules for L3 interfaces are not allowed by vpp
- describes other limitations of ietf-acl model implementation

Change-Id: If7e79e4bbfe3113b82e3411d9a951c409799a29f
Signed-off-by: Marek Gradzki <[email protected]>
12 files changed:
v3po/api/src/main/yang/v3po.yang
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AbstractAceWriter.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriter.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4Writer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6Writer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceWriter.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAClWriter.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizer.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriterTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4WriterTest.java
v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6WriterTest.java

index 96844b8..f17ee9a 100644 (file)
@@ -130,6 +130,13 @@ module v3po {
     }
   }
 
+  typedef interface-mode {
+    type enumeration {
+      enum "l2";
+      enum "l3";
+    }
+  }
+
   grouping bridge-domain-attributes {
     leaf flood {
       type boolean;
@@ -453,11 +460,21 @@ module v3po {
         ACL lists are merged into 3 type of acls (eth0, ip4 and ip6) that are supported by vpp.
         Then corresponding tables and sessions are created and assigned to the interface.
 
+        All ACEs for all assigned ACLs have to use the same packet-handling action (either deny or parmit).
+
         Assignment update/delete removes all created tables and sessions and repeats process described above.
         Update/delete of ACL lists referenced here is not permitted (assignment needs to be removed first).
 
         Read is supported only for acls that were created and assigned by Honeycomb agent
-        (corresponding metadata are present).";
+        (corresponding metadata are present).
+
+        Limitations (due to vpp limitations):
+        - egress rules are currently ignored (HONEYCOMB-234)
+        - L4 rules are currently not supported (limited support will by provided by HONEYCOMB-218)
+        - mixing L2/L3/L4 rules is currently not supported (limited support will by provided by HONEYCOMB-233)
+        - L2 only rules on L3 interfaces are not supported (not allowed by vpp,
+          in the future defining L2/L3 pairs should be partially supported)
+        - vlan tags are supported only for sub-interfaces defined as exact-match";
       list acl {
         key "type name";
 
@@ -469,6 +486,20 @@ module v3po {
           type acl:access-control-list-ref;
         }
       }
+
+      leaf mode {
+        type interface-mode;
+        default l3;
+        description
+          "The way ACLs are translated depends on the interface mode.
+           In case of L2 interfaces (bridge/interconnection)
+           classify tables are assigned as l2_table using input_acl_set_interface (ether type matching is automatically
+           added in case of L3 rules).
+           In case of L3 interfaces, classify tables are assigned as ip4/ip6 tables.
+
+           It is the user responsibility to choose mode that matches target interface.
+           ";
+      }
     }
   }
 
index 022726e..882c00a 100644 (file)
@@ -23,28 +23,29 @@ import com.google.common.annotations.VisibleForTesting;
 import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
 import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.List;
 import java.util.concurrent.CompletionStage;
 import java.util.stream.Collector;
 import javax.annotation.Nonnegative;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
 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.AceType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.VppBaseCallException;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
-import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 
 /**
- * Base writer for translation of ietf-acl model ACEs to VPP's classify tables and sessions.
- * <p/>
- * Creates one classify table with single session per ACE.
+ * Base writer for translation of ietf-acl model ACEs to VPP's classify tables and sessions. <p/> Creates one classify
+ * table with single session per ACE.
  *
  * @param <T> type of access control list entry
  */
@@ -60,7 +61,7 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe
     static final int VLAN_TAG_LEN = 4;
 
     private static final Collector<PacketHandling, ?, PacketHandling> SINGLE_ITEM_COLLECTOR =
-            RWUtils.singleItemCollector();
+        RWUtils.singleItemCollector();
 
     private final FutureJVppCore futureJVppCore;
 
@@ -73,12 +74,14 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe
      *
      * @param action         packet handling action (permit/deny)
      * @param ace            ACE to be translated
+     * @param mode           interface mode
      * @param nextTableIndex classify table index
      * @param vlanTags       number of vlan tags
      * @return classify table that represents given ACE
      */
     protected abstract ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action,
                                                                @Nonnull final T ace,
+                                                               @Nullable final InterfaceMode mode,
                                                                final int nextTableIndex,
                                                                final int vlanTags);
 
@@ -87,12 +90,14 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe
      *
      * @param action     packet handling action (permit/deny)
      * @param ace        ACE to be translated
+     * @param mode           interface mode
      * @param tableIndex classify table index for the given session
      * @param vlanTags   number of vlan tags
      * @return classify session that represents given ACE
      */
     protected abstract ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action,
                                                                    @Nonnull final T ace,
+                                                                   @Nullable final InterfaceMode mode,
                                                                    final int tableIndex,
                                                                    final int vlanTags);
 
@@ -106,29 +111,29 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe
 
     @Override
     public final void write(@Nonnull final InstanceIdentifier<?> id, @Nonnull final List<Ace> aces,
-                            @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags)
-            throws VppBaseCallException, WriteTimeoutException {
+                            final InterfaceMode mode, @Nonnull final InputAclSetInterface request,
+                            @Nonnegative final int vlanTags)
+        throws VppBaseCallException, WriteTimeoutException {
         final PacketHandling action = aces.stream().map(ace -> ace.getActions().getPacketHandling()).distinct()
-                .collect(SINGLE_ITEM_COLLECTOR);
+            .collect(SINGLE_ITEM_COLLECTOR);
 
         checkArgument(vlanTags >= 0 && vlanTags <= 2, "Number of vlan tags %s is not in [0,2] range");
-
         int nextTableIndex = -1;
         for (final Ace ace : aces) {
             // Create table + session per entry
 
             final ClassifyAddDelTable ctRequest =
-                    createClassifyTable(action, (T) ace.getMatches().getAceType(), nextTableIndex, vlanTags);
+                createClassifyTable(action, (T) ace.getMatches().getAceType(), mode, nextTableIndex, vlanTags);
             nextTableIndex = createClassifyTable(id, ctRequest);
             createClassifySession(id,
-                    createClassifySession(action, (T) ace.getMatches().getAceType(), nextTableIndex, vlanTags));
+                createClassifySession(action, (T) ace.getMatches().getAceType(), mode, nextTableIndex, vlanTags));
         }
         setClassifyTable(request, nextTableIndex);
     }
 
     private int createClassifyTable(@Nonnull final InstanceIdentifier<?> id,
                                     @Nonnull final ClassifyAddDelTable request)
-            throws VppBaseCallException, WriteTimeoutException {
+        throws VppBaseCallException, WriteTimeoutException {
         final CompletionStage<ClassifyAddDelTableReply> cs = futureJVppCore.classifyAddDelTable(request);
 
         final ClassifyAddDelTableReply reply = getReplyForWrite(cs.toCompletableFuture(), id);
@@ -137,7 +142,7 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe
 
     private void createClassifySession(@Nonnull final InstanceIdentifier<?> id,
                                        @Nonnull final ClassifyAddDelSession request)
-            throws VppBaseCallException, WriteTimeoutException {
+        throws VppBaseCallException, WriteTimeoutException {
         final CompletionStage<ClassifyAddDelSessionReply> cs = futureJVppCore.classifyAddDelSession(request);
 
         getReplyForWrite(cs.toCompletableFuture(), id);
index 167196e..38ac536 100644 (file)
 
 package io.fd.honeycomb.translate.v3po.interfaces.acl.ingress;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.annotations.VisibleForTesting;
 import io.fd.honeycomb.translate.vpp.util.MacTranslator;
 import java.util.List;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 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.matches.ace.type.AceEth;
 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -39,11 +43,18 @@ final class AceEthWriter extends AbstractAceWriter<AceEth> implements MacTransla
         super(futureJVppCore);
     }
 
+    private static void checkInterfaceMode(@Nullable final InterfaceMode mode) {
+        checkArgument(InterfaceMode.L2.equals(mode), "L2 rules are not allowed for interface in L3 mode");
+    }
+
     @Override
     public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action,
                                                    @Nonnull final AceEth aceEth,
-                                                   @Nonnull final int nextTableIndex,
+                                                   @Nullable final InterfaceMode mode,
+                                                   final int nextTableIndex,
                                                    final int vlanTags) {
+        checkInterfaceMode(mode);
+
         final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex);
 
         request.mask = new byte[16];
@@ -98,8 +109,11 @@ final class AceEthWriter extends AbstractAceWriter<AceEth> implements MacTransla
     @Override
     public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action,
                                                        @Nonnull final AceEth aceEth,
-                                                       @Nonnull final int tableIndex,
+                                                       @Nullable final InterfaceMode mode,
+                                                       final int tableIndex,
                                                        final int vlanTags) {
+        checkInterfaceMode(mode);
+
         final ClassifyAddDelSession request = createClassifySession(action, tableIndex);
 
         request.match = new byte[16];
index 63d430b..bbc1889 100644 (file)
@@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.primitives.Ints;
 import io.fd.honeycomb.translate.vpp.util.Ipv4Translator;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 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.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;
@@ -30,6 +31,7 @@ import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,7 +43,8 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla
     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 ETHER_TYPE_OFFSET = 12; // first 14 bytes represent L2 header (2x6)
+    private static final int IP_VERSION_OFFSET = ETHER_TYPE_OFFSET+2;
     private static final int IP_VERSION_MASK = 0xf0;
     private static final int DSCP_OFFSET = 15;
     private static final int DSCP_MASK = 0xfc;
@@ -77,6 +80,7 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla
     @Override
     public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action,
                                                    @Nonnull final AceIp aceIp,
+                                                   @Nullable final InterfaceMode mode,
                                                    final int nextTableIndex,
                                                    final int vlanTags) {
         checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp);
@@ -91,6 +95,12 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla
 
         final int baseOffset = getVlanTagsLen(vlanTags);
 
+        if (InterfaceMode.L2.equals(mode)) {
+            // in L2 mode we need to match ether type
+            request.mask[baseOffset + ETHER_TYPE_OFFSET] = (byte) 0xff;
+            request.mask[baseOffset + ETHER_TYPE_OFFSET + 1] = (byte) 0xff;
+        }
+
         // First 14 bytes represent l2 header (2x6 + etherType(2))
         if (aceIp.getProtocol() != null) { // Internet Protocol number
             request.mask[baseOffset + IP_VERSION_OFFSET] = (byte) IP_VERSION_MASK; // first 4 bits
@@ -134,6 +144,7 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla
     @Override
     public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action,
                                                        @Nonnull final AceIp aceIp,
+                                                       @Nullable final InterfaceMode mode,
                                                        final int tableIndex,
                                                        final int vlanTags) {
         checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp);
@@ -146,6 +157,12 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla
 
         final int baseOffset = getVlanTagsLen(vlanTags);
 
+        if (InterfaceMode.L2.equals(mode)) {
+            // match IP4 etherType (0x0800)
+            request.match[baseOffset + ETHER_TYPE_OFFSET] = 0x08;
+            request.match[baseOffset + ETHER_TYPE_OFFSET + 1] = 0x00;
+        }
+
         if (aceIp.getProtocol() != null) {
             request.match[baseOffset + IP_VERSION_OFFSET] =
                     (byte) (IP_VERSION_MASK & (aceIp.getProtocol().intValue() << 4));
index 94c12e5..a6f55ca 100644 (file)
@@ -23,6 +23,7 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.BitSet;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 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.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.AceIpv6;
@@ -31,6 +32,7 @@ import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,7 +44,8 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> {
     private static final int TABLE_MASK_LENGTH = 64;
     private static final int IP6_MASK_BIT_LENGTH = 128;
 
-    private static final int IP_VERSION_OFFSET = 14; // first 14 bytes represent L2 header (2x6 + etherType(2))
+    private static final int ETHER_TYPE_OFFSET = 12; // first 14 bytes represent L2 header (2x6)
+    private static final int IP_VERSION_OFFSET = ETHER_TYPE_OFFSET+2;
     private static final int IP_VERSION_MASK = 0xf0;
     private static final int DSCP_MASK1 = 0x0f;
     private static final int DSCP_MASK2 = 0xc0;
@@ -91,6 +94,7 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> {
     @Override
     public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action,
                                                    @Nonnull final AceIp aceIp,
+                                                   @Nullable final InterfaceMode mode,
                                                    final int nextTableIndex,
                                                    final int vlanTags) {
         checkArgument(aceIp.getAceIpVersion() instanceof AceIpv6, "Expected AceIpv6 version, but was %", aceIp);
@@ -105,6 +109,12 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> {
 
         final int baseOffset = getVlanTagsLen(vlanTags);
 
+        if (InterfaceMode.L2.equals(mode)) {
+            // in L2 mode we need to match ether type
+            request.mask[baseOffset + ETHER_TYPE_OFFSET] = (byte) 0xff;
+            request.mask[baseOffset + ETHER_TYPE_OFFSET + 1] = (byte) 0xff;
+        }
+
         if (aceIp.getProtocol() != null) {
             aceIsEmpty = false;
             request.mask[baseOffset + IP_VERSION_OFFSET] |= IP_VERSION_MASK;
@@ -157,6 +167,7 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> {
     @Override
     public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action,
                                                        @Nonnull final AceIp aceIp,
+                                                       @Nullable final InterfaceMode mode,
                                                        final int tableIndex,
                                                        final int vlanTags) {
         checkArgument(aceIp.getAceIpVersion() instanceof AceIpv6, "Expected AceIpv6 version, but was %", aceIp);
@@ -168,6 +179,12 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> {
 
         final int baseOffset = getVlanTagsLen(vlanTags);
 
+        if (InterfaceMode.L2.equals(mode)) {
+            // match IP6 etherType (0x86dd)
+            request.match[baseOffset + ETHER_TYPE_OFFSET] = (byte) 0x86;
+            request.match[baseOffset + ETHER_TYPE_OFFSET + 1] = (byte) 0xdd;
+        }
+
         if (aceIp.getProtocol() != null) {
             noMatch = false;
             request.match[baseOffset + IP_VERSION_OFFSET] |=
index a687d4a..2be3e09 100644 (file)
@@ -21,6 +21,7 @@ import java.util.List;
 import javax.annotation.Nonnegative;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import io.fd.vpp.jvpp.VppBaseCallException;
 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
@@ -34,12 +35,12 @@ interface AceWriter {
      * Translates list of ACEs to chain of classify tables. Each ACE is translated into one classify table with single
      * classify session. Also initializes input_acl_set_interface request message DTO with first classify table of the
      * chain that was created.
-     *
-     * @param id      uniquely identifies ietf-acl container
+     *  @param id      uniquely identifies ietf-acl container
      * @param aces    list of access control entries
+     * @param mode
      * @param request input_acl_set_interface request DTO
      */
     void write(@Nonnull final InstanceIdentifier<?> id, @Nonnull final List<Ace> aces,
-               @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags)
+               final InterfaceMode mode, @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags)
         throws VppBaseCallException, WriteTimeoutException;
 }
index 0fe9954..91c7794 100644 (file)
@@ -25,6 +25,14 @@ import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
 import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException;
 import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.VppBaseCallException;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
+import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface;
+import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
+import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +41,7 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnegative;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntries;
@@ -42,16 +51,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont
 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.AceIpVersion;
 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.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import io.fd.vpp.jvpp.VppBaseCallException;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
-import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply;
-import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface;
-import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply;
-import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
-import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply;
-import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -138,12 +140,13 @@ public final class IetfAClWriter implements JvppReplyConsumer {
     }
 
     void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, @Nonnull final List<Acl> acls,
-               @Nonnull final WriteContext writeContext)
+               @Nullable final InterfaceMode mode, @Nonnull final WriteContext writeContext)
             throws VppBaseCallException, WriteTimeoutException {
-        write(id, swIfIndex, acls, writeContext, 0);
+        write(id, swIfIndex, mode, acls, writeContext, 0);
     }
 
-    void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, @Nonnull final List<Acl> acls,
+    void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, final InterfaceMode mode,
+               @Nonnull final List<Acl> acls,
                @Nonnull final WriteContext writeContext, @Nonnegative final int numberOfTags)
             throws VppBaseCallException, WriteTimeoutException {
 
@@ -169,7 +172,7 @@ public final class IetfAClWriter implements JvppReplyConsumer {
             if (aceWriter == null) {
                 LOG.warn("AceProcessor for {} not registered. Skipping ACE.", aceType);
             } else {
-                aceWriter.write(id, aces, request, numberOfTags);
+                aceWriter.write(id, aces, mode, request, numberOfTags);
             }
         }
 
index 5ffb95a..b10dc36 100644 (file)
@@ -63,7 +63,7 @@ public class IetfAclCustomizer implements WriterCustomizer<Ingress> {
             "ietf-acl container does not define acl list");
 
         try {
-            aclWriter.write(id, ifIndex, accessLists.getAcl(), writeContext);
+            aclWriter.write(id, ifIndex, accessLists.getAcl(), accessLists.getMode(), writeContext);
         } catch (VppBaseCallException e) {
             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
         }
index 285ebce..c9068d7 100644 (file)
@@ -82,7 +82,7 @@ public class SubInterfaceIetfAclCustomizer implements WriterCustomizer<Ingress>
         final SubInterface subInterface = subInterfaceOptional.get();
 
         try {
-            aclWriter.write(id, subInterfaceIndex, accessLists.getAcl(), writeContext,
+            aclWriter.write(id, subInterfaceIndex, accessLists.getMode(), accessLists.getAcl(), writeContext,
                 getNumberOfTags(subInterface.getTags()));
         } catch (VppBaseCallException e) {
             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
index c352b51..c334d4a 100644 (file)
@@ -32,6 +32,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont
 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.AceEth;
 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.AceEthBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 
 public class AceEthWriterTest {
 
@@ -42,7 +43,7 @@ public class AceEthWriterTest {
     private AceEth aceEth;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         initMocks(this);
         writer = new AceEthWriter(jvpp);
         action = new DenyBuilder().setDeny(true).build();
@@ -55,9 +56,9 @@ public class AceEthWriterTest {
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest() throws Exception {
+    public void testCreateClassifyTable() {
         final int nextTableIndex = 42;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceEth, nextTableIndex, 0);
+        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceEth, InterfaceMode.L2, nextTableIndex, 0);
 
         assertEquals(1, request.isAdd);
         assertEquals(-1, request.tableIndex);
@@ -78,10 +79,15 @@ public class AceEthWriterTest {
         assertArrayEquals(expectedMask, request.mask);
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateClassifyTableForL3Interface() {
+        writer.createClassifyTable(action, aceEth, InterfaceMode.L3, 42, 0);
+    }
+
     @Test
-    public void testGetClassifyAddDelSessionRequest() throws Exception {
+    public void testCreateClassifySession() {
         final int tableIndex = 123;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceEth, tableIndex, 0);
+        final ClassifyAddDelSession request = writer.createClassifySession(action, aceEth, InterfaceMode.L2, tableIndex, 0);
 
         assertEquals(1, request.isAdd);
         assertEquals(tableIndex, request.tableIndex);
@@ -97,8 +103,13 @@ public class AceEthWriterTest {
         assertArrayEquals(expectedMatch, request.match);
     }
 
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateClassifySessionForL3Interface() {
+        writer.createClassifySession(action, aceEth, InterfaceMode.L3, 42, 0);
+    }
+
     @Test
-    public void testSetClassifyTable() throws Exception {
+    public void testSetClassifyTable() {
         final int tableIndex = 321;
         final InputAclSetInterface request = new InputAclSetInterface();
         writer.setClassifyTable(request, tableIndex);
index 85ee57f..3954ad4 100644 (file)
@@ -34,6 +34,7 @@ import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 
 public class AceIp4WriterTest {
 
@@ -59,7 +60,7 @@ public class AceIp4WriterTest {
     }
 
     private static void verifyTableRequest(final ClassifyAddDelTable request, final int nextTableIndex,
-                                           final int vlanTags) {
+                                           final int vlanTags, final boolean isL2) {
         assertEquals(1, request.isAdd);
         assertEquals(-1, request.tableIndex);
         assertEquals(1, request.nbuckets);
@@ -74,12 +75,17 @@ public class AceIp4WriterTest {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1,
             -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
         };
+
+        if (isL2) {
+            expectedMask[12] = (byte) 0xff;
+            expectedMask[13] = (byte) 0xff;
+        }
         AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMask, request.mask, vlanTags * VLAN_TAG_LEN);
 
     }
 
     private static void verifySessionRequest(final ClassifyAddDelSession request, final int tableIndex,
-                                             final int vlanTags) {
+                                             final int vlanTags, final boolean isL2) {
         assertEquals(1, request.isAdd);
         assertEquals(tableIndex, request.tableIndex);
         assertEquals(0, request.hitNextIndex);
@@ -89,55 +95,74 @@ public class AceIp4WriterTest {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 1, 2,
             4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
         };
+
+        if (isL2) {
+            expectedMatch[12] = (byte) 0x08;
+            expectedMatch[13] = (byte) 0x00;
+        }
         AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMatch, request.match, vlanTags * VLAN_TAG_LEN);
 
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest() throws Exception {
+    public void testCreateClassifyTable() throws Exception {
+        final int nextTableIndex = 42;
+        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, 0);
+        verifyTableRequest(request, nextTableIndex, 0, false);
+    }
+
+    @Test
+    public void testCreateClassifyTableForL2Interface() throws Exception {
         final int nextTableIndex = 42;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, nextTableIndex, 0);
-        verifyTableRequest(request, nextTableIndex, 0);
+        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L2, nextTableIndex, 0);
+        verifyTableRequest(request, nextTableIndex, 0, true);
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest1VlanTag() throws Exception {
+    public void testCreateClassifyTable1VlanTag() throws Exception {
         final int nextTableIndex = 42;
         final int vlanTags = 1;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, nextTableIndex, vlanTags);
-        verifyTableRequest(request, nextTableIndex, vlanTags);
+        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+        verifyTableRequest(request, nextTableIndex, vlanTags, false);
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest2VlanTags() throws Exception {
+    public void testCreateClassifyTable2VlanTags() throws Exception {
         final int nextTableIndex = 42;
         final int vlanTags = 2;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, nextTableIndex, vlanTags);
-        verifyTableRequest(request, nextTableIndex, vlanTags);
+        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+        verifyTableRequest(request, nextTableIndex, vlanTags, false);
+    }
+
+    @Test
+    public void testCreateClassifySession() throws Exception {
+        final int tableIndex = 123;
+        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, InterfaceMode.L3, tableIndex, 0);
+        verifySessionRequest(request, tableIndex, 0, false);
     }
 
     @Test
-    public void testGetClassifyAddDelSessionRequest() throws Exception {
+    public void testCreateClassifySessionForL2Interface() throws Exception {
         final int tableIndex = 123;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, tableIndex, 0);
-        verifySessionRequest(request, tableIndex, 0);
+        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, InterfaceMode.L2, tableIndex, 0);
+        verifySessionRequest(request, tableIndex, 0, true);
     }
 
     @Test
-    public void testGetClassifyAddDelSessionRequest1VlanTag() throws Exception {
+    public void testCreateClassifySession1VlanTag() throws Exception {
         final int tableIndex = 123;
         final int vlanTags = 1;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, tableIndex, vlanTags);
-        verifySessionRequest(request, tableIndex, vlanTags);
+        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags);
+        verifySessionRequest(request, tableIndex, vlanTags, false);
     }
 
     @Test
-    public void testGetClassifyAddDelSessionRequest2VlanTags() throws Exception {
+    public void testCreateClassifySession2VlanTags() throws Exception {
         final int tableIndex = 123;
         final int vlanTags = 2;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, tableIndex, vlanTags);
+        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags);
 
-        verifySessionRequest(request, tableIndex, vlanTags);
+        verifySessionRequest(request, tableIndex, vlanTags, false);
     }
 
     @Test
index 3f3c6f7..260d454 100644 (file)
@@ -35,6 +35,7 @@ import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
 
 public class AceIp6WriterTest {
 
@@ -45,7 +46,7 @@ public class AceIp6WriterTest {
     private AceIp aceIp;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         initMocks(this);
         writer = new AceIp6Writer(jvpp);
         action = new DenyBuilder().setDeny(true).build();
@@ -62,7 +63,7 @@ public class AceIp6WriterTest {
 
 
     private static void verifyTableRequest(final ClassifyAddDelTable request, final int nextTableIndex,
-                                           final int vlanTags) {
+                                           final int vlanTags, final boolean isL2) {
         assertEquals(1, request.isAdd);
         assertEquals(-1, request.tableIndex);
         assertEquals(1, request.nbuckets);
@@ -87,12 +88,16 @@ public class AceIp6WriterTest {
             // padding to multiple of 16B:
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0
         };
-        AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMask, request.mask, vlanTags * VLAN_TAG_LEN);
 
+        if (isL2) {
+            expectedMask[12] = (byte) 0xff;
+            expectedMask[13] = (byte) 0xff;
+        }
+        AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMask, request.mask, vlanTags * VLAN_TAG_LEN);
     }
 
     private static void verifySessionRequest(final ClassifyAddDelSession request, final int tableIndex,
-                                             final int vlanTags) {
+                                             final int vlanTags, final boolean isL2) {
         assertEquals(1, request.isAdd);
         assertEquals(tableIndex, request.tableIndex);
         assertEquals(0, request.hitNextIndex);
@@ -112,58 +117,85 @@ public class AceIp6WriterTest {
             // padding to multiple of 16B:
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0
         };
+
+        if (isL2) {
+            expectedMatch[12] = (byte) 0x86;
+            expectedMatch[13] = (byte) 0xdd;
+        }
         AceIpWriterTestUtils.assertArrayEqualsWithOffset(expectedMatch, request.match, vlanTags * VLAN_TAG_LEN);
 
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest() throws Exception {
+    public void testCreateClassifyTable() {
         final int nextTableIndex = 42;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, nextTableIndex, 0);
-        verifyTableRequest(request, nextTableIndex, 0);
+        final ClassifyAddDelTable request =
+            writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, 0);
+        verifyTableRequest(request, nextTableIndex, 0, false);
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest1VlanTag() throws Exception {
+    public void testCreateClassifyTableForL2Interface() {
+        final int nextTableIndex = 42;
+        final ClassifyAddDelTable request =
+            writer.createClassifyTable(action, aceIp, InterfaceMode.L2, nextTableIndex, 0);
+        verifyTableRequest(request, nextTableIndex, 0, true);
+    }
+
+    @Test
+    public void testCreateClassifyTable1VlanTag() {
         final int nextTableIndex = 42;
         final int vlanTags = 1;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, nextTableIndex, vlanTags);
-        verifyTableRequest(request, nextTableIndex, vlanTags);
+        final ClassifyAddDelTable request =
+            writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+        verifyTableRequest(request, nextTableIndex, vlanTags, false);
     }
 
     @Test
-    public void testGetClassifyAddDelTableRequest2VlanTag() throws Exception {
+    public void testCreateClassifyTable2VlanTags() {
         final int nextTableIndex = 42;
         final int vlanTags = 2;
-        final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, nextTableIndex, vlanTags);
-        verifyTableRequest(request, nextTableIndex, vlanTags);
+        final ClassifyAddDelTable request =
+            writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags);
+        verifyTableRequest(request, nextTableIndex, vlanTags, false);
+    }
+
+    @Test
+    public void testCreateClassifySession() {
+        final int tableIndex = 123;
+        final ClassifyAddDelSession request =
+            writer.createClassifySession(action, aceIp, InterfaceMode.L3, tableIndex, 0);
+        verifySessionRequest(request, tableIndex, 0, false);
     }
 
     @Test
-    public void testGetClassifyAddDelSessionRequest() throws Exception {
+    public void testCreateClassifySessionForL2Interface() {
         final int tableIndex = 123;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, tableIndex, 0);
-        verifySessionRequest(request, tableIndex, 0);
+        final ClassifyAddDelSession request =
+            writer.createClassifySession(action, aceIp, InterfaceMode.L2, tableIndex, 0);
+        verifySessionRequest(request, tableIndex, 0, true);
     }
 
     @Test
-    public void testGetClassifyAddDelSessionRequest1VlanTag() throws Exception {
+    public void testCreateClassifySession1VlanTag() {
         final int tableIndex = 123;
         final int vlanTags = 1;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, tableIndex, vlanTags);
-        verifySessionRequest(request, tableIndex, vlanTags);
+        final ClassifyAddDelSession request =
+            writer.createClassifySession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags);
+        verifySessionRequest(request, tableIndex, vlanTags, false);
     }
 
     @Test
-    public void testGetClassifyAddDelSessionRequest2VlanTag() throws Exception {
+    public void testCreateClassifySession2VlanTags() {
         final int tableIndex = 123;
         final int vlanTags = 2;
-        final ClassifyAddDelSession request = writer.createClassifySession(action, aceIp, tableIndex, vlanTags);
-        verifySessionRequest(request, tableIndex, vlanTags);
+        final ClassifyAddDelSession request =
+            writer.createClassifySession(action, aceIp, InterfaceMode.L3, tableIndex, vlanTags);
+        verifySessionRequest(request, tableIndex, vlanTags, false);
     }
 
     @Test
-    public void testSetClassifyTable() throws Exception {
+    public void testSetClassifyTable() {
         final int tableIndex = 321;
         final InputAclSetInterface request = new InputAclSetInterface();
         writer.setClassifyTable(request, tableIndex);