- match = 1;
-
- void *oldheap = clib_mem_set_heap (cm->vlib_main->heap_base);
- int ret = vnet_classify_add_del_table (cm, skip_mask_ptr, nbuckets,
- memory_size, skip, match,
- next_table_index, miss_next_index,
- table_index, current_data_flag,
- current_data_offset, is_add,
- 1 /* delete_chain */ );
- clib_mem_set_heap (oldheap);
- 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;
- 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,
- 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);
- 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);
- vnet_l2_input_classify_enable_disable (sw_if_index, 0);
-
- if (am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
- {
- ip4_table_index =
- am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_index];
- am->acl_ip4_input_classify_table_by_sw_if_index[sw_if_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);
- }
- if (am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index] != ~0)
- {
- ip6_table_index =
- am->acl_ip6_input_classify_table_by_sw_if_index[sw_if_index];
- am->acl_ip6_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,
- 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);
- }
- 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;
-}
-
-static int
-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;
- 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,
- 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);
- 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);
-
- vnet_l2_output_classify_enable_disable (sw_if_index, 0);
-
- if (am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
- {
- ip4_table_index =
- am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_index];
- am->acl_ip4_output_classify_table_by_sw_if_index[sw_if_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);
- }
- if (am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index] != ~0)
- {
- ip6_table_index =
- am->acl_ip6_output_classify_table_by_sw_if_index[sw_if_index];
- am->acl_ip6_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,
- 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);
- }
- 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;
-}
-
-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;
- if (is_dot1ad)
- {
- /* 802.1ad ethertype */
- match[12] = 0x88;
- match[13] = 0xa8;
- /* 802.1q ethertype */
- match[16] = 0x81;
- match[17] = 0x00;
- }
- else
- {
- /* 802.1q ethertype */
- match[12] = 0x81;
- match[13] = 0x00;
- }
-
- /* 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);
- /* reset the mask back to being a mask */
- match[idx] = 0xff;
- match[idx + 1] = 0xff;
- match[12] = 0xff;
- match[13] = 0xff;
- if (is_dot1ad)
- {
- match[16] = 0xff;
- match[17] = 0xff;
- }
-}
-
-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;
- u32 ip4_table_index = ~0;
- 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);
-
- /* in case there were previous tables attached */
- acl_unhook_l2_input_classify (am, sw_if_index);
- 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, 1);
- if (rv)
- goto done;
-
- rv =
- 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, 1);
- 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);
- 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,
- etype_table_index, ~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, 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, 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;
- 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:
- clib_mem_set_heap (prevheap);
- return rv;
-}
-
-static int
-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;
- u32 etype_table_index = ~0;
- int rv;
-
- void *prevheap = clib_mem_set_heap (cm->vlib_main->heap_base);
-
- /* in case there were previous tables attached */
- acl_unhook_l2_output_classify (am, sw_if_index);
- rv =
- 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, 1);
- if (rv)
- goto done;
- rv =
- 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, 1);
- if (rv)
- {
- 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;
- }
-
- 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,
- etype_table_index, ~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;
- }