aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/acl/acl.api20
-rw-r--r--src/plugins/acl/acl.c203
-rw-r--r--src/plugins/acl/acl.h6
-rw-r--r--src/plugins/acl/acl_test.c60
-rw-r--r--src/plugins/acl/manual_fns.h24
-rw-r--r--test/test_acl_plugin.py100
-rw-r--r--test/vpp_papi_provider.py10
7 files changed, 411 insertions, 12 deletions
diff --git a/src/plugins/acl/acl.api b/src/plugins/acl/acl.api
index e3166d691a8..047fc683b87 100644
--- a/src/plugins/acl/acl.api
+++ b/src/plugins/acl/acl.api
@@ -476,3 +476,23 @@ define macip_acl_interface_list_details
u8 count;
u32 acls[count];
};
+
+/** \brief Set the ethertype whitelists on an interface. Takes effect when applying ACLs on the interface, so must be given prior.
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param sw_if_index - the interface to alter the list of ACLs on
+ @param count - total number of whitelisted ethertypes in the vector
+ @param n_input - this many first elements correspond to input whitelisted ethertypes, the rest - output
+ @param whitelist - vector of whitelisted ethertypes
+*/
+
+autoreply manual_print define acl_interface_set_etype_whitelist
+{
+ u32 client_index;
+ u32 context;
+ u32 sw_if_index;
+ u8 count; /* Total number of ethertypes in the whitelist */
+ u8 n_input; /* first n_input ethertypes are input, the rest - output */
+ u16 whitelist[count];
+};
+
diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c
index 82e1ab04e84..82a5670235b 100644
--- a/src/plugins/acl/acl.c
+++ b/src/plugins/acl/acl.c
@@ -75,7 +75,8 @@ _(MACIP_ACL_DEL, macip_acl_del) \
_(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del) \
_(MACIP_ACL_DUMP, macip_acl_dump) \
_(MACIP_ACL_INTERFACE_GET, macip_acl_interface_get) \
-_(MACIP_ACL_INTERFACE_LIST_DUMP, macip_acl_interface_list_dump)
+_(MACIP_ACL_INTERFACE_LIST_DUMP, macip_acl_interface_list_dump) \
+_(ACL_INTERFACE_SET_ETYPE_WHITELIST, acl_interface_set_etype_whitelist)
/* *INDENT-OFF* */
@@ -85,6 +86,24 @@ VLIB_PLUGIN_REGISTER () = {
};
/* *INDENT-ON* */
+/* Format vec16. */
+u8 *
+format_vec16 (u8 * s, va_list * va)
+{
+ u16 *v = va_arg (*va, u16 *);
+ char *fmt = va_arg (*va, char *);
+ uword i;
+ for (i = 0; i < vec_len (v); i++)
+ {
+ if (i > 0)
+ s = format (s, ", ");
+ s = format (s, fmt, v[i]);
+ }
+ return s;
+}
+
+
+
static void *
acl_set_heap (acl_main_t * am)
@@ -402,6 +421,10 @@ u8 ip4_5tuple_mask[] =
_(padpad) __ __ __ __
_(padeth) __ __;
+ u8 ethertype_mask[] =
+ _(" dmac smac etype ")
+ _(ether) __ __ __ __ __ __ v __ __ __ __ __ __ v XX XX __ __;
+
/* *INDENT-ON* */
#undef XX
#undef __
@@ -486,6 +509,7 @@ acl_unhook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
u32 ip6_table_index = ~0;
u32 dot1q_table_index = ~0;
u32 dot1ad_table_index = ~0;
+ u32 etype_table_index = ~0;
void *oldheap = acl_set_heap (am);
vec_validate_init_empty (am->acl_ip4_input_classify_table_by_sw_if_index,
@@ -496,6 +520,8 @@ acl_unhook_l2_input_classify (acl_main_t * am, u32 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);
+ vec_validate_init_empty (am->acl_etype_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);
@@ -539,6 +565,15 @@ acl_unhook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
sizeof (dot1ad_5tuple_mask) - 1, ~0,
~0, &dot1ad_table_index, 0);
}
+ if (am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
+ {
+ etype_table_index =
+ am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index];
+ am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index] = ~0;
+ acl_classify_add_del_table_tiny (cm, ethertype_mask,
+ sizeof (ethertype_mask) - 1, ~0,
+ ~0, &etype_table_index, 0);
+ }
clib_mem_set_heap (oldheap);
return 0;
}
@@ -551,6 +586,7 @@ acl_unhook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
u32 ip6_table_index = ~0;
u32 dot1q_table_index = ~0;
u32 dot1ad_table_index = ~0;
+ u32 etype_table_index = ~0;
void *oldheap = acl_set_heap (am);
vec_validate_init_empty (am->acl_ip4_output_classify_table_by_sw_if_index,
@@ -561,6 +597,8 @@ acl_unhook_l2_output_classify (acl_main_t * am, u32 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);
+ vec_validate_init_empty (am->acl_etype_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);
@@ -605,6 +643,15 @@ acl_unhook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
sizeof (dot1ad_5tuple_mask) - 1, ~0,
~0, &dot1ad_table_index, 0);
}
+ if (am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
+ {
+ etype_table_index =
+ am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index];
+ am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index] = ~0;
+ acl_classify_add_del_table_tiny (cm, ethertype_mask,
+ sizeof (ethertype_mask) - 1, ~0,
+ ~0, &etype_table_index, 0);
+ }
clib_mem_set_heap (oldheap);
return 0;
}
@@ -677,6 +724,45 @@ acl_add_vlan_session (acl_main_t * am, u32 table_index, u8 is_output,
}
static int
+intf_has_etype_whitelist (acl_main_t * am, u32 sw_if_index, int is_input)
+{
+ u16 **v = is_input
+ ? am->input_etype_whitelist_by_sw_if_index
+ : am->output_etype_whitelist_by_sw_if_index;
+ return ((vec_len (v) > sw_if_index) && vec_elt (v, sw_if_index));
+}
+
+static int
+etype_whitelist_add_sessions (acl_main_t * am, u32 sw_if_index, int is_input,
+ u32 etype_table_index)
+{
+ vnet_classify_main_t *cm = &vnet_classify_main;
+ u16 **v = is_input
+ ? am->input_etype_whitelist_by_sw_if_index
+ : am->output_etype_whitelist_by_sw_if_index;
+ u8 *match = ethertype_mask;
+
+ int i;
+ int rv = 0;
+ u16 *whitelist = vec_elt (v, sw_if_index);
+ u32 next = ~0; /* permit */
+ for (i = 0; i < vec_len (whitelist); i++)
+ {
+ /* big-endian */
+ match[12] = (whitelist[i] >> 8) & 0xff;
+ match[13] = whitelist[i] & 0xff;
+ rv = rv
+ || vnet_classify_add_del_session (cm, etype_table_index, match, next,
+ whitelist[i], 0, 0, 0, 1);
+ }
+
+ /* restore the mask */
+ match[12] = 0xff;
+ match[13] = 0xff;
+ return rv;
+}
+
+static int
acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
{
vnet_classify_main_t *cm = &vnet_classify_main;
@@ -684,6 +770,7 @@ acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
u32 ip6_table_index = ~0;
u32 dot1q_table_index = ~0;
u32 dot1ad_table_index = ~0;
+ u32 etype_table_index = ~0;
int rv;
void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
@@ -712,10 +799,18 @@ acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
goto done;
}
+ if (intf_has_etype_whitelist (am, sw_if_index, 1))
+ {
+ acl_classify_add_del_table_tiny (cm, ethertype_mask, sizeof (ethertype_mask) - 1, ~0, 0, /* drop if no match */
+ &etype_table_index, 1);
+ etype_whitelist_add_sessions (am, sw_if_index, 1, etype_table_index);
+ }
+
rv =
acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
- sizeof (dot1ad_5tuple_mask) - 1, ~0,
- ~0, &dot1ad_table_index, 1);
+ sizeof (dot1ad_5tuple_mask) - 1,
+ etype_table_index, ~0,
+ &dot1ad_table_index, 1);
rv =
acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask,
sizeof (dot1q_5tuple_mask) - 1,
@@ -774,6 +869,10 @@ acl_hook_l2_input_classify (acl_main_t * am, u32 sw_if_index)
dot1q_table_index;
am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] =
dot1ad_table_index;
+ am->acl_dot1ad_input_classify_table_by_sw_if_index[sw_if_index] =
+ dot1ad_table_index;
+ am->acl_etype_input_classify_table_by_sw_if_index[sw_if_index] =
+ etype_table_index;
vnet_l2_input_classify_enable_disable (sw_if_index, 1);
done:
@@ -789,6 +888,7 @@ acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
u32 ip6_table_index = ~0;
u32 dot1q_table_index = ~0;
u32 dot1ad_table_index = ~0;
+ u32 etype_table_index = ~0;
int rv;
void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
@@ -816,10 +916,19 @@ acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
goto done;
}
+ if (intf_has_etype_whitelist (am, sw_if_index, 0))
+ {
+ acl_classify_add_del_table_tiny (cm, ethertype_mask, sizeof (ethertype_mask) - 1, ~0, 0, /* drop if no match */
+ &etype_table_index, 1);
+ etype_whitelist_add_sessions (am, sw_if_index, 0, etype_table_index);
+ }
+
+
rv =
acl_classify_add_del_table_tiny (cm, dot1ad_5tuple_mask,
- sizeof (dot1ad_5tuple_mask) - 1, ~0,
- ~0, &dot1ad_table_index, 1);
+ sizeof (dot1ad_5tuple_mask) - 1,
+ etype_table_index, ~0,
+ &dot1ad_table_index, 1);
rv =
acl_classify_add_del_table_tiny (cm, dot1q_5tuple_mask,
sizeof (dot1q_5tuple_mask) - 1,
@@ -881,6 +990,8 @@ acl_hook_l2_output_classify (acl_main_t * am, u32 sw_if_index)
dot1q_table_index;
am->acl_dot1ad_output_classify_table_by_sw_if_index[sw_if_index] =
dot1ad_table_index;
+ am->acl_etype_output_classify_table_by_sw_if_index[sw_if_index] =
+ etype_table_index;
vnet_l2_output_classify_enable_disable (sw_if_index, 1);
done:
@@ -1187,6 +1298,43 @@ acl_interface_add_del_inout_acl (u32 sw_if_index, u8 is_add, u8 is_input,
return rv;
}
+static int
+acl_set_etype_whitelists (acl_main_t * am, u32 sw_if_index, u16 * vec_in,
+ u16 * vec_out)
+{
+ vec_validate (am->input_etype_whitelist_by_sw_if_index, sw_if_index);
+ vec_validate (am->output_etype_whitelist_by_sw_if_index, sw_if_index);
+
+ vec_free (am->input_etype_whitelist_by_sw_if_index[sw_if_index]);
+ vec_free (am->output_etype_whitelist_by_sw_if_index[sw_if_index]);
+
+ am->input_etype_whitelist_by_sw_if_index[sw_if_index] = vec_in;
+ am->output_etype_whitelist_by_sw_if_index[sw_if_index] = vec_out;
+
+ /*
+ * if there are already inbound/outbound ACLs applied, toggle the
+ * enable/disable - this will recreate the necessary tables.
+ */
+
+ if (vec_len (am->input_acl_vec_by_sw_if_index) > sw_if_index)
+ {
+ if (vec_len (am->input_acl_vec_by_sw_if_index[sw_if_index]) > 0)
+ {
+ acl_interface_in_enable_disable (am, sw_if_index, 0);
+ acl_interface_in_enable_disable (am, sw_if_index, 1);
+ }
+ }
+ if (vec_len (am->output_acl_vec_by_sw_if_index) > sw_if_index)
+ {
+ if (vec_len (am->output_acl_vec_by_sw_if_index[sw_if_index]) > 0)
+ {
+ acl_interface_out_enable_disable (am, sw_if_index, 0);
+ acl_interface_out_enable_disable (am, sw_if_index, 1);
+ }
+ }
+ return 0;
+}
+
typedef struct
{
@@ -2499,6 +2647,38 @@ static void
}
}
+static void
+ vl_api_acl_interface_set_etype_whitelist_t_handler
+ (vl_api_acl_interface_set_etype_whitelist_t * mp)
+{
+ acl_main_t *am = &acl_main;
+ vl_api_acl_interface_set_etype_whitelist_reply_t *rmp;
+ int rv = 0;
+ int i;
+ vnet_interface_main_t *im = &am->vnet_main->interface_main;
+ u32 sw_if_index = ntohl (mp->sw_if_index);
+ u16 *vec_in = 0, *vec_out = 0;
+ void *oldheap = acl_set_heap (am);
+
+ if (pool_is_free_index (im->sw_interfaces, sw_if_index))
+ rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
+ else
+ {
+ for (i = 0; i < mp->count; i++)
+ {
+ if (i < mp->n_input)
+ vec_add1 (vec_in, ntohs (mp->whitelist[i]));
+ else
+ vec_add1 (vec_out, ntohs (mp->whitelist[i]));
+ }
+ rv = acl_set_etype_whitelists (am, sw_if_index, vec_in, vec_out);
+ }
+
+ clib_mem_set_heap (oldheap);
+ REPLY_MACRO (VL_API_ACL_INTERFACE_SET_ETYPE_WHITELIST_REPLY);
+}
+
+
/* Set up the API message handling tables */
static clib_error_t *
acl_plugin_api_hookup (vlib_main_t * vm)
@@ -3013,6 +3193,19 @@ acl_plugin_show_interface (acl_main_t * am, u32 sw_if_index, int show_acl)
vlib_cli_output (vm, "sw_if_index %d:\n", swi);
+ if (intf_has_etype_whitelist (am, swi, 1))
+ {
+ vlib_cli_output (vm, " input etype whitelist: %U", format_vec16,
+ am->input_etype_whitelist_by_sw_if_index[swi],
+ "%04x");
+ }
+ if (intf_has_etype_whitelist (am, swi, 0))
+ {
+ vlib_cli_output (vm, " output etype whitelist: %U", format_vec16,
+ am->output_etype_whitelist_by_sw_if_index[swi],
+ "%04x");
+ }
+
if ((swi < vec_len (am->input_acl_vec_by_sw_if_index)) &&
(vec_len (am->input_acl_vec_by_sw_if_index[swi]) > 0))
{
diff --git a/src/plugins/acl/acl.h b/src/plugins/acl/acl.h
index 263867b61ff..07ed8681ef1 100644
--- a/src/plugins/acl/acl.h
+++ b/src/plugins/acl/acl.h
@@ -188,6 +188,12 @@ typedef struct {
u32 *acl_dot1q_output_classify_table_by_sw_if_index;
u32 *acl_dot1ad_output_classify_table_by_sw_if_index;
+ u32 *acl_etype_input_classify_table_by_sw_if_index;
+ u32 *acl_etype_output_classify_table_by_sw_if_index;
+
+ u16 **input_etype_whitelist_by_sw_if_index;
+ u16 **output_etype_whitelist_by_sw_if_index;
+
/* MACIP (input) ACLs associated with the interfaces */
u32 *macip_acl_by_sw_if_index;
diff --git a/src/plugins/acl/acl_test.c b/src/plugins/acl/acl_test.c
index 90fd49980de..c264034c939 100644
--- a/src/plugins/acl/acl_test.c
+++ b/src/plugins/acl/acl_test.c
@@ -67,6 +67,7 @@ _(acl_del_reply) \
_(acl_interface_add_del_reply) \
_(macip_acl_interface_add_del_reply) \
_(acl_interface_set_acl_list_reply) \
+_(acl_interface_set_etype_whitelist_reply) \
_(macip_acl_del_reply)
#define foreach_reply_retval_aclindex_handler \
@@ -269,6 +270,7 @@ _(ACL_ADD_REPLACE_REPLY, acl_add_replace_reply) \
_(ACL_DEL_REPLY, acl_del_reply) \
_(ACL_INTERFACE_ADD_DEL_REPLY, acl_interface_add_del_reply) \
_(ACL_INTERFACE_SET_ACL_LIST_REPLY, acl_interface_set_acl_list_reply) \
+_(ACL_INTERFACE_SET_ETYPE_WHITELIST_REPLY, acl_interface_set_etype_whitelist_reply) \
_(ACL_INTERFACE_LIST_DETAILS, acl_interface_list_details) \
_(ACL_DETAILS, acl_details) \
_(MACIP_ACL_ADD_REPLY, macip_acl_add_reply) \
@@ -746,6 +748,63 @@ static int api_acl_interface_set_acl_list (vat_main_t * vam)
return ret;
}
+static int api_acl_interface_set_etype_whitelist (vat_main_t * vam)
+{
+ unformat_input_t * i = vam->input;
+ vl_api_acl_interface_set_etype_whitelist_t * mp;
+ u32 sw_if_index = ~0;
+ u32 ethertype = ~0;
+ u16 *etypes_in = 0;
+ u16 *etypes_out = 0;
+ u8 is_input = 1;
+ int ret;
+
+// acl_interface_set_etype_whitelist <intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
+ if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
+ ;
+ else if (unformat (i, "sw_if_index %d", &sw_if_index))
+ ;
+ else if (unformat (i, "%x", &ethertype))
+ {
+ ethertype = ethertype & 0xffff;
+ if(is_input)
+ vec_add1(etypes_in, htons(ethertype));
+ else
+ vec_add1(etypes_out, htons(ethertype));
+ }
+ else if (unformat (i, "input"))
+ is_input = 1;
+ else if (unformat (i, "output"))
+ is_input = 0;
+ else
+ break;
+ }
+
+ if (sw_if_index == ~0) {
+ errmsg ("missing interface name / explicit sw_if_index number \n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M2(ACL_INTERFACE_SET_ETYPE_WHITELIST, mp, sizeof(u32) * (vec_len(etypes_in) + vec_len(etypes_out)));
+ mp->sw_if_index = ntohl(sw_if_index);
+ mp->n_input = vec_len(etypes_in);
+ mp->count = vec_len(etypes_in) + vec_len(etypes_out);
+ vec_append(etypes_in, etypes_out);
+ if (vec_len(etypes_in) > 0)
+ clib_memcpy(mp->whitelist, etypes_in, vec_len(etypes_in)*sizeof(etypes_in[0]));
+
+ /* send it... */
+ S(mp);
+
+ /* Wait for a reply... */
+ W (ret);
+ return ret;
+}
+
static void
api_acl_send_control_ping(vat_main_t *vam)
{
@@ -1163,6 +1222,7 @@ _(acl_del, "<acl-idx>") \
_(acl_dump, "[<acl-idx>]") \
_(acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] [input|output] acl <acl-idx>") \
_(acl_interface_set_acl_list, "<intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]") \
+_(acl_interface_set_etype_whitelist, "<intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]") \
_(acl_interface_list_dump, "[<intfc> | sw_if_index <if-idx>]") \
_(macip_acl_add, "...") \
_(macip_acl_add_replace, "<acl-idx> [<ipv4|ipv6> <permit|deny|action N> [count <count>] [src] ip <ipaddress/[plen]> mac <mac> mask <mac_mask>, ... , ...") \
diff --git a/src/plugins/acl/manual_fns.h b/src/plugins/acl/manual_fns.h
index e00f1abcc61..6ab014caf8d 100644
--- a/src/plugins/acl/manual_fns.h
+++ b/src/plugins/acl/manual_fns.h
@@ -360,6 +360,30 @@ vl_api_acl_interface_set_acl_list_t_print (vl_api_acl_interface_set_acl_list_t
}
static inline void *
+vl_api_acl_interface_set_etype_whitelist_t_print (vl_api_acl_interface_set_etype_whitelist_t
+ * a, void *handle)
+{
+ u8 *s;
+ int i;
+
+ s = format
+ (0, "SCRIPT: acl_interface_set_etype_whitelist sw_if_index %d count %d\n",
+ clib_net_to_host_u32 (a->sw_if_index), (u32) a->count);
+
+ s = format (s, " input ");
+
+ for (i = 0; i < a->count; i++)
+ {
+ if (i == a->n_input)
+ s = format (s, "output ");
+ s = format (s, "%x ", clib_net_to_host_u16 (a->whitelist[i]));
+ }
+
+ PRINT_S;
+ return handle;
+}
+
+static inline void *
vl_api_acl_interface_add_del_t_print (vl_api_acl_interface_add_del_t * a,
void *handle)
{
diff --git a/test/test_acl_plugin.py b/test/test_acl_plugin.py
index 361ced14c21..5fcf09c5ee7 100644
--- a/test/test_acl_plugin.py
+++ b/test/test_acl_plugin.py
@@ -247,6 +247,15 @@ class TestACLplugin(VppTestCase):
acls=[reply.acl_index])
return
+ def etype_whitelist(self, whitelist, n_input):
+ # Apply whitelists on all the interfaces
+ for i in self.pg_interfaces:
+ # checkstyle can't read long names. Help them.
+ fun = self.vapi.acl_interface_set_etype_whitelist
+ fun(sw_if_index=i.sw_if_index, n_input=n_input,
+ whitelist=whitelist)
+ return
+
def create_upper_layer(self, packet_index, proto, ports=0):
p = self.proto_map[proto]
if p == 'UDP':
@@ -268,7 +277,8 @@ class TestACLplugin(VppTestCase):
return ''
def create_stream(self, src_if, packet_sizes, traffic_type=0, ipv6=0,
- proto=-1, ports=0, fragments=False, pkt_raw=True):
+ proto=-1, ports=0, fragments=False,
+ pkt_raw=True, etype=-1):
"""
Create input packet stream for defined interface using hosts or
deleted_hosts list.
@@ -300,6 +310,10 @@ class TestACLplugin(VppTestCase):
pkt_info.proto = proto
payload = self.info_to_payload(pkt_info)
p = Ether(dst=dst_host.mac, src=src_host.mac)
+ if etype > 0:
+ p = Ether(dst=dst_host.mac,
+ src=src_host.mac,
+ type=etype)
if pkt_info.ip:
p /= IPv6(dst=dst_host.ip6, src=src_host.ip6)
if fragments:
@@ -328,7 +342,8 @@ class TestACLplugin(VppTestCase):
pkts.append(p)
return pkts
- def verify_capture(self, pg_if, capture, traffic_type=0, ip_type=0):
+ def verify_capture(self, pg_if, capture,
+ traffic_type=0, ip_type=0, etype=-1):
"""
Verify captured input packet stream for defined interface.
@@ -341,6 +356,12 @@ class TestACLplugin(VppTestCase):
last_info[i.sw_if_index] = None
dst_sw_if_index = pg_if.sw_if_index
for packet in capture:
+ if etype > 0:
+ if packet[Ether].type != etype:
+ self.logger.error(ppp("Unexpected ethertype in packet:",
+ packet))
+ else:
+ continue
try:
# Raw data for ICMPv6 are stored in ICMPv6EchoRequest.data
if traffic_type == self.ICMP and ip_type == self.IPV6:
@@ -429,7 +450,7 @@ class TestACLplugin(VppTestCase):
self.pg_start()
def run_verify_test(self, traffic_type=0, ip_type=0, proto=-1, ports=0,
- frags=False, pkt_raw=True):
+ frags=False, pkt_raw=True, etype=-1):
# Test
# Create incoming packet streams for packet-generator interfaces
pkts_cnt = 0
@@ -437,7 +458,7 @@ class TestACLplugin(VppTestCase):
if self.flows.__contains__(i):
pkts = self.create_stream(i, self.pg_if_packet_sizes,
traffic_type, ip_type, proto, ports,
- frags, pkt_raw)
+ frags, pkt_raw, etype)
if len(pkts) > 0:
i.add_stream(pkts)
pkts_cnt += len(pkts)
@@ -454,17 +475,18 @@ class TestACLplugin(VppTestCase):
capture = dst_if.get_capture(pkts_cnt)
self.logger.info("Verifying capture on interface %s" %
dst_if.name)
- self.verify_capture(dst_if, capture, traffic_type, ip_type)
+ self.verify_capture(dst_if, capture,
+ traffic_type, ip_type, etype)
def run_verify_negat_test(self, traffic_type=0, ip_type=0, proto=-1,
- ports=0, frags=False):
+ ports=0, frags=False, etype=-1):
# Test
self.reset_packet_infos()
for i in self.pg_interfaces:
if self.flows.__contains__(i):
pkts = self.create_stream(i, self.pg_if_packet_sizes,
traffic_type, ip_type, proto, ports,
- frags)
+ frags, True, etype)
if len(pkts) > 0:
i.add_stream(pkts)
@@ -1306,6 +1328,70 @@ class TestACLplugin(VppTestCase):
self.logger.info("ACLP_TEST_FINISH_0113")
+ def test_0300_tcp_permit_v4_etype_aaaa(self):
+ """ permit TCPv4, send 0xAAAA etype
+ """
+ self.logger.info("ACLP_TEST_START_0300")
+
+ # Add an ACL
+ rules = []
+ rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
+ self.proto[self.IP][self.TCP]))
+ rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
+ self.proto[self.IP][self.TCP]))
+ # deny ip any any in the end
+ rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
+
+ # Apply rules
+ self.apply_rules(rules, "permit ipv4 tcp")
+
+ # Traffic should still pass
+ self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP])
+
+ # Traffic should still pass also for an odd ethertype
+ self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP],
+ 0, False, True, 0xaaaa)
+
+ self.logger.info("ACLP_TEST_FINISH_0300")
+
+ def test_0305_tcp_permit_v4_etype_blacklist_aaaa(self):
+ """ permit TCPv4, whitelist 0x0BBB ethertype, send 0xAAAA, 0x0BBB
+ """
+ self.logger.info("ACLP_TEST_START_0305")
+
+ # Add an ACL
+ rules = []
+ rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
+ self.proto[self.IP][self.TCP]))
+ rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
+ self.proto[self.IP][self.TCP]))
+ # deny ip any any in the end
+ rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
+
+ # Apply rules
+ self.apply_rules(rules, "permit ipv4 tcp")
+
+ # whitelist the 0xbbbb etype - so the 0xaaaa should be blocked
+ self.etype_whitelist([0xbbb], 1)
+
+ # The IPv4 traffic should still pass
+ self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP])
+
+ # The oddball ethertype should be blocked
+ self.run_verify_negat_test(self.IP, self.IPV4,
+ self.proto[self.IP][self.TCP],
+ 0, False, 0xaaaa)
+
+ # The whitelisted traffic, on the other hand, should pass
+ self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP],
+ 0, False, True, 0x0bbb)
+
+ # remove the whitelist, the previously blocked 0xAAAA should pass now
+ self.etype_whitelist([], 0)
+ self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP],
+ 0, False, True, 0xaaaa)
+
+ self.logger.info("ACLP_TEST_FINISH_0305")
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 0e56af1ca9e..a10b777a13a 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -2680,6 +2680,16 @@ class VppPapiProvider(object):
'acls': acls},
expected_retval=expected_retval)
+ def acl_interface_set_etype_whitelist(self, sw_if_index,
+ n_input, whitelist,
+ expected_retval=0):
+ return self.api(self.papi.acl_interface_set_etype_whitelist,
+ {'sw_if_index': sw_if_index,
+ 'count': len(whitelist),
+ 'n_input': n_input,
+ 'whitelist': whitelist},
+ expected_retval=expected_retval)
+
def acl_interface_add_del(self,
sw_if_index,
acl_index,