+ for (tags = 2; tags >= 0; tags--)
+ {
+ memset (mask, 0, sizeof (mask));
+ l3_src_offs = tags * 4 + get_l3_src_offset (is6);
+ 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);
+ }
+
+ /* add ARP table entry too */
+ if (!is6 && (mvec[match_type_index].arp_table_index != ~0))
+ {
+ 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);
+ }
+ if (macip_permit_also_egress (a->rules[i].is_permit))
+ {
+ /* Add the egress entry with destination set */
+ for (tags = 2; tags >= 0; tags--)
+ {
+ memset (mask, 0, sizeof (mask));
+ l3_dst_offs = tags * 4 + get_l3_dst_offset (is6);
+ /* src mac in the other direction becomes dst */
+ memcpy (&mask[0], a->rules[i].src_mac, 6);
+ switch (tags)
+ {
+ case 0:
+ default:
+ tag_table = mvec[match_type_index].out_table_index;
+ eth = 12;
+ break;
+ case 1:
+ tag_table = mvec[match_type_index].out_dot1q_table_index;
+ mask[12] = 0x81;
+ mask[13] = 0x00;
+ eth = 16;
+ break;
+ case 2:
+ tag_table = mvec[match_type_index].out_dot1ad_table_index;
+ mask[12] = 0x88;
+ mask[13] = 0xa8;
+ mask[16] = 0x81;
+ mask[17] = 0x00;
+ eth = 20;
+ break;
+ }
+ if (is6)
+ {
+ memcpy (&mask[l3_dst_offs], &a->rules[i].src_ip_addr.ip6,
+ 16);
+ mask[eth] = 0x86;
+ mask[eth + 1] = 0xdd;
+ }
+ else
+ {
+ memcpy (&mask[l3_dst_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);
+ }
+
+ /* 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);
+ }
+ }
+ }
+ return 0;
+}
+
+static void
+macip_destroy_classify_tables (acl_main_t * am, u32 macip_acl_index)
+{
+ vnet_classify_main_t *cm = &vnet_classify_main;
+ macip_acl_list_t *a = pool_elt_at_index (am->macip_acls, macip_acl_index);
+
+ if (a->ip4_table_index != ~0)
+ {
+ acl_classify_add_del_table_small (cm, 0, ~0, ~0, ~0,
+ &a->ip4_table_index, 0);
+ a->ip4_table_index = ~0;