ACL plugin support tagged subinterfaces 19/8519/7
authorPavel Kotucek <pkotucek@cisco.com>
Mon, 25 Sep 2017 07:44:05 +0000 (09:44 +0200)
committerDamjan Marion <dmarion.lists@gmail.com>
Wed, 8 Nov 2017 19:51:15 +0000 (19:51 +0000)
Change-Id: I92b351895c7efb26533c05512b91ead8ddbfb9c8
Signed-off-by: Pavel Kotucek <pkotucek@cisco.com>
src/plugins/acl/acl.c
src/plugins/acl/acl.h
test/test_acl_plugin_macip.py
test/vpp_papi_provider.py

index 50e9557..dc7f1eb 100644 (file)
@@ -318,12 +318,14 @@ acl_del_list (u32 acl_list_index)
 /* Some aids in ASCII graphing the content */
 #define XX "\377"
 #define __ "\000"
+#define DOT1AD "\210\250"
+#define DOT1Q "\201\00"
 #define _(x)
 #define v
 
 u8 ip4_5tuple_mask[] =
-_("             dmac               smac            etype ")
-_(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
+  _("             dmac               smac            etype ")
+  _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
   _("        v ihl totlen   ")
   _(0x0000)
   __ __ __ __
@@ -349,8 +351,8 @@ _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
   _(padeth)
   __ __;
 
    u8 ip6_5tuple_mask[] =
-       _("             dmac               smac            etype ")
+ u8 ip6_5tuple_mask[] =
+  _("             dmac               smac            etype ")
   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
   _("        v  tc + flow ")
   _(0x0000) __ __ __ __
@@ -369,12 +371,29 @@ _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v __ __ v
   _("L4T/U  sport dport   ")
   _(tcpudp) XX XX XX XX _(padpad) __ __ __ __ _(padeth) __ __;
 
+ u8 dot1q_5tuple_mask[] =
+   _("             dmac               smac          dot1q         etype ")
+   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v DOT1Q __ __ v XX XX v
+   _(padpad) __ __ __ __
+   _(padpad) __ __ __ __
+   _(padpad) __ __ __ __
+   _(padeth) __ __;
+
+ u8 dot1ad_5tuple_mask[] =
+   _("             dmac               smac          dot1ad                     etype ")
+   _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v DOT1AD __ __ DOT1Q __ __ v XX XX v
+   _(padpad) __ __ __ __
+   _(padpad) __ __ __ __
+   _(padeth) __ __;
+
 #undef XX
 #undef __
+#undef DOT1AD
+#undef DOT1Q
 #undef _
 #undef v
 
-     static int count_skip (u8 * p, u32 size)
+static int count_skip (u8 * p, u32 size)
 {
   u64 *p64 = (u64 *) p;
   /* Be tolerant to null pointer */
@@ -443,19 +462,24 @@ acl_classify_add_del_table_small (vnet_classify_main_t * cm, u8 * mask,
   return ret;
 }
 
-
 static int
 acl_unhook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
 {
   vnet_classify_main_t *cm = &vnet_classify_main;
   u32 ip4_table_index = ~0;
   u32 ip6_table_index = ~0;
+  u32 dot1q_table_index = ~0;
+  u32 dot1ad_table_index = ~0;
   void *oldheap = acl_set_heap(am);
 
   vec_validate_init_empty (am->acl_ip4_input_classify_table_by_sw_if_index,
                           sw_if_index, ~0);
   vec_validate_init_empty (am->acl_ip6_input_classify_table_by_sw_if_index,
                           sw_if_index, ~0);
+  vec_validate_init_empty (am->acl_dot1q_input_classify_table_by_sw_if_index,
+         sw_if_index, ~0);
+  vec_validate_init_empty (am->acl_dot1ad_input_classify_table_by_sw_if_index,
+         sw_if_index, ~0);
 
   /* switch to global heap while calling vnet_* functions */
   clib_mem_set_heap (cm->vlib_main->heap_base);
@@ -481,6 +505,26 @@ acl_unhook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
                                  am->l2_input_classify_next_acl_ip6,
                                  &ip6_table_index, 0);
     }
+  if (am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
+    {
+      dot1q_table_index =
+  am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index];
+      am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
+      acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask,
+          sizeof (ip6_5tuple_mask) - 1, ~0,
+          ~0,
+          &dot1q_table_index, 0);
+    }
+  if (am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
+    {
+      dot1ad_table_index =
+  am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index];
+      am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
+      acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+          sizeof (dot1ad_5tuple_mask) - 1, ~0,
+          ~0,
+          &dot1ad_table_index, 0);
+    }
   clib_mem_set_heap (oldheap);
   return 0;
 }
@@ -491,12 +535,18 @@ acl_unhook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
   vnet_classify_main_t *cm = &vnet_classify_main;
   u32 ip4_table_index = ~0;
   u32 ip6_table_index = ~0;
+  u32 dot1q_table_index = ~0;
+  u32 dot1ad_table_index = ~0;
   void *oldheap = acl_set_heap(am);
 
   vec_validate_init_empty (am->acl_ip4_output_classify_table_by_sw_if_index,
                           sw_if_index, ~0);
   vec_validate_init_empty (am->acl_ip6_output_classify_table_by_sw_if_index,
                           sw_if_index, ~0);
+  vec_validate_init_empty (am->acl_dot1q_output_classify_table_by_sw_if_index,
+         sw_if_index, ~0);
+  vec_validate_init_empty (am->acl_dot1ad_output_classify_table_by_sw_if_index,
+         sw_if_index, ~0);
 
   /* switch to global heap while calling vnet_* functions */
   clib_mem_set_heap (cm->vlib_main->heap_base);
@@ -523,16 +573,76 @@ acl_unhook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
                                  am->l2_output_classify_next_acl_ip6,
                                  &ip6_table_index, 0);
     }
+  if (am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
+    {
+      dot1q_table_index =
+  am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index];
+      am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
+      acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask,
+          sizeof (ip6_5tuple_mask) - 1, ~0,
+          ~0,
+          &dot1q_table_index, 0);
+    }
+  if (am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
+    {
+      dot1ad_table_index =
+  am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index];
+      am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
+      acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+          sizeof (dot1ad_5tuple_mask) - 1, ~0,
+          ~0,
+          &dot1ad_table_index, 0);
+    }
   clib_mem_set_heap (oldheap);
   return 0;
 }
 
+static void
+acl_add_vlan_session(acl_main_t * am, u32 table_index, u8 is_output, u8 is_dot1ad, u8 is_ip6)
+{
+  vnet_classify_main_t *cm = &vnet_classify_main;
+  u8 *match;
+  u32 next_acl;
+  u8 idx;
+  u8 session_idx;
+
+  if (is_ip6)
+    {
+  next_acl = (is_output)?am->l2_output_classify_next_acl_ip6:am->l2_input_classify_next_acl_ip6;
+    }
+  else
+    {
+  next_acl = (is_output)?am->l2_output_classify_next_acl_ip4:am->l2_input_classify_next_acl_ip4;
+    }
+  match = (is_dot1ad)?dot1ad_5tuple_mask:dot1q_5tuple_mask;
+  idx = (is_dot1ad)?20:16;
+
+  /* add sessions to vlan tables per ethernet_type */
+  if (is_ip6)
+    {
+  match[idx] = 0x86;
+  match[idx+1] = 0xdd;
+  session_idx = 1;
+    }
+  else
+    {
+  match[idx] = 0x08;
+  match[idx+1] = 0x00;
+  session_idx = 0;
+    }
+  vnet_classify_add_del_session (cm, table_index, match, next_acl,
+                                 session_idx, 0, 0, 0, 1);
+  memset (&match[idx], 0x00, 2);
+}
+
 static int
 acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
 {
   vnet_classify_main_t *cm = &vnet_classify_main;
   u32 ip4_table_index = ~0;
   u32 ip6_table_index = ~0;
+  u32 dot1q_table_index = ~0;
+  u32 dot1ad_table_index = ~0;
   int rv;
 
   void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
@@ -546,6 +656,7 @@ acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
                                &ip4_table_index, 1);
   if (rv)
     goto done;
+
   rv =
     acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask,
                                sizeof (ip6_5tuple_mask) - 1, ~0,
@@ -559,26 +670,68 @@ acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
                                  &ip4_table_index, 0);
       goto done;
     }
+
+  rv =
+    acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+        sizeof (dot1ad_5tuple_mask) - 1, ~0,
+        ~0, &dot1ad_table_index, 1);
+  rv =
+    acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask,
+        sizeof (dot1q_5tuple_mask) - 1, dot1ad_table_index,
+        ~0, &dot1q_table_index, 1);
+  if (rv)
+    {
+      acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+          sizeof (dot1ad_5tuple_mask) - 1, ~0,
+          ~0, &dot1ad_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask,
+          sizeof (ip6_5tuple_mask) - 1, ~0,
+          am->l2_input_classify_next_acl_ip6,
+          &ip6_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
+          sizeof (ip4_5tuple_mask) - 1, ~0,
+          am->l2_input_classify_next_acl_ip4,
+          &ip4_table_index, 0);
+      goto done;
+    }
+
   rv =
     vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
-                                      ip6_table_index, ~0);
+                                      ip6_table_index, dot1q_table_index);
+
   if (rv)
     {
+      acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
+          sizeof (ip4_5tuple_mask) - 1, ~0,
+          am->l2_input_classify_next_acl_ip4,
+          &ip4_table_index, 0);
       acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask,
                                  sizeof (ip6_5tuple_mask) - 1, ~0,
                                  am->l2_input_classify_next_acl_ip6,
                                  &ip6_table_index, 0);
-      acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
-                                 sizeof (ip4_5tuple_mask) - 1, ~0,
-                                 am->l2_input_classify_next_acl_ip4,
-                                 &ip4_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask,
+          sizeof (dot1q_5tuple_mask) - 1, ~0,
+          ~0, &dot1q_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+          sizeof (dot1ad_5tuple_mask) - 1, ~0,
+          ~0, &dot1ad_table_index, 0);
       goto done;
     }
 
+  /* add sessions to vlan tables per ethernet_type */
+  acl_add_vlan_session(am, dot1q_table_index, 0, 0, 0);
+  acl_add_vlan_session(am, dot1q_table_index, 0, 0, 1);
+  acl_add_vlan_session(am, dot1ad_table_index, 0, 1, 0);
+  acl_add_vlan_session(am, dot1ad_table_index, 0, 1, 1);
+
   am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] =
     ip4_table_index;
   am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] =
     ip6_table_index;
+  am->acl_dot1q_input_classify_table_by_sw_if_index[sw_if_index] =
+    dot1q_table_index;
+  am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] =
+    dot1ad_table_index;
 
   vnet_l2_input_classify_enable_disable (sw_if_index, 1);
 done:
@@ -592,6 +745,8 @@ acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
   vnet_classify_main_t *cm = &vnet_classify_main;
   u32 ip4_table_index = ~0;
   u32 ip6_table_index = ~0;
+  u32 dot1q_table_index = ~0;
+  u32 dot1ad_table_index = ~0;
   int rv;
 
   void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
@@ -618,9 +773,35 @@ acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
                                  &ip4_table_index, 0);
       goto done;
     }
+
+  rv =
+    acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+        sizeof (dot1ad_5tuple_mask) - 1, ~0,
+        ~0, &dot1ad_table_index, 1);
+  rv =
+    acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask,
+        sizeof (dot1q_5tuple_mask) - 1, dot1ad_table_index,
+        ~0, &dot1q_table_index, 1);
+  if (rv)
+    {
+      acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+          sizeof (dot1ad_5tuple_mask) - 1, ~0,
+          ~0, &dot1ad_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, ip6_5tuple_mask,
+          sizeof (ip6_5tuple_mask) - 1, ~0,
+          am->l2_output_classify_next_acl_ip6,
+          &ip6_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, ip4_5tuple_mask,
+          sizeof (ip4_5tuple_mask) - 1, ~0,
+          am->l2_output_classify_next_acl_ip4,
+          &ip4_table_index, 0);
+      goto done;
+    }
+
   rv =
     vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
-                                       ip6_table_index, ~0);
+                                       ip6_table_index, dot1q_table_index);
+
   clib_warning
     ("ACL enabling on interface sw_if_index %d, setting tables to the following: ip4: %d ip6: %d\n",
      sw_if_index, ip4_table_index, ip6_table_index);
@@ -634,13 +815,31 @@ acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
                                  sizeof (ip4_5tuple_mask) - 1, ~0,
                                  am->l2_output_classify_next_acl_ip4,
                                  &ip4_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask,
+          sizeof (dot1q_5tuple_mask) - 1, ~0,
+          ~0,
+          &dot1q_table_index, 0);
+      acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
+          sizeof (dot1ad_5tuple_mask) - 1, ~0,
+          ~0,
+          &dot1ad_table_index, 0);
       goto done;
     }
 
+  /* add sessions to vlan tables per ethernet_type */
+  acl_add_vlan_session(am, dot1q_table_index, 1, 0, 0);
+  acl_add_vlan_session(am, dot1q_table_index, 1, 0, 1);
+  acl_add_vlan_session(am, dot1ad_table_index, 1, 1, 0);
+  acl_add_vlan_session(am, dot1ad_table_index, 1, 1, 1);
+
   am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] =
     ip4_table_index;
   am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] =
     ip6_table_index;
+  am->acl_dot1q_output_classify_table_by_sw_if_index[sw_if_index] =
+    dot1q_table_index;
+  am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] =
+    dot1ad_table_index;
 
   vnet_l2_output_classify_enable_disable (sw_if_index, 1);
 done:
@@ -648,8 +847,6 @@ done:
   return rv;
 }
 
-
-
 int
 acl_interface_in_enable_disable (acl_main_t * am, u32 sw_if_index,
                                 int enable_disable)
@@ -917,6 +1114,8 @@ typedef struct
   u32 count;
   u32 table_index;
   u32 arp_table_index;
+  u32 dot1q_table_index;
+  u32 dot1ad_table_index;
 } macip_match_type_t;
 
 static u32
@@ -1007,6 +1206,8 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
          mvec[match_type_index].prefix_len = a->rules[i].src_prefixlen;
          mvec[match_type_index].is_ipv6 = a->rules[i].is_ipv6;
          mvec[match_type_index].table_index = ~0;
+    mvec[match_type_index].dot1q_table_index = ~0;
+    mvec[match_type_index].dot1ad_table_index = ~0;
        }
       mvec[match_type_index].count++;
     }
@@ -1047,8 +1248,36 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
     int mask_len;
     int is6 = mt->is_ipv6;
     int l3_src_offs = get_l3_src_offset(is6);
-    memset (mask, 0, sizeof (mask));
-    memcpy (&mask[6], mt->mac_mask, 6);
+    int tags;
+    u32 *last_tag_table;
+
+    /*
+     * create chained tables for VLAN (no-tags, dot1q and dot1ad) packets
+     */
+    l3_src_offs += 8;
+    for (tags = 2; tags >= 0; tags--)
+      {
+        memset (mask, 0, sizeof (mask));
+        memcpy (&mask[6], mt->mac_mask, 6);
+        switch (tags)
+          {
+          case 0:
+          default:
+            memset (&mask[12], 0xff, 2); /* ethernet protocol */
+            last_tag_table = &mt->table_index;
+            break;
+          case 1:
+            memset (&mask[12], 0xff, 2); /* VLAN tag1 */
+            memset (&mask[16], 0xff, 2); /* ethernet protocol */
+            last_tag_table = &mt->dot1q_table_index;
+            break;
+          case 2:
+            memset (&mask[12], 0xff, 2); /* VLAN tag1 */
+            memset (&mask[16], 0xff, 2); /* VLAN tag2 */
+            memset (&mask[20], 0xff, 2); /* ethernet protocol */
+            last_tag_table = &mt->dot1ad_table_index;
+            break;
+          }
     for (i = 0; i < (mt->prefix_len / 8); i++)
       {
        mask[l3_src_offs + i] = 0xff;
@@ -1065,9 +1294,13 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
     mask_len = ((l3_src_offs + ((mt->prefix_len+7) / 8) +
                 (sizeof (u32x4)-1))/sizeof(u32x4)) * sizeof (u32x4);
     acl_classify_add_del_table_small (cm, mask, mask_len, last_table,
-                               (~0 == last_table) ? 0 : ~0, &mt->table_index,
+                               (~0 == last_table) ? 0 : ~0, last_tag_table,
                                1);
-    last_table = mt->table_index;
+    last_table = *last_tag_table;
+
+    memset (&mask[12], 0, sizeof (mask)-12);
+    l3_src_offs -= 4;
+      }
   }
   a->ip4_table_index = last_table;
   a->ip6_table_index = last_table;
@@ -1080,30 +1313,63 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index)
       u32 metadata = 0;
       int is6 = a->rules[i].is_ipv6;
       int l3_src_offs = get_l3_src_offset(is6);
-      memset (mask, 0, sizeof (mask));
-      memcpy (&mask[6], a->rules[i].src_mac, 6);
-      memset (&mask[12], 0xff, 2); /* ethernet protocol */
-      if (is6)
-       {
-         memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
-         mask[12] = 0x86;
-         mask[13] = 0xdd;
-       }
-      else
-       {
-         memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
-         mask[12] = 0x08;
-         mask[13] = 0x00;
-       }
+      u32 tag_table;
+      int tags, eth;
+
       match_type_index =
-       macip_find_match_type (mvec, a->rules[i].src_mac_mask,
-                              a->rules[i].src_prefixlen,
-                              a->rules[i].is_ipv6);
+  macip_find_match_type (mvec, a->rules[i].src_mac_mask,
+             a->rules[i].src_prefixlen,
+             a->rules[i].is_ipv6);
       ASSERT(match_type_index != ~0);
-      /* add session to table mvec[match_type_index].table_index; */
-      vnet_classify_add_del_session (cm, mvec[match_type_index].table_index,
-                                    mask, a->rules[i].is_permit ? ~0 : 0, i,
-                                    0, action, metadata, 1);
+
+      l3_src_offs += 8;
+      for (tags = 2; tags >= 0; tags--)
+        {
+          memset (mask, 0, sizeof (mask));
+          memcpy (&mask[6], a->rules[i].src_mac, 6);
+          switch (tags)
+            {
+            case 0:
+            default:
+              tag_table = mvec[match_type_index].table_index;
+              eth = 12;
+              break;
+            case 1:
+              tag_table = mvec[match_type_index].dot1q_table_index;
+              mask[12] = 0x81;
+              mask[13] = 0x00;
+              eth = 16;
+              break;
+            case 2:
+              tag_table = mvec[match_type_index].dot1ad_table_index;
+              mask[12] = 0x88;
+              mask[13] = 0xa8;
+              mask[16] = 0x81;
+              mask[17] = 0x00;
+              eth = 20;
+              break;
+            }
+          if (is6)
+      {
+        memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip6, 16);
+        mask[eth] = 0x86;
+        mask[eth+1] = 0xdd;
+      }
+          else
+      {
+        memcpy (&mask[l3_src_offs], &a->rules[i].src_ip_addr.ip4, 4);
+        mask[eth] = 0x08;
+        mask[eth+1] = 0x00;
+      }
+
+          /* add session to table mvec[match_type_index].table_index; */
+          vnet_classify_add_del_session (cm, tag_table,
+                 mask, a->rules[i].is_permit ? ~0 : 0, i,
+                 0, action, metadata, 1);
+          memset (&mask[12], 0, sizeof (mask)-12);
+          l3_src_offs -= 4;
+        }
+
       /* add ARP table entry too */
       if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
         {
index bed22e5..d38c129 100644 (file)
@@ -179,6 +179,11 @@ typedef struct {
   u32 *acl_ip4_output_classify_table_by_sw_if_index;
   u32 *acl_ip6_output_classify_table_by_sw_if_index;
 
+  u32 *acl_dot1q_input_classify_table_by_sw_if_index;
+  u32 *acl_dot1ad_input_classify_table_by_sw_if_index;
+  u32 *acl_dot1q_output_classify_table_by_sw_if_index;
+  u32 *acl_dot1ad_output_classify_table_by_sw_if_index;
+
   /* MACIP (input) ACLs associated with the interfaces */
   u32 *macip_acl_by_sw_if_index;
 
index f10d6cc..d27458d 100644 (file)
@@ -9,16 +9,16 @@ from socket import inet_ntop, inet_pton, AF_INET, AF_INET6
 from struct import *
 from scapy.packet import Raw
 from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, UDP, TCP
+from scapy.layers.inet import IP, UDP
 from scapy.layers.inet6 import IPv6
 
 from framework import VppTestCase, VppTestRunner, running_extended_tests
 from vpp_lo_interface import VppLoInterface
+from vpp_papi_provider import L2_VTR_OP
+from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
 
 
-class TestMACIP(VppTestCase):
-    """MACIP Test Case"""
-
+class MethodHolder(VppTestCase):
     DEBUG = False
 
     BRIDGED = True
@@ -27,6 +27,11 @@ class TestMACIP(VppTestCase):
     IS_IP4 = False
     IS_IP6 = True
 
+    DOT1AD = "dot1ad"
+    DOT1Q = "dot1q"
+    PERMIT_TAGS = True
+    DENY_TAGS = False
+
     # rule types
     DENY = 0
     PERMIT = 1
@@ -49,19 +54,36 @@ class TestMACIP(VppTestCase):
         class VppTestCase) before running the test case, set test case related
         variables and configure VPP.
         """
-        super(TestMACIP, cls).setUpClass()
+        super(MethodHolder, cls).setUpClass()
 
         cls.pg_if_packet_sizes = [64, 512, 1518, 9018]  # packet sizes
-        cls.bd_id = 10
-        cls.remote_hosts_count = 250
+        cls.bd_id = 111
+        cls.remote_hosts_count = 200
 
         try:
-            # create 3 pg interfaces, 1 loopback interface
-            cls.create_pg_interfaces(range(3))
+            # create 4 pg interfaces, 1 loopback interface
+            cls.create_pg_interfaces(range(4))
             cls.create_loopback_interfaces(range(1))
 
+            # create 2 subinterfaces
+            cls.subifs = [
+                 VppDot1QSubint(cls, cls.pg1, 10),
+                 VppDot1ADSubint(cls, cls.pg2, 20, 300, 400),
+                 VppDot1QSubint(cls, cls.pg3, 30),
+                 VppDot1ADSubint(cls, cls.pg3, 40, 600, 700)]
+
+            cls.subifs[0].set_vtr(L2_VTR_OP.L2_POP_1,
+                                  inner=10, push1q=1)
+            cls.subifs[1].set_vtr(L2_VTR_OP.L2_POP_2,
+                                  outer=300, inner=400, push1q=1)
+            cls.subifs[2].set_vtr(L2_VTR_OP.L2_POP_1,
+                                  inner=30, push1q=1)
+            cls.subifs[3].set_vtr(L2_VTR_OP.L2_POP_2,
+                                  outer=600, inner=700, push1q=1)
+
             cls.interfaces = list(cls.pg_interfaces)
             cls.interfaces.extend(cls.lo_interfaces)
+            cls.interfaces.extend(cls.subifs)
 
             for i in cls.interfaces:
                 i.admin_up()
@@ -73,12 +95,18 @@ class TestMACIP(VppTestCase):
                 cls.pg0.sw_if_index, bd_id=cls.bd_id)
             cls.vapi.sw_interface_set_l2_bridge(
                 cls.pg1.sw_if_index, bd_id=cls.bd_id)
+            cls.vapi.sw_interface_set_l2_bridge(
+                cls.subifs[0].sw_if_index, bd_id=cls.bd_id)
+            cls.vapi.sw_interface_set_l2_bridge(
+                cls.subifs[1].sw_if_index, bd_id=cls.bd_id)
 
-            # Configure IPv4 addresses on loop interface and routed interface
+            # Configure IPv4/6 addresses on loop interface and routed interface
             cls.loop0.config_ip4()
             cls.loop0.config_ip6()
             cls.pg2.config_ip4()
             cls.pg2.config_ip6()
+            cls.pg3.config_ip4()
+            cls.pg3.config_ip6()
 
             # Configure MAC address binding to IPv4 neighbors on loop0
             cls.loop0.generate_remote_hosts(cls.remote_hosts_count)
@@ -90,22 +118,35 @@ class TestMACIP(VppTestCase):
 
             cls.loop0.configure_ipv4_neighbors()
             cls.loop0.configure_ipv6_neighbors()
+
+            # configure MAC address on pg3
+            cls.pg3.resolve_arp()
+            cls.pg3.resolve_ndp()
+
+            # configure MAC address on subifs
+            for i in cls.subifs:
+                i.config_ip4()
+                i.resolve_arp()
+                i.config_ip6()
+
             # configure MAC address on pg2
             cls.pg2.resolve_arp()
             cls.pg2.resolve_ndp()
 
             # Loopback BVI interface has remote hosts
-            # one half of hosts are behind pg0 second behind pg1
-            half = cls.remote_hosts_count // 2
-            cls.pg0.remote_hosts = cls.loop0.remote_hosts[:half]
-            cls.pg1.remote_hosts = cls.loop0.remote_hosts[half:]
+            # one half of hosts are behind pg0 second behind pg1,pg2,pg3 subifs
+            cls.pg0.remote_hosts = cls.loop0.remote_hosts[:100]
+            cls.subifs[0].remote_hosts = cls.loop0.remote_hosts[100:125]
+            cls.subifs[1].remote_hosts = cls.loop0.remote_hosts[125:150]
+            cls.subifs[2].remote_hosts = cls.loop0.remote_hosts[150:175]
+            cls.subifs[3].remote_hosts = cls.loop0.remote_hosts[175:]
 
         except Exception:
             super(TestMACIP, cls).tearDownClass()
             raise
 
     def setUp(self):
-        super(TestMACIP, self).setUp()
+        super(MethodHolder, self).setUp()
         self.reset_packet_infos()
         del self.ACLS[:]
 
@@ -113,13 +154,16 @@ class TestMACIP(VppTestCase):
         """
         Show various debug prints after each test.
         """
-        super(TestMACIP, self).tearDown()
+        super(MethodHolder, self).tearDown()
         if not self.vpp_dead:
             self.logger.info(self.vapi.ppcli("show interface address"))
             self.logger.info(self.vapi.ppcli("show hardware"))
             self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl"))
             self.logger.info(self.vapi.ppcli("sh acl-plugin macip interface"))
             self.logger.info(self.vapi.ppcli("sh classify tables verbose"))
+            self.logger.info(self.vapi.ppcli("sh acl-plugin acl"))
+            self.logger.info(self.vapi.ppcli("sh acl-plugin interface"))
+            self.logger.info(self.vapi.ppcli("sh acl-plugin tables"))
             # print self.vapi.ppcli("show interface address")
             # print self.vapi.ppcli("show hardware")
             # print self.vapi.ppcli("sh acl-plugin macip interface")
@@ -217,13 +261,13 @@ class TestMACIP(VppTestCase):
             src_mac += 1099511627776
         return acls
 
-    def apply_rules(self, acls):
+    def apply_macip_rules(self, acls):
         for acl in acls:
             reply = self.vapi.macip_acl_add(acl)
             self.assertEqual(reply.retval, 0)
             self.ACLS.append(reply.acl_index)
 
-    def verify_acls(self, acl_count, rules_count, expected_count=2):
+    def verify_macip_acls(self, acl_count, rules_count, expected_count=2):
         reply = self.macip_acl_dump_debug()
         for acl in range(2, (acl_count+1) * 2):
             self.assertEqual(reply[acl - 2].count, rules_count[acl/2-1])
@@ -243,8 +287,18 @@ class TestMACIP(VppTestCase):
         reply = self.vapi.macip_acl_dump()
         self.assertEqual(len(reply), 0)
 
+        intf_acls = self.vapi.ppcli("sh acl-plugin interface").split(
+            "\nsw_if_index")
+        for i_a in intf_acls:
+            ia = i_a.split(":")
+            if len(ia) == 3:
+                sw_if_index = int(ia[0])
+                acl_index = int(ia[2])
+                self.vapi.acl_interface_add_del(sw_if_index, acl_index, 0)
+                self.vapi.acl_del(acl_index)
+
     def create_stream(self, mac_type, ip_type, packet_count,
-                      src_ip_if, dst_ip_if, bridged_routed, is_ip6):
+                      src_if, dst_if, traffic, is_ip6, tags=PERMIT_TAGS):
         # exact MAC and exact IP
         # exact MAC and subnet of IPs
         # exact MAC and wildcard IP
@@ -256,15 +310,16 @@ class TestMACIP(VppTestCase):
         # OUI restricted MAC and wildcard IP
 
         packets = []
-        rules = []
+        macip_rules = []
+        acl_rules = []
         ip_permit = ""
         mac_permit = ""
         dst_mac = ""
         mac_rule = "00:00:00:00:00:00"
         mac_mask = "00:00:00:00:00:00"
         for p in range(0, packet_count):
-            remote_dst_index = p % len(dst_ip_if.remote_hosts)
-            remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index]
+            remote_dst_index = p % len(dst_if.remote_hosts)
+            remote_dst_host = dst_if.remote_hosts[remote_dst_index]
 
             dst_port = 1234 + p
             src_port = 4321 + p
@@ -276,14 +331,14 @@ class TestMACIP(VppTestCase):
             if not is_permit and mac_type == self.WILD_MAC:
                 denyIP = True
 
-            if bridged_routed == self.BRIDGED:
+            if traffic == self.BRIDGED:
                 if is_permit:
                     src_mac = remote_dst_host._mac
                     dst_mac = 'de:ad:00:00:00:00'
                     src_ip4 = remote_dst_host.ip4
-                    dst_ip4 = src_ip_if.remote_ip4
+                    dst_ip4 = src_if.remote_ip4
                     src_ip6 = remote_dst_host.ip6
-                    dst_ip6 = src_ip_if.remote_ip6
+                    dst_ip6 = src_if.remote_ip6
                     ip_permit = src_ip6 if is_ip6 else src_ip4
                     mac_permit = src_mac
                 if denyMAC:
@@ -298,16 +353,16 @@ class TestMACIP(VppTestCase):
                     if ip_type != self.WILD_IP:
                         src_mac = mac_permit
                     src_ip4 = remote_dst_host.ip4
-                    dst_ip4 = src_ip_if.remote_ip4
+                    dst_ip4 = src_if.remote_ip4
                     src_ip6 = remote_dst_host.ip6
-                    dst_ip6 = src_ip_if.remote_ip6
+                    dst_ip6 = src_if.remote_ip6
             else:
                 if is_permit:
                     src_mac = remote_dst_host._mac
-                    dst_mac = src_ip_if.local_mac
-                    src_ip4 = src_ip_if.remote_ip4
+                    dst_mac = src_if.local_mac
+                    src_ip4 = src_if.remote_ip4
                     dst_ip4 = remote_dst_host.ip4
-                    src_ip6 = src_ip_if.remote_ip6
+                    src_ip6 = src_if.remote_ip6
                     dst_ip6 = remote_dst_host.ip6
                     ip_permit = src_ip6 if is_ip6 else src_ip4
                     mac_permit = src_mac
@@ -324,12 +379,12 @@ class TestMACIP(VppTestCase):
                     if ip_type != self.WILD_IP:
                         src_mac = mac_permit
                     src_ip4 = remote_dst_host.ip4
-                    dst_ip4 = src_ip_if.remote_ip4
+                    dst_ip4 = src_if.remote_ip4
                     src_ip6 = remote_dst_host.ip6
-                    dst_ip6 = src_ip_if.remote_ip6
+                    dst_ip6 = src_if.remote_ip6
 
             if is_permit:
-                info = self.create_packet_info(src_ip_if, dst_ip_if)
+                info = self.create_packet_info(src_if, dst_if)
                 payload = self.info_to_payload(info)
             else:
                 payload = "to be blocked"
@@ -379,10 +434,34 @@ class TestMACIP(VppTestCase):
             packet[Raw].load += " mac:"+src_mac
 
             size = self.pg_if_packet_sizes[p % len(self.pg_if_packet_sizes)]
+            if isinstance(src_if, VppSubInterface):
+                size = size + 4
+            if isinstance(src_if, VppDot1QSubint):
+                if src_if is self.subifs[0]:
+                    if tags == self.PERMIT_TAGS:
+                        packet = src_if.add_dot1q_layer(packet, 10)
+                    else:
+                        packet = src_if.add_dot1q_layer(packet, 11)
+                else:
+                    if tags == self.PERMIT_TAGS:
+                        packet = src_if.add_dot1q_layer(packet, 30)
+                    else:
+                        packet = src_if.add_dot1q_layer(packet, 33)
+            elif isinstance(src_if, VppDot1ADSubint):
+                if src_if is self.subifs[1]:
+                    if tags == self.PERMIT_TAGS:
+                        packet = src_if.add_dot1ad_layer(packet, 300, 400)
+                    else:
+                        packet = src_if.add_dot1ad_layer(packet, 333, 444)
+                else:
+                    if tags == self.PERMIT_TAGS:
+                        packet = src_if.add_dot1ad_layer(packet, 600, 700)
+                    else:
+                        packet = src_if.add_dot1ad_layer(packet, 666, 777)
             self.extend_packet(packet, size)
             packets.append(packet)
 
-            # create suitable rule
+            # create suitable MACIP rule
             if mac_type == self.EXACT_MAC:
                 mac_rule = src_mac
                 mac_mask = "ff:ff:ff:ff:ff:ff"
@@ -422,38 +501,77 @@ class TestMACIP(VppTestCase):
                 prefix_len = 64 if is_ip6 else 16
             ip_rule = inet_pton(AF_INET6 if is_ip6 else AF_INET, ip)
 
+            # create suitable ACL rule
+            if is_permit:
+                rule_l4_sport = packet[UDP].sport
+                rule_l4_dport = packet[UDP].dport
+                rule_family = AF_INET6 if packet.haslayer(IPv6) else AF_INET
+                rule_prefix_len = 128 if packet.haslayer(IPv6) else 32
+                rule_l3_layer = IPv6 if packet.haslayer(IPv6) else IP
+                if packet.haslayer(IPv6):
+                    rule_l4_proto = packet[UDP].overload_fields[IPv6]['nh']
+                else:
+                    rule_l4_proto = packet[IP].proto
+
+                acl_rule = {
+                    'is_permit': is_permit,
+                    'is_ipv6': is_ip6,
+                    'src_ip_addr': inet_pton(rule_family,
+                                             packet[rule_l3_layer].src),
+                    'src_ip_prefix_len': rule_prefix_len,
+                    'dst_ip_addr': inet_pton(rule_family,
+                                             packet[rule_l3_layer].dst),
+                    'dst_ip_prefix_len': rule_prefix_len,
+                    'srcport_or_icmptype_first': rule_l4_sport,
+                    'srcport_or_icmptype_last': rule_l4_sport,
+                    'dstport_or_icmpcode_first': rule_l4_dport,
+                    'dstport_or_icmpcode_last': rule_l4_dport,
+                    'proto': rule_l4_proto}
+                acl_rules.append(acl_rule)
+
             if mac_type == self.WILD_MAC and ip_type == self.WILD_IP and p > 0:
                 continue
 
             if is_permit:
-                rule = ({'is_permit': is_permit,
-                         'is_ipv6': is_ip6,
-                         'src_ip_addr': ip_rule,
-                         'src_ip_prefix_len': prefix_len,
-                         'src_mac': mac_rule.replace(':', '').decode('hex'),
-                         'src_mac_mask': mac_mask.replace(':', '').decode(
-                             'hex')})
-                rules.append(rule)
+                macip_rule = ({
+                    'is_permit': is_permit,
+                    'is_ipv6': is_ip6,
+                    'src_ip_addr': ip_rule,
+                    'src_ip_prefix_len': prefix_len,
+                    'src_mac': mac_rule.replace(':', '').decode('hex'),
+                    'src_mac_mask': mac_mask.replace(':', '').decode('hex')})
+                macip_rules.append(macip_rule)
 
         # deny all other packets
         if not (mac_type == self.WILD_MAC and ip_type == self.WILD_IP):
-            rule = ({'is_permit': 0,
-                     'is_ipv6': is_ip6,
-                     'src_ip_addr': "",
-                     'src_ip_prefix_len': 0,
-                     'src_mac': "",
-                     'src_mac_mask': ""})
-            rules.append(rule)
-
-        return {'stream': packets, 'rules': rules}
+            macip_rule = ({'is_permit': 0,
+                           'is_ipv6': is_ip6,
+                           'src_ip_addr': "",
+                           'src_ip_prefix_len': 0,
+                           'src_mac': "",
+                           'src_mac_mask': ""})
+            macip_rules.append(macip_rule)
+
+        acl_rule = {'is_permit': 0,
+                    'is_ipv6': is_ip6}
+        acl_rules.append(acl_rule)
+        return {'stream': packets,
+                'macip_rules': macip_rules,
+                'acl_rules': acl_rules}
 
     def verify_capture(self, stream, capture, is_ip6):
-        p_l3 = IPv6 if is_ip6 else IP
-        if self.DEBUG:
-            for p in stream:
-                print p[Ether].src, p[Ether].dst, p[p_l3].src, p[p_l3].dst
-
-        acls = self.macip_acl_dump_debug()
+        """
+        :param stream:
+        :param capture:
+        :param is_ip6:
+        :return:
+        """
+        # p_l3 = IPv6 if is_ip6 else IP
+        # if self.DEBUG:
+        #     for p in stream:
+        #         print p[Ether].src, p[Ether].dst, p[p_l3].src, p[p_l3].dst
+        #
+        # acls = self.macip_acl_dump_debug()
 
         # TODO : verify
         # for acl in acls:
@@ -468,64 +586,112 @@ class TestMACIP(VppTestCase):
         #     data = p[Raw].load.split(':',1)[1]
         #     print p[p_l3].src, data
 
-    def run_traffic(self, mac_type, ip_type, bridged_routed, is_ip6, packets,
-                    do_not_expected_capture=False):
+    def run_traffic(self, mac_type, ip_type, traffic, is_ip6, packets,
+                    do_not_expected_capture=False, tags=None,
+                    apply_rules=True, isMACIP=True, permit_tags=PERMIT_TAGS):
         self.reset_packet_infos()
 
-        tx_if = self.pg0 if bridged_routed == self.BRIDGED else self.pg2
-        rx_if = self.pg2 if bridged_routed == self.BRIDGED else self.pg0
+        if tags is None:
+            tx_if = self.pg0 if traffic == self.BRIDGED else self.pg3
+            rx_if = self.pg3 if traffic == self.BRIDGED else self.pg0
+            src_if = self.pg3
+            dst_if = self.loop0
+        else:
+            if tags == self.DOT1Q:
+                if traffic == self.BRIDGED:
+                    tx_if = self.subifs[0]
+                    rx_if = self.pg0
+                    src_if = self.subifs[0]
+                    dst_if = self.loop0
+                else:
+                    tx_if = self.subifs[2]
+                    rx_if = self.pg0
+                    src_if = self.subifs[2]
+                    dst_if = self.loop0
+            elif tags == self.DOT1AD:
+                if traffic == self.BRIDGED:
+                    tx_if = self.subifs[1]
+                    rx_if = self.pg0
+                    src_if = self.subifs[1]
+                    dst_if = self.loop0
+                else:
+                    tx_if = self.subifs[3]
+                    rx_if = self.pg0
+                    src_if = self.subifs[3]
+                    dst_if = self.loop0
+            else:
+                return
 
         test_dict = self.create_stream(mac_type, ip_type, packets,
-                                       self.pg2, self.loop0,
-                                       bridged_routed,
-                                       is_ip6)
-
-        reply = self.vapi.macip_acl_add(test_dict['rules'])
-        self.assertEqual(reply.retval, 0)
-        acl_index = reply.acl_index
+                                       src_if, dst_if,
+                                       traffic, is_ip6,
+                                       tags=permit_tags)
 
-        self.vapi.macip_acl_interface_add_del(sw_if_index=tx_if.sw_if_index,
-                                              acl_index=acl_index)
-        reply = self.vapi.macip_acl_interface_get()
-        self.assertEqual(reply.acls[tx_if.sw_if_index], acl_index)
-        self.ACLS.append(reply.acls[tx_if.sw_if_index])
+        if apply_rules:
+            if isMACIP:
+                reply = self.vapi.macip_acl_add(test_dict['macip_rules'])
+            else:
+                reply = self.vapi.acl_add_replace(acl_index=4294967295,
+                                                  r=test_dict['acl_rules'])
+            self.assertEqual(reply.retval, 0)
+            acl_index = reply.acl_index
+
+            if isMACIP:
+                self.vapi.macip_acl_interface_add_del(
+                                                 sw_if_index=tx_if.sw_if_index,
+                                                 acl_index=acl_index)
+                reply = self.vapi.macip_acl_interface_get()
+                self.assertEqual(reply.acls[tx_if.sw_if_index], acl_index)
+                self.ACLS.append(reply.acls[tx_if.sw_if_index])
+            else:
+                self.vapi.acl_interface_add_del(
+                    sw_if_index=tx_if.sw_if_index, acl_index=acl_index)
+        else:
+            self.vapi.macip_acl_interface_add_del(
+                sw_if_index=tx_if.sw_if_index,
+                acl_index=0)
 
-        tx_if.add_stream(test_dict['stream'])
+        if not isinstance(src_if, VppSubInterface):
+            tx_if.add_stream(test_dict['stream'])
+        else:
+            tx_if.parent.add_stream(test_dict['stream'])
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start()
 
         if do_not_expected_capture:
             rx_if.get_capture(0)
         else:
-            packet_count = self.get_packet_count_for_if_idx(
-                self.loop0.sw_if_index)
-            if mac_type == self.WILD_MAC and ip_type == self.WILD_IP:
-                packet_count = packets if bridged_routed else packet_count
-            capture = rx_if.get_capture(packet_count)
+            if traffic == self.BRIDGED and mac_type == self.WILD_MAC and \
+                    ip_type == self.WILD_IP:
+                capture = rx_if.get_capture(packets)
+            else:
+                capture = rx_if.get_capture(
+                    self.get_packet_count_for_if_idx(dst_if.sw_if_index))
             self.verify_capture(test_dict['stream'], capture, is_ip6)
+        if not isMACIP:
+            self.vapi.acl_interface_add_del(sw_if_index=tx_if.sw_if_index,
+                                            acl_index=acl_index, is_add=0)
+            self.vapi.acl_del(acl_index)
 
     def run_test_acls(self, mac_type, ip_type, acl_count,
                       rules_count, traffic=None, ip=None):
-        self.apply_rules(self.create_rules(mac_type, ip_type, acl_count,
-                                           rules_count))
-        self.verify_acls(acl_count, rules_count)
+        self.apply_macip_rules(self.create_rules(mac_type, ip_type, acl_count,
+                                                 rules_count))
+        self.verify_macip_acls(acl_count, rules_count)
 
         if traffic is not None:
             self.run_traffic(self.EXACT_MAC, self.EXACT_IP, traffic, ip, 9)
 
+
+class TestMACIP_IP4(MethodHolder):
+    """MACIP with IP4 traffic"""
+
     def test_acl_bridged_ip4_exactMAC_exactIP(self):
         """ IP4 MACIP exactMAC|exactIP ACL bridged traffic
         """
         self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_exactMAC_exactIP(self):
-        """ IP6 MACIP exactMAC|exactIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_acl_bridged_ip4_exactMAC_subnetIP(self):
         """ IP4 MACIP exactMAC|subnetIP ACL bridged traffic
         """
@@ -533,13 +699,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_exactMAC_subnetIP(self):
-        """ IP6 MACIP exactMAC|subnetIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_acl_bridged_ip4_exactMAC_wildIP(self):
         """ IP4 MACIP exactMAC|wildIP ACL bridged traffic
         """
@@ -547,13 +706,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.EXACT_MAC, self.WILD_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_exactMAC_wildIP(self):
-        """ IP6 MACIP exactMAC|wildIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.EXACT_MAC, self.WILD_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_acl_bridged_ip4_ouiMAC_exactIP(self):
         """ IP4 MACIP ouiMAC|exactIP ACL bridged traffic
         """
@@ -561,13 +713,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.OUI_MAC, self.EXACT_IP,
                          self.BRIDGED, self.IS_IP4, 3)
 
-    def test_acl_bridged_ip6_ouiMAC_exactIP(self):
-        """ IP6 MACIP oui_MAC|exactIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.OUI_MAC, self.EXACT_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_acl_bridged_ip4_ouiMAC_subnetIP(self):
         """ IP4 MACIP ouiMAC|subnetIP ACL bridged traffic
         """
@@ -575,13 +720,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_ouiMAC_subnetIP(self):
-        """ IP6 MACIP ouiMAC|subnetIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_acl_bridged_ip4_ouiMAC_wildIP(self):
         """ IP4 MACIP ouiMAC|wildIP ACL bridged traffic
         """
@@ -589,13 +727,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.OUI_MAC, self.WILD_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_ouiMAC_wildIP(self):
-        """ IP6 MACIP ouiMAC|wildIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.OUI_MAC, self.WILD_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_ac_bridgedl_ip4_wildMAC_exactIP(self):
         """ IP4 MACIP wildcardMAC|exactIP ACL bridged traffic
         """
@@ -603,13 +734,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.WILD_MAC, self.EXACT_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_wildMAC_exactIP(self):
-        """ IP6 MACIP wildcardMAC|exactIP ACL bridged traffic
-        """
-
-        self.run_traffic(self.WILD_MAC, self.EXACT_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
     def test_acl_bridged_ip4_wildMAC_subnetIP(self):
         """ IP4 MACIP wildcardMAC|subnetIP ACL bridged traffic
         """
@@ -617,20 +741,148 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip6_wildMAC_subnetIP(self):
-        """ IP6 MACIP wildcardMAC|subnetIP ACL bridged traffic
+    def test_acl_bridged_ip4_wildMAC_wildIP(self):
+        """ IP4 MACIP wildcardMAC|wildIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.WILD_MAC, self.WILD_IP,
+                         self.BRIDGED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_exactMAC_exactIP(self):
+        """ IP4 MACIP exactMAC|exactIP ACL routed traffic
+        """
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_exactMAC_subnetIP(self):
+        """ IP4 MACIP exactMAC|subnetIP ACL routed traffic
+        """
+        self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_exactMAC_wildIP(self):
+        """ IP4 MACIP exactMAC|wildIP ACL routed traffic
+        """
+        self.run_traffic(self.EXACT_MAC, self.WILD_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_ouiMAC_exactIP(self):
+        """ IP4 MACIP ouiMAC|exactIP ACL routed traffic
+        """
+
+        self.run_traffic(self.OUI_MAC, self.EXACT_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_ouiMAC_subnetIP(self):
+        """ IP4 MACIP ouiMAC|subnetIP ACL routed traffic
+        """
+
+        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_ouiMAC_wildIP(self):
+        """ IP4 MACIP ouiMAC|wildIP ACL routed traffic
+        """
+
+        self.run_traffic(self.OUI_MAC, self.WILD_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_wildMAC_exactIP(self):
+        """ IP4 MACIP wildcardMAC|exactIP ACL routed traffic
+        """
+
+        self.run_traffic(self.WILD_MAC, self.EXACT_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_routed_ip4_wildMAC_subnetIP(self):
+        """ IP4 MACIP wildcardMAC|subnetIP ACL routed traffic
         """
 
         self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
+                         self.ROUTED, self.IS_IP4, 9)
 
-    def test_acl_bridged_ip4_wildMAC_wildIP(self):
-        """ IP4 MACIP wildcardMAC|wildIP ACL bridged traffic
+    def test_acl_routed_ip4_wildMAC_wildIP(self):
+        """ IP4 MACIP wildcardMAC|wildIP ACL
         """
 
         self.run_traffic(self.WILD_MAC, self.WILD_IP,
+                         self.ROUTED, self.IS_IP4, 9)
+
+    def test_acl_replace_traffic_ip4(self):
+        """ MACIP replace ACL with IP4 traffic
+        """
+        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
                          self.BRIDGED, self.IS_IP4, 9)
 
+        r = self.create_rules()
+        # replace acls #2, #3 with new
+        reply = self.vapi.macip_acl_add_replace(r[0], 0)
+        self.assertEqual(reply.retval, 0)
+        self.assertEqual(reply.acl_index, 0)
+
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
+                         self.BRIDGED, self.IS_IP4, 9, True)
+
+
+class TestMACIP_IP6(MethodHolder):
+    """MACIP with IP6 traffic"""
+
+    def test_acl_bridged_ip6_exactMAC_exactIP(self):
+        """ IP6 MACIP exactMAC|exactIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_exactMAC_subnetIP(self):
+        """ IP6 MACIP exactMAC|subnetIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_exactMAC_wildIP(self):
+        """ IP6 MACIP exactMAC|wildIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.EXACT_MAC, self.WILD_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_ouiMAC_exactIP(self):
+        """ IP6 MACIP oui_MAC|exactIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.OUI_MAC, self.EXACT_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_ouiMAC_subnetIP(self):
+        """ IP6 MACIP ouiMAC|subnetIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_ouiMAC_wildIP(self):
+        """ IP6 MACIP ouiMAC|wildIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.OUI_MAC, self.WILD_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_wildMAC_exactIP(self):
+        """ IP6 MACIP wildcardMAC|exactIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.WILD_MAC, self.EXACT_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+    def test_acl_bridged_ip6_wildMAC_subnetIP(self):
+        """ IP6 MACIP wildcardMAC|subnetIP ACL bridged traffic
+        """
+
+        self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
     def test_acl_bridged_ip6_wildMAC_wildIP(self):
         """ IP6 MACIP wildcardMAC|wildIP ACL bridged traffic
         """
@@ -638,12 +890,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.WILD_MAC, self.WILD_IP,
                          self.BRIDGED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_exactMAC_exactIP(self):
-        """ IP4 MACIP exactMAC|exactIP ACL routed traffic
-        """
-        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_exactMAC_exactIP(self):
         """ IP6 MACIP exactMAC|exactIP ACL routed traffic
         """
@@ -651,12 +897,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_exactMAC_subnetIP(self):
-        """ IP4 MACIP exactMAC|subnetIP ACL routed traffic
-        """
-        self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_exactMAC_subnetIP(self):
         """ IP6 MACIP exactMAC|subnetIP ACL routed traffic
         """
@@ -664,12 +904,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_exactMAC_wildIP(self):
-        """ IP4 MACIP exactMAC|wildIP ACL routed traffic
-        """
-        self.run_traffic(self.EXACT_MAC, self.WILD_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_exactMAC_wildIP(self):
         """ IP6 MACIP exactMAC|wildIP ACL routed traffic
         """
@@ -677,13 +911,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.EXACT_MAC, self.WILD_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_ouiMAC_exactIP(self):
-        """ IP4 MACIP ouiMAC|exactIP ACL routed traffic
-        """
-
-        self.run_traffic(self.OUI_MAC, self.EXACT_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_ouiMAC_exactIP(self):
         """ IP6 MACIP ouiMAC|exactIP ACL routed traffic
         """
@@ -691,13 +918,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.OUI_MAC, self.EXACT_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_ouiMAC_subnetIP(self):
-        """ IP4 MACIP ouiMAC|subnetIP ACL routed traffic
-        """
-
-        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_ouiMAC_subnetIP(self):
         """ IP6 MACIP ouiMAC|subnetIP ACL routed traffic
         """
@@ -705,13 +925,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_ouiMAC_wildIP(self):
-        """ IP4 MACIP ouiMAC|wildIP ACL routed traffic
-        """
-
-        self.run_traffic(self.OUI_MAC, self.WILD_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_ouiMAC_wildIP(self):
         """ IP6 MACIP ouiMAC|wildIP ACL routed traffic
         """
@@ -719,13 +932,6 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.OUI_MAC, self.WILD_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_wildMAC_exactIP(self):
-        """ IP4 MACIP wildcardMAC|exactIP ACL routed traffic
-        """
-
-        self.run_traffic(self.WILD_MAC, self.EXACT_IP,
-                         self.ROUTED, self.IS_IP4, 9)
-
     def test_acl_routed_ip6_wildMAC_exactIP(self):
         """ IP6 MACIP wildcardMAC|exactIP ACL routed traffic
         """
@@ -733,20 +939,39 @@ class TestMACIP(VppTestCase):
         self.run_traffic(self.WILD_MAC, self.EXACT_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip4_wildMAC_subnetIP(self):
-        """ IP4 MACIP wildcardMAC|subnetIP ACL routed traffic
+    def test_acl_routed_ip6_wildMAC_subnetIP(self):
+        """ IP6 MACIP wildcardMAC|subnetIP ACL routed traffic
         """
 
         self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
-                         self.ROUTED, self.IS_IP4, 9)
+                         self.ROUTED, self.IS_IP6, 9)
 
-    def test_acl_routed_ip6_wildMAC_subnetIP(self):
-        """ IP6 MACIP wildcardMAC|subnetIP ACL routed traffic
+    def test_acl_routed_ip6_wildMAC_wildIP(self):
+        """ IP6 MACIP wildcardMAC|wildIP ACL
         """
 
-        self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
+        self.run_traffic(self.WILD_MAC, self.WILD_IP,
                          self.ROUTED, self.IS_IP6, 9)
 
+    def test_acl_replace_traffic_ip6(self):
+        """ MACIP replace ACL with IP6 traffic
+        """
+        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
+                         self.BRIDGED, self.IS_IP6, 9)
+
+        r = self.create_rules()
+        # replace acls #2, #3 with new
+        reply = self.vapi.macip_acl_add_replace(r[0], 0)
+        self.assertEqual(reply.retval, 0)
+        self.assertEqual(reply.acl_index, 0)
+
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
+                         self.BRIDGED, self.IS_IP6, 9, True)
+
+
+class TestMACIP(MethodHolder):
+    """MACIP Tests"""
+
     def test_acl_1_2(self):
         """ MACIP ACL with 2 entries
         """
@@ -818,7 +1043,7 @@ class TestMACIP(VppTestCase):
 
         r1 = self.create_rules(acl_count=3, rules_count=[2, 2, 2])
         r2 = self.create_rules(mac_type=self.OUI_MAC, ip_type=self.SUBNET_IP)
-        self.apply_rules(r1)
+        self.apply_macip_rules(r1)
 
         acls_before = self.macip_acl_dump_debug()
 
@@ -853,43 +1078,14 @@ class TestMACIP(VppTestCase):
                 self.assertNotEqual(len(acl1.r), len(acl2.r))
                 self.assertNotEqual(acl1.r, acl2.r)
 
-    def test_acl_replace_traffic_ip4(self):
-        """ MACIP replace ACL with IP4 traffic
-        """
-        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
-                         self.BRIDGED, self.IS_IP4, 9)
-
-        r = self.create_rules()
-        # replace acls #2, #3 with new
-        reply = self.vapi.macip_acl_add_replace(r[0], 0)
-        self.assertEqual(reply.retval, 0)
-        self.assertEqual(reply.acl_index, 0)
-
-        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
-                         self.BRIDGED, self.IS_IP4, 9, True)
-
-    def test_acl_replace_traffic_ip6(self):
-        """ MACIP replace ACL with IP6 traffic
-        """
-        self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
-                         self.BRIDGED, self.IS_IP6, 9)
-
-        r = self.create_rules()
-        # replace acls #2, #3 with new
-        reply = self.vapi.macip_acl_add_replace(r[0], 0)
-        self.assertEqual(reply.retval, 0)
-        self.assertEqual(reply.acl_index, 0)
-
-        self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
-                         self.BRIDGED, self.IS_IP6, 9, True)
-
     def test_delete_intf(self):
         """ MACIP ACL delete intf with acl
         """
 
         intf_count = len(self.interfaces)+1
         intf = []
-        self.apply_rules(self.create_rules(acl_count=3, rules_count=[3, 5, 4]))
+        self.apply_macip_rules(self.create_rules(acl_count=3,
+                                                 rules_count=[3, 5, 4]))
 
         intf.append(VppLoInterface(self, 0))
         intf.append(VppLoInterface(self, 1))
@@ -942,19 +1138,85 @@ class TestMACIP(VppTestCase):
 
         self.assertEqual(len([x for x in reply.acls if x != 4294967295]), 0)
 
-    def test_acl_routed_ip4_wildMAC_wildIP(self):
-        """ IP4 MACIP wildcardMAC|wildIP ACL
-        """
 
-        self.run_traffic(self.WILD_MAC, self.WILD_IP,
-                         self.ROUTED, self.IS_IP4, 9)
+class TestACL_dot1q_bridged(MethodHolder):
+    """ACL on dot1q bridged subinterfaces Tests"""
 
-    def test_acl_routed_ip6_wildMAC_wildIP(self):
-        """ IP6 MACIP wildcardMAC|wildIP ACL
-        """
+    def test_acl_bridged_ip4_subif_dot1q(self):
+        """ IP4 ACL SubIf Dot1Q bridged traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
+                         self.IS_IP4, 9, tags=self.DOT1Q, isMACIP=False)
 
-        self.run_traffic(self.WILD_MAC, self.WILD_IP,
-                         self.ROUTED, self.IS_IP6, 9)
+    def test_acl_bridged_ip6_subif_dot1q(self):
+        """ IP6 ACL SubIf Dot1Q bridged traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
+                         self.IS_IP6, 9, tags=self.DOT1Q, isMACIP=False)
+
+
+class TestACL_dot1ad_bridged(MethodHolder):
+    """ACL on dot1ad bridged subinterfaces Tests"""
+
+    def test_acl_bridged_ip4_subif_dot1ad(self):
+        """ IP4 ACL SubIf Dot1AD bridged traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
+                         self.IS_IP4, 9, tags=self.DOT1AD, isMACIP=False)
+
+    def test_acl_bridged_ip6_subif_dot1ad(self):
+        """ IP6 ACL SubIf Dot1AD bridged traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
+                         self.IS_IP6, 9, tags=self.DOT1AD, isMACIP=False)
+
+
+class TestACL_dot1q_routed(MethodHolder):
+    """ACL on dot1q routed subinterfaces Tests"""
+
+    def test_acl_routed_ip4_subif_dot1q(self):
+        """ IP4 ACL SubIf Dot1Q routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP4, 9, tags=self.DOT1Q, isMACIP=False)
+
+    def test_acl_routed_ip6_subif_dot1q(self):
+        """ IP6 ACL SubIf Dot1Q routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP6, 9, tags=self.DOT1Q, isMACIP=False)
+
+    def test_acl_routed_ip4_subif_dot1q_deny_by_tags(self):
+        """ IP4 ACL SubIf wrong tags Dot1Q routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP4, 9, True, tags=self.DOT1Q, isMACIP=False,
+                         permit_tags=self.DENY_TAGS)
+
+    def test_acl_routed_ip6_subif_dot1q_deny_by_tags(self):
+        """ IP6 ACL SubIf wrong tags Dot1Q routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP6, 9, True, tags=self.DOT1Q, isMACIP=False,
+                         permit_tags=self.DENY_TAGS)
+
+
+class TestACL_dot1ad_routed(MethodHolder):
+    """ACL on dot1ad routed subinterfaces Tests"""
+
+    def test_acl_routed_ip6_subif_dot1ad(self):
+        """ IP6 ACL SubIf Dot1AD routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP6, 9, tags=self.DOT1AD, isMACIP=False)
+
+    def test_acl_routed_ip4_subif_dot1ad(self):
+        """ IP4 ACL SubIf Dot1AD routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP4, 9, tags=self.DOT1AD, isMACIP=False)
+
+    def test_acl_routed_ip6_subif_dot1ad_deny_by_tags(self):
+        """ IP6 ACL SubIf wrong tags Dot1AD routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP6, 9, True, tags=self.DOT1AD, isMACIP=False,
+                         permit_tags=self.DENY_TAGS)
+
+    def test_acl_routed_ip4_subif_dot1ad_deny_by_tags(self):
+        """ IP4 ACL SubIf wrong tags Dot1AD routed traffic"""
+        self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
+                         self.IS_IP4, 9, True, tags=self.DOT1AD, isMACIP=False,
+                         permit_tags=self.DENY_TAGS)
 
 
 if __name__ == '__main__':
index 495db95..5085ff2 100644 (file)
@@ -2493,6 +2493,23 @@ class VppPapiProvider(object):
                          'acls': acls},
                         expected_retval=expected_retval)
 
+    def acl_interface_add_del(self,
+                              sw_if_index,
+                              acl_index,
+                              is_add=1):
+        """ Add/Delete ACL to/from interface
+
+        :param sw_if_index:
+        :param acl_index:
+        :param is_add:  (Default value = 1)
+        """
+
+        return self.api(self.papi.acl_interface_add_del,
+                        {'is_add': is_add,
+                         'is_input': 1,
+                         'sw_if_index': sw_if_index,
+                         'acl_index': acl_index})
+
     def acl_dump(self, acl_index, expected_retval=0):
         return self.api(self.papi.acl_dump,
                         {'acl_index': acl_index},