gbp: Add support for ACL 28/11628/18
authorMohsin Kazmi <sykazmi@cisco.com>
Tue, 17 Apr 2018 17:35:42 +0000 (19:35 +0200)
committerNeale Ranns <nranns@cisco.com>
Thu, 19 Jul 2018 07:51:32 +0000 (07:51 +0000)
Change-Id: I7513c41307e62068ab5d9739cac393675c6066f8
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
src/plugins/gbp/gbp.h
src/plugins/gbp/gbp_api.c
src/plugins/gbp/gbp_contract.c
src/plugins/gbp/gbp_contract.h
src/plugins/gbp/gbp_policy.c
src/plugins/gbp/gbp_policy_dpo.c
test/test_gbp.py

index 8672fd3..06612cd 100644 (file)
@@ -31,6 +31,8 @@
 #ifndef __GBP_H__
 #define __GBP_H__
 
+#include <plugins/acl/exports.h>
+
 #include <plugins/gbp/gbp_types.h>
 #include <plugins/gbp/gbp_endpoint.h>
 #include <plugins/gbp/gbp_endpoint_group.h>
 #include <plugins/gbp/gbp_subnet.h>
 #include <plugins/gbp/gbp_recirc.h>
 
+typedef struct
+{
+  u32 gbp_acl_user_id;
+  acl_plugin_methods_t acl_plugin;
+} gbp_main_t;
+
+extern gbp_main_t gbp_main;
+
 #endif
 
 /*
index 88b2cd1..1f24eed 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Get the API version number */
 #define vl_api_version(n,v) static u32 api_version=(v);
-#include <acl/acl_all_api_h.h>
+#include <gbp/gbp_all_api_h.h>
 #undef vl_api_version
 
 #include <vlibapi/api_helper_macros.h>
   _(GBP_CONTRACT_ADD_DEL, gbp_contract_add_del)             \
   _(GBP_CONTRACT_DUMP, gbp_contract_dump)
 
-/**
- * L2 Emulation Main
- */
-typedef struct gbp_main_t_
-{
-  u16 msg_id_base;
-} gbp_main_t;
+gbp_main_t gbp_main;
 
-static gbp_main_t gbp_main;
+static u16 msg_id_base;
 
-#define GBP_MSG_BASE gbp_main.msg_id_base
+#define GBP_MSG_BASE msg_id_base
 
 static void
 vl_api_gbp_endpoint_add_del_t_handler (vl_api_gbp_endpoint_add_del_t * mp)
@@ -418,7 +412,7 @@ gbp_contract_send_details (gbp_contract_t * gbpc, void *args)
 
   mp->contract.src_epg = ntohl (gbpc->gc_key.gck_src);
   mp->contract.dst_epg = ntohl (gbpc->gc_key.gck_dst);
-  mp->contract.acl_index = ntohl (gbpc->gc_acl_index);
+  mp->contract.acl_index = ntohl (gbpc->gc_value.gc_acl_index);
 
   vl_api_send_msg (ctx->reg, (u8 *) mp);
 
@@ -484,10 +478,11 @@ gbp_init (vlib_main_t * vm)
   gbp_main_t *gbpm = &gbp_main;
   u8 *name = format (0, "gbp_%08x%c", api_version, 0);
 
-  /* Ask for a correctly-sized block of API message decode slots */
-  gbpm->msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
-                                             VL_MSG_FIRST_AVAILABLE);
+  gbpm->gbp_acl_user_id = ~0;
 
+  /* Ask for a correctly-sized block of API message decode slots */
+  msg_id_base = vl_msg_api_get_msg_ids ((char *) name,
+                                       VL_MSG_FIRST_AVAILABLE);
   gbp_api_hookup (vm);
 
   /* Add our API messages to the global name_crc hash table */
index 71d8bcf..a536f89 100644 (file)
@@ -25,22 +25,64 @@ gbp_contract_db_t gbp_contract_db;
 void
 gbp_contract_update (epg_id_t src_epg, epg_id_t dst_epg, u32 acl_index)
 {
+  gbp_main_t *gm = &gbp_main;
+  u32 *acl_vec = 0;
+  gbp_contract_value_t value = {
+    .gc_lc_index = ~0,
+    .gc_acl_index = ~0,
+  };
+  uword *p;
+
   gbp_contract_key_t key = {
     .gck_src = src_epg,
     .gck_dst = dst_epg,
   };
 
-  hash_set (gbp_contract_db.gc_hash, key.as_u64, acl_index);
+  if (~0 == gm->gbp_acl_user_id)
+    {
+      acl_plugin_exports_init (&gm->acl_plugin);
+      gm->gbp_acl_user_id =
+       gm->acl_plugin.register_user_module ("GBP ACL", "src-epg", "dst-epg");
+    }
+
+  p = hash_get (gbp_contract_db.gc_hash, key.as_u64);
+  if (p != NULL)
+    {
+      value.as_u64 = p[0];
+    }
+  else
+    {
+      value.gc_lc_index =
+       gm->acl_plugin.get_lookup_context_index (gm->gbp_acl_user_id, src_epg,
+                                                dst_epg);
+      value.gc_acl_index = acl_index;
+      hash_set (gbp_contract_db.gc_hash, key.as_u64, value.as_u64);
+    }
+
+  if (value.gc_lc_index == ~0)
+    return;
+  vec_add1 (acl_vec, acl_index);
+  gm->acl_plugin.set_acl_vec_for_context (value.gc_lc_index, acl_vec);
+  vec_free (acl_vec);
 }
 
 void
 gbp_contract_delete (epg_id_t src_epg, epg_id_t dst_epg)
 {
+  gbp_main_t *gm = &gbp_main;
+  uword *p;
+  gbp_contract_value_t value;
   gbp_contract_key_t key = {
     .gck_src = src_epg,
     .gck_dst = dst_epg,
   };
 
+  p = hash_get (gbp_contract_db.gc_hash, key.as_u64);
+  if (p != NULL)
+    {
+      value.as_u64 = p[0];
+      gm->acl_plugin.put_lookup_context_index (value.gc_lc_index);
+    }
   hash_unset (gbp_contract_db.gc_hash, key.as_u64);
 }
 
@@ -48,14 +90,14 @@ void
 gbp_contract_walk (gbp_contract_cb_t cb, void *ctx)
 {
   gbp_contract_key_t key;
-  u32 acl_index;
+  gbp_contract_value_t value;
 
   /* *INDENT-OFF* */
-  hash_foreach(key.as_u64, acl_index, gbp_contract_db.gc_hash,
+  hash_foreach(key.as_u64, value.as_u64, gbp_contract_db.gc_hash,
   ({
     gbp_contract_t gbpc = {
       .gc_key = key,
-      .gc_acl_index = acl_index,
+      .gc_value = value,
     };
 
     if (!cb(&gbpc, ctx))
@@ -112,11 +154,14 @@ gbp_contract_cli (vlib_main_t * vm,
  * @cliexstart{set gbp contract [del] src-epg <ID> dst-epg <ID> acl-index <ACL>}
  * @cliexend
  ?*/
+/* *INDENT-OFF* */
 VLIB_CLI_COMMAND (gbp_contract_cli_node, static) =
 {
-.path = "gbp contract",.short_help =
-    "gbp contract [del] src-epg <ID> dst-epg <ID> acl-index <ACL>",.function
-    = gbp_contract_cli,};
+  .path = "gbp contract",
+  .short_help =
+    "gbp contract [del] src-epg <ID> dst-epg <ID> acl-index <ACL>",
+  .function = gbp_contract_cli,
+};
 /* *INDENT-ON* */
 
 static clib_error_t *
@@ -124,15 +169,15 @@ gbp_contract_show (vlib_main_t * vm,
                   unformat_input_t * input, vlib_cli_command_t * cmd)
 {
   gbp_contract_key_t key;
-  epg_id_t epg_id;
+  gbp_contract_value_t value;
 
   vlib_cli_output (vm, "Contracts:");
 
   /* *INDENT-OFF* */
-  hash_foreach (key.as_u64, epg_id, gbp_contract_db.gc_hash,
+  hash_foreach (key.as_u64, value.as_u64, gbp_contract_db.gc_hash,
   {
     vlib_cli_output (vm, "  {%d,%d} -> %d", key.gck_src,
-                     key.gck_dst, epg_id);
+                     key.gck_dst, value.gc_acl_index);
   });
   /* *INDENT-ON* */
 
index 1964098..75f2edc 100644 (file)
@@ -37,6 +37,25 @@ typedef struct gbp_contract_key_t_
   };
 } gbp_contract_key_t;
 
+/**
+ * The value for an Contract
+ */
+typedef struct gbp_contract_value_t_
+{
+  union
+  {
+    struct
+    {
+      /**
+       * lookup context and acl index
+       */
+      u32 gc_lc_index;
+      u32 gc_acl_index;
+    };
+    u64 as_u64;
+  };
+} gbp_contract_value_t;
+
 /**
  * A Group Based Policy Contract.
  *  Determines the ACL that applies to traffic pass between two endpoint groups
@@ -51,7 +70,7 @@ typedef struct gbp_contract_t_
   /**
    * The ACL to apply for packets from the source to the destination EPG
    */
-  u32 gc_acl_index;;
+  gbp_contract_value_t gc_value;
 } gbp_contract_t;
 
 /**
@@ -78,7 +97,7 @@ extern void gbp_contract_walk (gbp_contract_cb_t bgpe, void *ctx);
  */
 extern gbp_contract_db_t gbp_contract_db;
 
-always_inline u32
+always_inline u64
 gbp_acl_lookup (gbp_contract_key_t * key)
 {
   uword *p;
index 8f3fc76..3825464 100644 (file)
@@ -68,6 +68,7 @@ static uword
 gbp_policy (vlib_main_t * vm,
            vlib_node_runtime_t * node, vlib_frame_t * frame)
 {
+  gbp_main_t *gm = &gbp_main;
   gbp_policy_main_t *gpm = &gbp_policy_main;
   u32 n_left_from, *from, *to_next;
   u32 next_index;
@@ -86,9 +87,11 @@ gbp_policy (vlib_main_t * vm,
        {
          gbp_policy_next_t next0;
          gbp_contract_key_t key0;
+         gbp_contract_value_t value0 = {
+           .as_u64 = ~0,
+         };
          u32 bi0, sw_if_index0;
          vlib_buffer_t *b0;
-         u32 acl_index0;
 
          next0 = GBP_POLICY_NEXT_DENY;
          bi0 = from[0];
@@ -106,7 +109,6 @@ gbp_policy (vlib_main_t * vm,
          sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
          key0.gck_dst = gbp_port_to_epg (sw_if_index0);
          key0.gck_src = vnet_buffer2 (b0)->gbp.src_epg;
-         acl_index0 = ~0;
 
          if (~0 != key0.gck_src)
            {
@@ -120,20 +122,48 @@ gbp_policy (vlib_main_t * vm,
                }
              else
                {
-                 acl_index0 = gbp_acl_lookup (&key0);
+                 value0.as_u64 = gbp_acl_lookup (&key0);
 
-                 if (~0 != acl_index0)
+                 if (~0 != value0.gc_lc_index)
                    {
+                     fa_5tuple_opaque_t pkt_5tuple0;
+                     u8 action0 = 0;
+                     u32 acl_pos_p0, acl_match_p0;
+                     u32 rule_match_p0, trace_bitmap0;
+                     u8 *h0, l2_len0;
+                     u16 ether_type0;
+                     u8 is_ip60 = 0;
+
+                     l2_len0 = vnet_buffer (b0)->l2.l2_len;
+                     h0 = vlib_buffer_get_current (b0);
+
+                     ether_type0 =
+                       clib_net_to_host_u16 (*(u16 *) (h0 + l2_len0 - 2));
+
+                     is_ip60 = (ether_type0 == ETHERNET_TYPE_IP6) ? 1 : 0;
                      /*
-                      * TODO tests against the ACL
-                      */
-                     /*
-                      * ACL tables are not available outside of ACL plugin
-                      * until then bypass the ACL to next node
+                      * tests against the ACL
                       */
-                     next0 =
-                       vnet_l2_feature_next (b0, gpm->l2_output_feat_next,
-                                             L2OUTPUT_FEAT_GBP_POLICY);
+                     acl_plugin_fill_5tuple_inline (gm->
+                                                    acl_plugin.p_acl_main,
+                                                    value0.gc_lc_index, b0,
+                                                    is_ip60,
+                                                    /* is_input */ 0,
+                                                    /* is_l2_path */ 1,
+                                                    &pkt_5tuple0);
+                     acl_plugin_match_5tuple_inline (gm->
+                                                     acl_plugin.p_acl_main,
+                                                     value0.gc_lc_index,
+                                                     &pkt_5tuple0, is_ip60,
+                                                     &action0, &acl_pos_p0,
+                                                     &acl_match_p0,
+                                                     &rule_match_p0,
+                                                     &trace_bitmap0);
+
+                     if (action0 > 0)
+                       next0 =
+                         vnet_l2_feature_next (b0, gpm->l2_output_feat_next,
+                                               L2OUTPUT_FEAT_GBP_POLICY);
                    }
                }
            }
@@ -153,7 +183,7 @@ gbp_policy (vlib_main_t * vm,
                vlib_add_trace (vm, node, b0, sizeof (*t));
              t->src_epg = key0.gck_src;
              t->dst_epg = key0.gck_dst;
-             t->acl_index = acl_index0;
+             t->acl_index = value0.gc_acl_index;
            }
 
          /* verify speculative enqueue, maybe switch current next frame */
@@ -209,6 +239,7 @@ static clib_error_t *
 gbp_policy_init (vlib_main_t * vm)
 {
   gbp_policy_main_t *gpm = &gbp_policy_main;
+  clib_error_t *error = 0;
 
   /* Initialize the feature next-node indexes */
   feat_bitmap_init_next_nodes (vm,
@@ -217,7 +248,7 @@ gbp_policy_init (vlib_main_t * vm)
                               l2output_get_feat_names (),
                               gpm->l2_output_feat_next);
 
-  return 0;
+  return error;
 }
 
 VLIB_INIT_FUNCTION (gbp_policy_init);
index 0f62fb3..e2af1e6 100644 (file)
  * limitations under the License.
  */
 
-#include <plugins/gbp/gbp.h>
-#include <plugins/gbp/gbp_policy_dpo.h>
-#include <plugins/gbp/gbp_recirc.h>
-
 #include <vnet/dpo/dvr_dpo.h>
 #include <vnet/fib/ip4_fib.h>
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/dpo/load_balance.h>
 
+#include <plugins/gbp/gbp.h>
+#include <plugins/gbp/gbp_policy_dpo.h>
+#include <plugins/gbp/gbp_recirc.h>
+
 /**
  * DPO pool
  */
@@ -206,8 +206,9 @@ typedef enum
 always_inline uword
 gbp_policy_dpo_inline (vlib_main_t * vm,
                       vlib_node_runtime_t * node,
-                      vlib_frame_t * from_frame, fib_protocol_t fproto)
+                      vlib_frame_t * from_frame, u8 is_ip6)
 {
+  gbp_main_t *gm = &gbp_main;
   u32 n_left_from, next_index, *from, *to_next;
 
   from = vlib_frame_vector_args (from_frame);
@@ -224,8 +225,11 @@ gbp_policy_dpo_inline (vlib_main_t * vm,
       while (n_left_from > 0 && n_left_to_next > 0)
        {
          const gbp_policy_dpo_t *gpd0;
-         u32 bi0, next0, acl_index0;
+         u32 bi0, next0;
          gbp_contract_key_t key0;
+         gbp_contract_value_t value0 = {
+           .as_u64 = ~0,
+         };
          vlib_buffer_t *b0;
 
          bi0 = from[0];
@@ -235,7 +239,6 @@ gbp_policy_dpo_inline (vlib_main_t * vm,
          n_left_from -= 1;
          n_left_to_next -= 1;
          next0 = GBP_POLICY_DROP;
-         acl_index0 = ~0;
 
          b0 = vlib_get_buffer (vm, bi0);
          gpd0 =
@@ -256,18 +259,35 @@ gbp_policy_dpo_inline (vlib_main_t * vm,
                }
              else
                {
-                 acl_index0 = gbp_acl_lookup (&key0);
+                 value0.as_u64 = gbp_acl_lookup (&key0);
 
-                 if (~0 != acl_index0)
+                 if (~0 != value0.gc_lc_index)
                    {
+                     fa_5tuple_opaque_t pkt_5tuple0;
+                     u8 action0 = 0;
+                     u32 acl_pos_p0, acl_match_p0;
+                     u32 rule_match_p0, trace_bitmap0;
                      /*
-                      * TODO tests against the ACL
-                      */
-                     /*
-                      * ACL tables are not available outside of ACL plugin
-                      * until then bypass the ACL to next node
+                      * tests against the ACL
                       */
-                     next0 = gpd0->gpd_dpo.dpoi_next_node;
+                     acl_plugin_fill_5tuple_inline (gm->
+                                                    acl_plugin.p_acl_main,
+                                                    value0.gc_lc_index, b0,
+                                                    is_ip6,
+                                                    /* is_input */ 1,
+                                                    /* is_l2_path */ 0,
+                                                    &pkt_5tuple0);
+                     acl_plugin_match_5tuple_inline (gm->
+                                                     acl_plugin.p_acl_main,
+                                                     value0.gc_lc_index,
+                                                     &pkt_5tuple0, is_ip6,
+                                                     &action0, &acl_pos_p0,
+                                                     &acl_match_p0,
+                                                     &rule_match_p0,
+                                                     &trace_bitmap0);
+
+                     if (action0 > 0)
+                       next0 = gpd0->gpd_dpo.dpoi_next_node;
                    }
                }
            }
@@ -287,7 +307,7 @@ gbp_policy_dpo_inline (vlib_main_t * vm,
              tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
              tr->src_epg = key0.gck_src;
              tr->dst_epg = key0.gck_dst;
-             tr->acl_index = acl_index0;
+             tr->acl_index = value0.gc_acl_index;
            }
 
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
@@ -315,14 +335,14 @@ static uword
 ip4_gbp_policy_dpo (vlib_main_t * vm,
                    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
 {
-  return (gbp_policy_dpo_inline (vm, node, from_frame, FIB_PROTOCOL_IP4));
+  return (gbp_policy_dpo_inline (vm, node, from_frame, 0));
 }
 
 static uword
 ip6_gbp_policy_dpo (vlib_main_t * vm,
                    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
 {
-  return (gbp_policy_dpo_inline (vm, node, from_frame, FIB_PROTOCOL_IP6));
+  return (gbp_policy_dpo_inline (vm, node, from_frame, 1));
 }
 
 /* *INDENT-OFF* */
index 7ee4d76..b6faa12 100644 (file)
@@ -21,7 +21,7 @@ from util import mactobinary
 
 class VppGbpEndpoint(VppObject):
     """
-    GDB Endpoint
+    GBP Endpoint
     """
 
     @property
@@ -94,7 +94,7 @@ class VppGbpEndpoint(VppObject):
 
 class VppGbpRecirc(VppObject):
     """
-    GDB Recirculation Interface
+    GBP Recirculation Interface
     """
 
     def __init__(self, test, epg, recirc, is_ext=False):
@@ -134,7 +134,7 @@ class VppGbpRecirc(VppObject):
 
 class VppGbpSubnet(VppObject):
     """
-    GDB Subnet
+    GBP Subnet
     """
 
     def __init__(self, test, table_id, address, address_len,
@@ -199,7 +199,7 @@ class VppGbpSubnet(VppObject):
 
 class VppGbpEndpointGroup(VppObject):
     """
-    GDB Endpoint Group
+    GBP Endpoint Group
     """
 
     def __init__(self, test, epg, rd, bd, uplink,
@@ -250,7 +250,7 @@ class VppGbpEndpointGroup(VppObject):
 
 class VppGbpContract(VppObject):
     """
-    GDB Contract
+    GBP Contract
     """
 
     def __init__(self, test, src_epg, dst_epg, acl_index):
@@ -291,6 +291,61 @@ class VppGbpContract(VppObject):
         return False
 
 
+class VppGbpAcl(VppObject):
+    """
+    GBP Acl
+    """
+
+    def __init__(self, test):
+        self._test = test
+        self.acl_index = 4294967295
+
+    def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
+                    s_prefix=0, s_ip='\x00\x00\x00\x00', sport_from=0,
+                    sport_to=65535, d_prefix=0, d_ip='\x00\x00\x00\x00',
+                    dport_from=0, dport_to=65535):
+        if proto == -1 or proto == 0:
+            sport_to = 0
+            dport_to = sport_to
+        elif proto == 1 or proto == 58:
+            sport_to = 255
+            dport_to = sport_to
+        rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
+                 'srcport_or_icmptype_first': sport_from,
+                 'srcport_or_icmptype_last': sport_to,
+                 'src_ip_prefix_len': s_prefix,
+                 'src_ip_addr': s_ip,
+                 'dstport_or_icmpcode_first': dport_from,
+                 'dstport_or_icmpcode_last': dport_to,
+                 'dst_ip_prefix_len': d_prefix,
+                 'dst_ip_addr': d_ip})
+        return rule
+
+    def add_vpp_config(self, rules):
+
+        reply = self._test.vapi.acl_add_replace(self.acl_index,
+                                                r=rules,
+                                                tag='GBPTest')
+        self.acl_index = reply.acl_index
+        return self.acl_index
+
+    def remove_vpp_config(self):
+        self._test.vapi.acl_del(self.acl_index)
+
+    def __str__(self):
+        return self.object_id()
+
+    def object_id(self):
+        return "gbp-acl;[%d]" % (self.acl_index)
+
+    def query_vpp_config(self):
+        cs = self._test.vapi.acl_dump()
+        for c in cs:
+            if c.acl_index == self.acl_index:
+                return True
+        return False
+
+
 class TestGBP(VppTestCase):
     """ GBP Test Case """
 
@@ -875,7 +930,11 @@ class TestGBP(VppTestCase):
         #
         # A uni-directional contract from EPG 220 -> 221
         #
-        c1 = VppGbpContract(self, 220, 221, 0)
+        acl = VppGbpAcl(self)
+        rule = acl.create_rule(permit_deny=1, proto=17)
+        rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
+        acl_index = acl.add_vpp_config([rule, rule2])
+        c1 = VppGbpContract(self, 220, 221, acl_index)
         c1.add_vpp_config()
 
         self.send_and_expect_bridged(self.pg0,
@@ -887,7 +946,7 @@ class TestGBP(VppTestCase):
         #
         # contract for the return direction
         #
-        c2 = VppGbpContract(self, 221, 220, 0)
+        c2 = VppGbpContract(self, 221, 220, acl_index)
         c2.add_vpp_config()
 
         self.send_and_expect_bridged(self.pg0,
@@ -907,7 +966,7 @@ class TestGBP(VppTestCase):
         #
         # A uni-directional contract from EPG 220 -> 222 'L3 routed'
         #
-        c3 = VppGbpContract(self, 220, 222, 0)
+        c3 = VppGbpContract(self, 220, 222, acl_index)
         c3.add_vpp_config()
 
         self.logger.info(self.vapi.cli("sh gbp contract"))
@@ -923,6 +982,7 @@ class TestGBP(VppTestCase):
         c2.remove_vpp_config()
         c1.remove_vpp_config()
         c3.remove_vpp_config()
+        acl.remove_vpp_config()
 
         self.send_and_assert_no_replies(self.pg2,
                                         pkt_inter_epg_221_to_220 * 65)
@@ -988,7 +1048,15 @@ class TestGBP(VppTestCase):
         self.send_and_assert_no_replies(self.pg0,
                                         pkt_inter_epg_220_to_global * 65)
 
-        c4 = VppGbpContract(self, 220, 333, 0)
+        acl2 = VppGbpAcl(self)
+        rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
+                                sport_to=1234, dport_from=1234, dport_to=1234)
+        rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
+                                 sport_from=1234, sport_to=1234,
+                                 dport_from=1234, dport_to=1234)
+
+        acl_index2 = acl2.add_vpp_config([rule, rule2])
+        c4 = VppGbpContract(self, 220, 333, acl_index2)
         c4.add_vpp_config()
 
         self.send_and_expect_natted(self.pg0,
@@ -1020,7 +1088,7 @@ class TestGBP(VppTestCase):
         self.send_and_assert_no_replies(self.pg7,
                                         pkt_inter_epg_220_from_global * 65)
 
-        c5 = VppGbpContract(self, 333, 220, 0)
+        c5 = VppGbpContract(self, 333, 220, acl_index2)
         c5.add_vpp_config()
 
         self.send_and_expect_unnatted(self.pg7,