X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Facl%2Facl.c;h=e1d6da02b754d91fc9ea7a353ad165bdfa87f20d;hb=f55957e71c58e38770b12af0720e9d19a8f6a8d6;hp=82e1ab04e8400cc3f458d2a09195c01cb1c5bafb;hpb=db3c480e375bd7eb22c27887590c8dca07293719;p=vpp.git diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index 82e1ab04e84..e1d6da02b75 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -75,7 +75,9 @@ _(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) \ +_(ACL_INTERFACE_ETYPE_WHITELIST_DUMP, acl_interface_etype_whitelist_dump) /* *INDENT-OFF* */ @@ -85,6 +87,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 +422,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 +510,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 +521,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 +566,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 +587,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 +598,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 +644,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; } @@ -676,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) { @@ -684,6 +771,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 +800,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 +870,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 +889,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 +917,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 +991,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 +1299,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 { @@ -1199,11 +1348,15 @@ typedef struct u32 arp_table_index; u32 dot1q_table_index; u32 dot1ad_table_index; + u32 arp_dot1q_table_index; + u32 arp_dot1ad_table_index; /* egress tables */ u32 out_table_index; u32 out_arp_table_index; u32 out_dot1q_table_index; u32 out_dot1ad_table_index; + u32 out_arp_dot1q_table_index; + u32 out_arp_dot1ad_table_index; } macip_match_type_t; static u32 @@ -1324,10 +1477,14 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) mvec[match_type_index].arp_table_index = ~0; mvec[match_type_index].dot1q_table_index = ~0; mvec[match_type_index].dot1ad_table_index = ~0; + mvec[match_type_index].arp_dot1q_table_index = ~0; + mvec[match_type_index].arp_dot1ad_table_index = ~0; mvec[match_type_index].out_table_index = ~0; mvec[match_type_index].out_arp_table_index = ~0; mvec[match_type_index].out_dot1q_table_index = ~0; mvec[match_type_index].out_dot1ad_table_index = ~0; + mvec[match_type_index].out_arp_dot1q_table_index = ~0; + mvec[match_type_index].out_arp_dot1ad_table_index = ~0; } mvec[match_type_index].count++; mvec[match_type_index].has_egress |= @@ -1343,6 +1500,10 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) { int mask_len; int is6 = mt->is_ipv6; + int tags; + u32 *last_tag_table; + u32 *out_last_tag_table; + u32 l3_offset; if (!is6) { @@ -1373,41 +1534,91 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - memset (mask, 0, sizeof (mask)); - /* source MAC address */ - memcpy (&mask[6], mt->mac_mask, 6); - memset (&mask[12], 0xff, 2); /* ethernet protocol */ - /* sender hardware address within ARP */ - memcpy (&mask[14 + 8], mt->mac_mask, 6); - /* sender protocol address within ARP */ - for (i = 0; i < (mt->prefix_len / 8); i++) - mask[14 + 14 + i] = 0xff; - if (mt->prefix_len % 8) - mask[14 + 14 + (mt->prefix_len / 8)] = - 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1); - - mask_len = ((14 + 14 + ((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->arp_table_index, 1); - last_table = mt->arp_table_index; - if (mt->has_egress) + for (tags = 2; tags >= 0; tags--) { - /* egress ARP table */ memset (mask, 0, sizeof (mask)); - // memcpy (&mask[0], mt->mac_mask, 6); - memset (&mask[12], 0xff, 2); /* ethernet protocol */ - /* AYXX: FIXME here - can we tighten the ARP-related table more ? */ - /* mask captures just the destination and the ethertype */ - mask_len = ((14 + + /* source MAC address */ + memcpy (&mask[6], mt->mac_mask, 6); + + switch (tags) + { + case 0: + default: + memset (&mask[12], 0xff, 2); /* ethernet protocol */ + l3_offset = 14; + last_tag_table = &mt->arp_table_index; + break; + case 1: + memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + memset (&mask[16], 0xff, 2); /* ethernet protocol */ + l3_offset = 18; + last_tag_table = &mt->arp_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 */ + l3_offset = 22; + last_tag_table = &mt->arp_dot1ad_table_index; + break; + } + + /* sender hardware address within ARP */ + memcpy (&mask[l3_offset + 8], mt->mac_mask, 6); + /* sender protocol address within ARP */ + for (i = 0; i < (mt->prefix_len / 8); i++) + mask[l3_offset + 14 + i] = 0xff; + if (mt->prefix_len % 8) + mask[l3_offset + 14 + (mt->prefix_len / 8)] = + 0xff - ((1 << (8 - mt->prefix_len % 8)) - 1); + + mask_len = ((l3_offset + 14 + ((mt->prefix_len + 7) / 8) + (sizeof (u32x4) - 1)) / sizeof (u32x4)) * sizeof (u32x4); - acl_classify_add_del_table_small (cm, mask, mask_len, - out_last_table, - (~0 == out_last_table) ? 0 : ~0, - &mt->out_arp_table_index, 1); - out_last_table = mt->out_arp_table_index; + acl_classify_add_del_table_small (cm, mask, mask_len, last_table, + (~0 == last_table) ? 0 : ~0, + last_tag_table, 1); + last_table = *last_tag_table; + if (mt->has_egress) + { + /* egress ARP table */ + memset (mask, 0, sizeof (mask)); + + switch (tags) + { + case 0: + default: + memset (&mask[12], 0xff, 2); /* ethernet protocol */ + l3_offset = 14; + out_last_tag_table = &mt->out_arp_table_index; + break; + case 1: + memset (&mask[12], 0xff, 2); /* VLAN tag1 */ + memset (&mask[16], 0xff, 2); /* ethernet protocol */ + l3_offset = 18; + out_last_tag_table = &mt->out_arp_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 */ + l3_offset = 22; + out_last_tag_table = &mt->out_arp_dot1ad_table_index; + break; + } + + /* AYXX: FIXME here - can we tighten the ARP-related table more ? */ + /* mask captures just the destination and the ethertype */ + mask_len = ((l3_offset + + (sizeof (u32x4) - + 1)) / sizeof (u32x4)) * sizeof (u32x4); + acl_classify_add_del_table_small (cm, mask, mask_len, + out_last_table, + (~0 == + out_last_table) ? 0 : ~0, + out_last_tag_table, 1); + out_last_table = *out_last_tag_table; + } } } } @@ -1597,15 +1808,45 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) { memset (mask, 0, sizeof (mask)); memcpy (&mask[6], a->rules[i].src_mac, 6); - mask[12] = 0x08; - mask[13] = 0x06; - memcpy (&mask[14 + 8], a->rules[i].src_mac, 6); - memcpy (&mask[14 + 14], &a->rules[i].src_ip_addr.ip4, 4); - vnet_classify_add_del_session (cm, - mvec - [match_type_index].arp_table_index, - mask, a->rules[i].is_permit ? ~0 : 0, - i, 0, action, metadata, 1); + + for (tags = 2; tags >= 0; tags--) + { + switch (tags) + { + case 0: + default: + tag_table = mvec[match_type_index].arp_table_index; + mask[12] = 0x08; + mask[13] = 0x06; + l3_src_offs = 14; + break; + case 1: + tag_table = mvec[match_type_index].arp_dot1q_table_index; + mask[12] = 0x81; + mask[13] = 0x00; + mask[16] = 0x08; + mask[17] = 0x06; + l3_src_offs = 18; + break; + case 2: + tag_table = mvec[match_type_index].arp_dot1ad_table_index; + mask[12] = 0x88; + mask[13] = 0xa8; + mask[16] = 0x81; + mask[17] = 0x00; + mask[20] = 0x08; + mask[21] = 0x06; + l3_src_offs = 22; + break; + } + + memcpy (&mask[l3_src_offs + 8], a->rules[i].src_mac, 6); + memcpy (&mask[l3_src_offs + 14], &a->rules[i].src_ip_addr.ip4, + 4); + vnet_classify_add_del_session (cm, tag_table, mask, + a->rules[i].is_permit ? ~0 : 0, + i, 0, action, metadata, 1); + } } if (macip_permit_also_egress (a->rules[i].is_permit)) { @@ -1664,16 +1905,43 @@ macip_create_classify_tables (acl_main_t * am, u32 macip_acl_index) /* add ARP table entry too */ if (!is6 && (mvec[match_type_index].out_arp_table_index != ~0)) { - memset (mask, 0, sizeof (mask)); - memcpy (&mask[0], a->rules[i].src_mac, 6); - mask[12] = 0x08; - mask[13] = 0x06; - vnet_classify_add_del_session (cm, - mvec - [match_type_index].out_arp_table_index, - mask, - a->rules[i].is_permit ? ~0 : 0, - i, 0, action, metadata, 1); + for (tags = 2; tags >= 0; tags--) + { + memset (mask, 0, sizeof (mask)); + switch (tags) + { + case 0: + default: + tag_table = mvec[match_type_index].out_arp_table_index; + mask[12] = 0x08; + mask[13] = 0x06; + break; + case 1: + tag_table = + mvec[match_type_index].out_arp_dot1q_table_index; + mask[12] = 0x81; + mask[13] = 0x00; + mask[16] = 0x08; + mask[17] = 0x06; + break; + case 2: + tag_table = + mvec[match_type_index].out_arp_dot1ad_table_index; + mask[12] = 0x88; + mask[13] = 0xa8; + mask[16] = 0x81; + mask[17] = 0x00; + mask[20] = 0x08; + mask[21] = 0x06; + break; + } + + vnet_classify_add_del_session (cm, tag_table, + mask, + a-> + rules[i].is_permit ? ~0 : 0, + i, 0, action, metadata, 1); + } } } } @@ -1704,6 +1972,24 @@ macip_destroy_classify_tables (acl_main_t * am, u32 macip_acl_index) 0); a->l2_table_index = ~0; } + if (a->out_ip4_table_index != ~0) + { + acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, + &a->out_ip4_table_index, 0); + a->out_ip4_table_index = ~0; + } + if (a->out_ip6_table_index != ~0) + { + acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, + &a->out_ip6_table_index, 0); + a->out_ip6_table_index = ~0; + } + if (a->out_l2_table_index != ~0) + { + acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0, + &a->out_l2_table_index, 0); + a->out_l2_table_index = ~0; + } } static int @@ -2499,6 +2785,130 @@ 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); +} + +static void +send_acl_interface_etype_whitelist_details (acl_main_t * am, + vl_api_registration_t * reg, + u32 sw_if_index, u32 context) +{ + vl_api_acl_interface_etype_whitelist_details_t *mp; + int msg_size; + int n_input = 0; + int n_output = 0; + int count = 0; + int i = 0; + + u16 *whitelist_in = 0; + u16 *whitelist_out = 0; + + if (intf_has_etype_whitelist (am, sw_if_index, 0)) + whitelist_out = + vec_elt (am->output_etype_whitelist_by_sw_if_index, sw_if_index); + + if (intf_has_etype_whitelist (am, sw_if_index, 1)) + whitelist_in = + vec_elt (am->input_etype_whitelist_by_sw_if_index, sw_if_index); + + if ((0 == whitelist_in) && (0 == whitelist_out)) + return; /* nothing to do */ + + void *oldheap = acl_set_heap (am); + + n_input = vec_len (whitelist_in); + n_output = vec_len (whitelist_out); + count = n_input + n_output; + + msg_size = sizeof (*mp); + msg_size += sizeof (mp->whitelist[0]) * count; + + mp = vl_msg_api_alloc (msg_size); + memset (mp, 0, msg_size); + mp->_vl_msg_id = + ntohs (VL_API_ACL_INTERFACE_ETYPE_WHITELIST_DETAILS + am->msg_id_base); + + /* fill in the message */ + mp->context = context; + mp->sw_if_index = htonl (sw_if_index); + mp->count = count; + mp->n_input = n_input; + for (i = 0; i < n_input; i++) + { + mp->whitelist[i] = htons (whitelist_in[i]); + } + for (i = 0; i < n_output; i++) + { + mp->whitelist[n_input + i] = htons (whitelist_out[i]); + } + clib_mem_set_heap (oldheap); + vl_api_send_msg (reg, (u8 *) mp); +} + + +static void + vl_api_acl_interface_etype_whitelist_dump_t_handler + (vl_api_acl_interface_list_dump_t * mp) +{ + acl_main_t *am = &acl_main; + vnet_sw_interface_t *swif; + vnet_interface_main_t *im = &am->vnet_main->interface_main; + + u32 sw_if_index; + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + if (mp->sw_if_index == ~0) + { + /* *INDENT-OFF* */ + pool_foreach (swif, im->sw_interfaces, + ({ + send_acl_interface_etype_whitelist_details(am, reg, swif->sw_if_index, mp->context); + })); + /* *INDENT-ON* */ + } + else + { + sw_if_index = ntohl (mp->sw_if_index); + if (!pool_is_free_index (im->sw_interfaces, sw_if_index)) + send_acl_interface_etype_whitelist_details (am, reg, sw_if_index, + mp->context); + } +} + + + /* Set up the API message handling tables */ static clib_error_t * acl_plugin_api_hookup (vlib_main_t * vm) @@ -2852,6 +3262,10 @@ macip_acl_print (acl_main_t * am, u32 macip_acl_index) vlib_main_t *vm = am->vlib_main; int i; + /* Don't attempt to show the ACLs that do not exist */ + if (pool_is_free_index (am->macip_acls, macip_acl_index)) + return; + /* Don't try to print someone else's memory */ if (macip_acl_index > vec_len (am->macip_acls)) return; @@ -3013,6 +3427,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)) {