1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2019 Mellanox Technologies. */
6 static bool dr_mask_is_smac_set(struct mlx5dr_match_spec *spec)
8 return (spec->smac_47_16 || spec->smac_15_0);
11 static bool dr_mask_is_dmac_set(struct mlx5dr_match_spec *spec)
13 return (spec->dmac_47_16 || spec->dmac_15_0);
16 static bool dr_mask_is_src_addr_set(struct mlx5dr_match_spec *spec)
18 return (spec->src_ip_127_96 || spec->src_ip_95_64 ||
19 spec->src_ip_63_32 || spec->src_ip_31_0);
22 static bool dr_mask_is_dst_addr_set(struct mlx5dr_match_spec *spec)
24 return (spec->dst_ip_127_96 || spec->dst_ip_95_64 ||
25 spec->dst_ip_63_32 || spec->dst_ip_31_0);
28 static bool dr_mask_is_l3_base_set(struct mlx5dr_match_spec *spec)
30 return (spec->ip_protocol || spec->frag || spec->tcp_flags ||
31 spec->ip_ecn || spec->ip_dscp);
34 static bool dr_mask_is_tcp_udp_base_set(struct mlx5dr_match_spec *spec)
36 return (spec->tcp_sport || spec->tcp_dport ||
37 spec->udp_sport || spec->udp_dport);
40 static bool dr_mask_is_ipv4_set(struct mlx5dr_match_spec *spec)
42 return (spec->dst_ip_31_0 || spec->src_ip_31_0);
45 static bool dr_mask_is_ipv4_5_tuple_set(struct mlx5dr_match_spec *spec)
47 return (dr_mask_is_l3_base_set(spec) ||
48 dr_mask_is_tcp_udp_base_set(spec) ||
49 dr_mask_is_ipv4_set(spec));
52 static bool dr_mask_is_eth_l2_tnl_set(struct mlx5dr_match_misc *misc)
54 return misc->vxlan_vni;
57 static bool dr_mask_is_ttl_set(struct mlx5dr_match_spec *spec)
59 return spec->ttl_hoplimit;
62 #define DR_MASK_IS_L2_DST(_spec, _misc, _inner_outer) (_spec.first_vid || \
63 (_spec).first_cfi || (_spec).first_prio || (_spec).cvlan_tag || \
64 (_spec).svlan_tag || (_spec).dmac_47_16 || (_spec).dmac_15_0 || \
65 (_spec).ethertype || (_spec).ip_version || \
66 (_misc)._inner_outer##_second_vid || \
67 (_misc)._inner_outer##_second_cfi || \
68 (_misc)._inner_outer##_second_prio || \
69 (_misc)._inner_outer##_second_cvlan_tag || \
70 (_misc)._inner_outer##_second_svlan_tag)
72 #define DR_MASK_IS_ETH_L4_SET(_spec, _misc, _inner_outer) ( \
73 dr_mask_is_l3_base_set(&(_spec)) || \
74 dr_mask_is_tcp_udp_base_set(&(_spec)) || \
75 dr_mask_is_ttl_set(&(_spec)) || \
76 (_misc)._inner_outer##_ipv6_flow_label)
78 #define DR_MASK_IS_ETH_L4_MISC_SET(_misc3, _inner_outer) ( \
79 (_misc3)._inner_outer##_tcp_seq_num || \
80 (_misc3)._inner_outer##_tcp_ack_num)
82 #define DR_MASK_IS_FIRST_MPLS_SET(_misc2, _inner_outer) ( \
83 (_misc2)._inner_outer##_first_mpls_label || \
84 (_misc2)._inner_outer##_first_mpls_exp || \
85 (_misc2)._inner_outer##_first_mpls_s_bos || \
86 (_misc2)._inner_outer##_first_mpls_ttl)
88 static bool dr_mask_is_tnl_gre_set(struct mlx5dr_match_misc *misc)
90 return (misc->gre_key_h || misc->gre_key_l ||
91 misc->gre_protocol || misc->gre_c_present ||
92 misc->gre_k_present || misc->gre_s_present);
95 #define DR_MASK_IS_OUTER_MPLS_OVER_GRE_UDP_SET(_misc2, gre_udp) ( \
96 (_misc2).outer_first_mpls_over_##gre_udp##_label || \
97 (_misc2).outer_first_mpls_over_##gre_udp##_exp || \
98 (_misc2).outer_first_mpls_over_##gre_udp##_s_bos || \
99 (_misc2).outer_first_mpls_over_##gre_udp##_ttl)
101 #define DR_MASK_IS_TNL_MPLS_SET(_misc2) ( \
102 DR_MASK_IS_OUTER_MPLS_OVER_GRE_UDP_SET((_misc2), gre) || \
103 DR_MASK_IS_OUTER_MPLS_OVER_GRE_UDP_SET((_misc2), udp))
106 dr_mask_is_vxlan_gpe_set(struct mlx5dr_match_misc3 *misc3)
108 return (misc3->outer_vxlan_gpe_vni ||
109 misc3->outer_vxlan_gpe_next_protocol ||
110 misc3->outer_vxlan_gpe_flags);
114 dr_matcher_supp_vxlan_gpe(struct mlx5dr_cmd_caps *caps)
116 return caps->flex_protocols & MLX5_FLEX_PARSER_VXLAN_GPE_ENABLED;
120 dr_mask_is_tnl_vxlan_gpe(struct mlx5dr_match_param *mask,
121 struct mlx5dr_domain *dmn)
123 return dr_mask_is_vxlan_gpe_set(&mask->misc3) &&
124 dr_matcher_supp_vxlan_gpe(&dmn->info.caps);
127 static bool dr_mask_is_tnl_geneve_set(struct mlx5dr_match_misc *misc)
129 return misc->geneve_vni ||
131 misc->geneve_protocol_type ||
132 misc->geneve_opt_len;
136 dr_matcher_supp_tnl_geneve(struct mlx5dr_cmd_caps *caps)
138 return caps->flex_protocols & MLX5_FLEX_PARSER_GENEVE_ENABLED;
142 dr_mask_is_tnl_geneve(struct mlx5dr_match_param *mask,
143 struct mlx5dr_domain *dmn)
145 return dr_mask_is_tnl_geneve_set(&mask->misc) &&
146 dr_matcher_supp_tnl_geneve(&dmn->info.caps);
149 static int dr_matcher_supp_icmp_v4(struct mlx5dr_cmd_caps *caps)
151 return caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED;
154 static int dr_matcher_supp_icmp_v6(struct mlx5dr_cmd_caps *caps)
156 return caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED;
159 static bool dr_mask_is_icmpv6_set(struct mlx5dr_match_misc3 *misc3)
161 return (misc3->icmpv6_type || misc3->icmpv6_code ||
162 misc3->icmpv6_header_data);
165 static bool dr_mask_is_icmp(struct mlx5dr_match_param *mask,
166 struct mlx5dr_domain *dmn)
168 if (DR_MASK_IS_ICMPV4_SET(&mask->misc3))
169 return dr_matcher_supp_icmp_v4(&dmn->info.caps);
170 else if (dr_mask_is_icmpv6_set(&mask->misc3))
171 return dr_matcher_supp_icmp_v6(&dmn->info.caps);
176 static bool dr_mask_is_wqe_metadata_set(struct mlx5dr_match_misc2 *misc2)
178 return misc2->metadata_reg_a;
181 static bool dr_mask_is_reg_c_0_3_set(struct mlx5dr_match_misc2 *misc2)
183 return (misc2->metadata_reg_c_0 || misc2->metadata_reg_c_1 ||
184 misc2->metadata_reg_c_2 || misc2->metadata_reg_c_3);
187 static bool dr_mask_is_reg_c_4_7_set(struct mlx5dr_match_misc2 *misc2)
189 return (misc2->metadata_reg_c_4 || misc2->metadata_reg_c_5 ||
190 misc2->metadata_reg_c_6 || misc2->metadata_reg_c_7);
193 static bool dr_mask_is_gvmi_or_qpn_set(struct mlx5dr_match_misc *misc)
195 return (misc->source_sqn || misc->source_port);
198 int mlx5dr_matcher_select_builders(struct mlx5dr_matcher *matcher,
199 struct mlx5dr_matcher_rx_tx *nic_matcher,
200 enum mlx5dr_ipv outer_ipv,
201 enum mlx5dr_ipv inner_ipv)
203 nic_matcher->ste_builder =
204 nic_matcher->ste_builder_arr[outer_ipv][inner_ipv];
205 nic_matcher->num_of_builders =
206 nic_matcher->num_of_builders_arr[outer_ipv][inner_ipv];
208 if (!nic_matcher->num_of_builders) {
209 mlx5dr_dbg(matcher->tbl->dmn,
210 "Rule not supported on this matcher due to IP related fields\n");
217 static int dr_matcher_set_ste_builders(struct mlx5dr_matcher *matcher,
218 struct mlx5dr_matcher_rx_tx *nic_matcher,
219 enum mlx5dr_ipv outer_ipv,
220 enum mlx5dr_ipv inner_ipv)
222 struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn;
223 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
224 struct mlx5dr_match_param mask = {};
225 struct mlx5dr_ste_build *sb;
230 sb = nic_matcher->ste_builder_arr[outer_ipv][inner_ipv];
231 rx = nic_dmn->ste_type == MLX5DR_STE_TYPE_RX;
233 /* Create a temporary mask to track and clear used mask fields */
234 if (matcher->match_criteria & DR_MATCHER_CRITERIA_OUTER)
235 mask.outer = matcher->mask.outer;
237 if (matcher->match_criteria & DR_MATCHER_CRITERIA_MISC)
238 mask.misc = matcher->mask.misc;
240 if (matcher->match_criteria & DR_MATCHER_CRITERIA_INNER)
241 mask.inner = matcher->mask.inner;
243 if (matcher->match_criteria & DR_MATCHER_CRITERIA_MISC2)
244 mask.misc2 = matcher->mask.misc2;
246 if (matcher->match_criteria & DR_MATCHER_CRITERIA_MISC3)
247 mask.misc3 = matcher->mask.misc3;
249 ret = mlx5dr_ste_build_pre_check(dmn, matcher->match_criteria,
250 &matcher->mask, NULL);
255 if (matcher->match_criteria & (DR_MATCHER_CRITERIA_OUTER |
256 DR_MATCHER_CRITERIA_MISC |
257 DR_MATCHER_CRITERIA_MISC2 |
258 DR_MATCHER_CRITERIA_MISC3)) {
261 if (dr_mask_is_wqe_metadata_set(&mask.misc2))
262 mlx5dr_ste_build_general_purpose(&sb[idx++], &mask, inner, rx);
264 if (dr_mask_is_reg_c_0_3_set(&mask.misc2))
265 mlx5dr_ste_build_register_0(&sb[idx++], &mask, inner, rx);
267 if (dr_mask_is_reg_c_4_7_set(&mask.misc2))
268 mlx5dr_ste_build_register_1(&sb[idx++], &mask, inner, rx);
270 if (dr_mask_is_gvmi_or_qpn_set(&mask.misc) &&
271 (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
272 dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX)) {
273 mlx5dr_ste_build_src_gvmi_qpn(&sb[idx++], &mask,
277 if (dr_mask_is_smac_set(&mask.outer) &&
278 dr_mask_is_dmac_set(&mask.outer)) {
279 mlx5dr_ste_build_eth_l2_src_dst(&sb[idx++], &mask,
283 if (dr_mask_is_smac_set(&mask.outer))
284 mlx5dr_ste_build_eth_l2_src(&sb[idx++], &mask, inner, rx);
286 if (DR_MASK_IS_L2_DST(mask.outer, mask.misc, outer))
287 mlx5dr_ste_build_eth_l2_dst(&sb[idx++], &mask, inner, rx);
289 if (outer_ipv == DR_RULE_IPV6) {
290 if (dr_mask_is_dst_addr_set(&mask.outer))
291 mlx5dr_ste_build_eth_l3_ipv6_dst(&sb[idx++], &mask,
294 if (dr_mask_is_src_addr_set(&mask.outer))
295 mlx5dr_ste_build_eth_l3_ipv6_src(&sb[idx++], &mask,
298 if (DR_MASK_IS_ETH_L4_SET(mask.outer, mask.misc, outer))
299 mlx5dr_ste_build_eth_ipv6_l3_l4(&sb[idx++], &mask,
302 if (dr_mask_is_ipv4_5_tuple_set(&mask.outer))
303 mlx5dr_ste_build_eth_l3_ipv4_5_tuple(&sb[idx++], &mask,
306 if (dr_mask_is_ttl_set(&mask.outer))
307 mlx5dr_ste_build_eth_l3_ipv4_misc(&sb[idx++], &mask,
311 if (dr_mask_is_tnl_vxlan_gpe(&mask, dmn))
312 mlx5dr_ste_build_tnl_vxlan_gpe(&sb[idx++], &mask,
314 else if (dr_mask_is_tnl_geneve(&mask, dmn))
315 mlx5dr_ste_build_tnl_geneve(&sb[idx++], &mask,
318 if (DR_MASK_IS_ETH_L4_MISC_SET(mask.misc3, outer))
319 mlx5dr_ste_build_eth_l4_misc(&sb[idx++], &mask, inner, rx);
321 if (DR_MASK_IS_FIRST_MPLS_SET(mask.misc2, outer))
322 mlx5dr_ste_build_mpls(&sb[idx++], &mask, inner, rx);
324 if (DR_MASK_IS_TNL_MPLS_SET(mask.misc2))
325 mlx5dr_ste_build_tnl_mpls(&sb[idx++], &mask, inner, rx);
327 if (dr_mask_is_icmp(&mask, dmn)) {
328 ret = mlx5dr_ste_build_icmp(&sb[idx++],
329 &mask, &dmn->info.caps,
334 if (dr_mask_is_tnl_gre_set(&mask.misc))
335 mlx5dr_ste_build_tnl_gre(&sb[idx++], &mask, inner, rx);
339 if (matcher->match_criteria & (DR_MATCHER_CRITERIA_INNER |
340 DR_MATCHER_CRITERIA_MISC |
341 DR_MATCHER_CRITERIA_MISC2 |
342 DR_MATCHER_CRITERIA_MISC3)) {
345 if (dr_mask_is_eth_l2_tnl_set(&mask.misc))
346 mlx5dr_ste_build_eth_l2_tnl(&sb[idx++], &mask, inner, rx);
348 if (dr_mask_is_smac_set(&mask.inner) &&
349 dr_mask_is_dmac_set(&mask.inner)) {
350 mlx5dr_ste_build_eth_l2_src_dst(&sb[idx++],
354 if (dr_mask_is_smac_set(&mask.inner))
355 mlx5dr_ste_build_eth_l2_src(&sb[idx++], &mask, inner, rx);
357 if (DR_MASK_IS_L2_DST(mask.inner, mask.misc, inner))
358 mlx5dr_ste_build_eth_l2_dst(&sb[idx++], &mask, inner, rx);
360 if (inner_ipv == DR_RULE_IPV6) {
361 if (dr_mask_is_dst_addr_set(&mask.inner))
362 mlx5dr_ste_build_eth_l3_ipv6_dst(&sb[idx++], &mask,
365 if (dr_mask_is_src_addr_set(&mask.inner))
366 mlx5dr_ste_build_eth_l3_ipv6_src(&sb[idx++], &mask,
369 if (DR_MASK_IS_ETH_L4_SET(mask.inner, mask.misc, inner))
370 mlx5dr_ste_build_eth_ipv6_l3_l4(&sb[idx++], &mask,
373 if (dr_mask_is_ipv4_5_tuple_set(&mask.inner))
374 mlx5dr_ste_build_eth_l3_ipv4_5_tuple(&sb[idx++], &mask,
377 if (dr_mask_is_ttl_set(&mask.inner))
378 mlx5dr_ste_build_eth_l3_ipv4_misc(&sb[idx++], &mask,
382 if (DR_MASK_IS_ETH_L4_MISC_SET(mask.misc3, inner))
383 mlx5dr_ste_build_eth_l4_misc(&sb[idx++], &mask, inner, rx);
385 if (DR_MASK_IS_FIRST_MPLS_SET(mask.misc2, inner))
386 mlx5dr_ste_build_mpls(&sb[idx++], &mask, inner, rx);
388 if (DR_MASK_IS_TNL_MPLS_SET(mask.misc2))
389 mlx5dr_ste_build_tnl_mpls(&sb[idx++], &mask, inner, rx);
391 /* Empty matcher, takes all */
392 if (matcher->match_criteria == DR_MATCHER_CRITERIA_EMPTY)
393 mlx5dr_ste_build_empty_always_hit(&sb[idx++], rx);
396 mlx5dr_err(dmn, "Cannot generate any valid rules from mask\n");
400 /* Check that all mask fields were consumed */
401 for (i = 0; i < sizeof(struct mlx5dr_match_param); i++) {
402 if (((u8 *)&mask)[i] != 0) {
403 mlx5dr_dbg(dmn, "Mask contains unsupported parameters\n");
408 nic_matcher->ste_builder = sb;
409 nic_matcher->num_of_builders_arr[outer_ipv][inner_ipv] = idx;
414 static int dr_matcher_connect(struct mlx5dr_domain *dmn,
415 struct mlx5dr_matcher_rx_tx *curr_nic_matcher,
416 struct mlx5dr_matcher_rx_tx *next_nic_matcher,
417 struct mlx5dr_matcher_rx_tx *prev_nic_matcher)
419 struct mlx5dr_table_rx_tx *nic_tbl = curr_nic_matcher->nic_tbl;
420 struct mlx5dr_domain_rx_tx *nic_dmn = nic_tbl->nic_dmn;
421 struct mlx5dr_htbl_connect_info info;
422 struct mlx5dr_ste_htbl *prev_htbl;
425 /* Connect end anchor hash table to next_htbl or to the default address */
426 if (next_nic_matcher) {
427 info.type = CONNECT_HIT;
428 info.hit_next_htbl = next_nic_matcher->s_htbl;
430 info.type = CONNECT_MISS;
431 info.miss_icm_addr = nic_tbl->default_icm_addr;
433 ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn,
434 curr_nic_matcher->e_anchor,
435 &info, info.type == CONNECT_HIT);
439 /* Connect start hash table to end anchor */
440 info.type = CONNECT_MISS;
441 info.miss_icm_addr = curr_nic_matcher->e_anchor->chunk->icm_addr;
442 ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn,
443 curr_nic_matcher->s_htbl,
448 /* Connect previous hash table to matcher start hash table */
449 if (prev_nic_matcher)
450 prev_htbl = prev_nic_matcher->e_anchor;
452 prev_htbl = nic_tbl->s_anchor;
454 info.type = CONNECT_HIT;
455 info.hit_next_htbl = curr_nic_matcher->s_htbl;
456 ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, prev_htbl,
461 /* Update the pointing ste and next hash table */
462 curr_nic_matcher->s_htbl->pointing_ste = prev_htbl->ste_arr;
463 prev_htbl->ste_arr[0].next_htbl = curr_nic_matcher->s_htbl;
465 if (next_nic_matcher) {
466 next_nic_matcher->s_htbl->pointing_ste = curr_nic_matcher->e_anchor->ste_arr;
467 curr_nic_matcher->e_anchor->ste_arr[0].next_htbl = next_nic_matcher->s_htbl;
473 static int dr_matcher_add_to_tbl(struct mlx5dr_matcher *matcher)
475 struct mlx5dr_matcher *next_matcher, *prev_matcher, *tmp_matcher;
476 struct mlx5dr_table *tbl = matcher->tbl;
477 struct mlx5dr_domain *dmn = tbl->dmn;
482 list_for_each_entry(tmp_matcher, &tbl->matcher_list, matcher_list) {
483 if (tmp_matcher->prio >= matcher->prio) {
484 next_matcher = tmp_matcher;
491 if (next_matcher && !first)
492 prev_matcher = list_prev_entry(next_matcher, matcher_list);
494 prev_matcher = list_last_entry(&tbl->matcher_list,
495 struct mlx5dr_matcher,
498 if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
499 dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) {
500 ret = dr_matcher_connect(dmn, &matcher->rx,
501 next_matcher ? &next_matcher->rx : NULL,
502 prev_matcher ? &prev_matcher->rx : NULL);
507 if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
508 dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX) {
509 ret = dr_matcher_connect(dmn, &matcher->tx,
510 next_matcher ? &next_matcher->tx : NULL,
511 prev_matcher ? &prev_matcher->tx : NULL);
517 list_add(&matcher->matcher_list, &prev_matcher->matcher_list);
518 else if (next_matcher)
519 list_add_tail(&matcher->matcher_list,
520 &next_matcher->matcher_list);
522 list_add(&matcher->matcher_list, &tbl->matcher_list);
527 static void dr_matcher_uninit_nic(struct mlx5dr_matcher_rx_tx *nic_matcher)
529 mlx5dr_htbl_put(nic_matcher->s_htbl);
530 mlx5dr_htbl_put(nic_matcher->e_anchor);
533 static void dr_matcher_uninit_fdb(struct mlx5dr_matcher *matcher)
535 dr_matcher_uninit_nic(&matcher->rx);
536 dr_matcher_uninit_nic(&matcher->tx);
539 static void dr_matcher_uninit(struct mlx5dr_matcher *matcher)
541 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
544 case MLX5DR_DOMAIN_TYPE_NIC_RX:
545 dr_matcher_uninit_nic(&matcher->rx);
547 case MLX5DR_DOMAIN_TYPE_NIC_TX:
548 dr_matcher_uninit_nic(&matcher->tx);
550 case MLX5DR_DOMAIN_TYPE_FDB:
551 dr_matcher_uninit_fdb(matcher);
559 static int dr_matcher_set_all_ste_builders(struct mlx5dr_matcher *matcher,
560 struct mlx5dr_matcher_rx_tx *nic_matcher)
562 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
564 dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV4, DR_RULE_IPV4);
565 dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV4, DR_RULE_IPV6);
566 dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV6, DR_RULE_IPV4);
567 dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV6, DR_RULE_IPV6);
569 if (!nic_matcher->ste_builder) {
570 mlx5dr_err(dmn, "Cannot generate IPv4 or IPv6 rules with given mask\n");
577 static int dr_matcher_init_nic(struct mlx5dr_matcher *matcher,
578 struct mlx5dr_matcher_rx_tx *nic_matcher)
580 struct mlx5dr_domain *dmn = matcher->tbl->dmn;
583 ret = dr_matcher_set_all_ste_builders(matcher, nic_matcher);
587 nic_matcher->e_anchor = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
589 MLX5DR_STE_LU_TYPE_DONT_CARE,
591 if (!nic_matcher->e_anchor)
594 nic_matcher->s_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool,
596 nic_matcher->ste_builder[0].lu_type,
597 nic_matcher->ste_builder[0].byte_mask);
598 if (!nic_matcher->s_htbl) {
603 /* make sure the tables exist while empty */
604 mlx5dr_htbl_get(nic_matcher->s_htbl);
605 mlx5dr_htbl_get(nic_matcher->e_anchor);
610 mlx5dr_ste_htbl_free(nic_matcher->e_anchor);
614 static int dr_matcher_init_fdb(struct mlx5dr_matcher *matcher)
618 ret = dr_matcher_init_nic(matcher, &matcher->rx);
622 ret = dr_matcher_init_nic(matcher, &matcher->tx);
629 dr_matcher_uninit_nic(&matcher->rx);
633 static int dr_matcher_init(struct mlx5dr_matcher *matcher,
634 struct mlx5dr_match_parameters *mask)
636 struct mlx5dr_table *tbl = matcher->tbl;
637 struct mlx5dr_domain *dmn = tbl->dmn;
640 if (matcher->match_criteria >= DR_MATCHER_CRITERIA_MAX) {
641 mlx5dr_err(dmn, "Invalid match criteria attribute\n");
646 if (mask->match_sz > DR_SZ_MATCH_PARAM) {
647 mlx5dr_err(dmn, "Invalid match size attribute\n");
650 mlx5dr_ste_copy_param(matcher->match_criteria,
651 &matcher->mask, mask);
655 case MLX5DR_DOMAIN_TYPE_NIC_RX:
656 matcher->rx.nic_tbl = &tbl->rx;
657 ret = dr_matcher_init_nic(matcher, &matcher->rx);
659 case MLX5DR_DOMAIN_TYPE_NIC_TX:
660 matcher->tx.nic_tbl = &tbl->tx;
661 ret = dr_matcher_init_nic(matcher, &matcher->tx);
663 case MLX5DR_DOMAIN_TYPE_FDB:
664 matcher->rx.nic_tbl = &tbl->rx;
665 matcher->tx.nic_tbl = &tbl->tx;
666 ret = dr_matcher_init_fdb(matcher);
676 struct mlx5dr_matcher *
677 mlx5dr_matcher_create(struct mlx5dr_table *tbl,
679 u8 match_criteria_enable,
680 struct mlx5dr_match_parameters *mask)
682 struct mlx5dr_matcher *matcher;
685 refcount_inc(&tbl->refcount);
687 matcher = kzalloc(sizeof(*matcher), GFP_KERNEL);
692 matcher->prio = priority;
693 matcher->match_criteria = match_criteria_enable;
694 refcount_set(&matcher->refcount, 1);
695 INIT_LIST_HEAD(&matcher->matcher_list);
697 mlx5dr_domain_lock(tbl->dmn);
699 ret = dr_matcher_init(matcher, mask);
703 ret = dr_matcher_add_to_tbl(matcher);
707 mlx5dr_domain_unlock(tbl->dmn);
712 dr_matcher_uninit(matcher);
714 mlx5dr_domain_unlock(tbl->dmn);
717 refcount_dec(&tbl->refcount);
721 static int dr_matcher_disconnect(struct mlx5dr_domain *dmn,
722 struct mlx5dr_table_rx_tx *nic_tbl,
723 struct mlx5dr_matcher_rx_tx *next_nic_matcher,
724 struct mlx5dr_matcher_rx_tx *prev_nic_matcher)
726 struct mlx5dr_domain_rx_tx *nic_dmn = nic_tbl->nic_dmn;
727 struct mlx5dr_htbl_connect_info info;
728 struct mlx5dr_ste_htbl *prev_anchor;
730 if (prev_nic_matcher)
731 prev_anchor = prev_nic_matcher->e_anchor;
733 prev_anchor = nic_tbl->s_anchor;
735 /* Connect previous anchor hash table to next matcher or to the default address */
736 if (next_nic_matcher) {
737 info.type = CONNECT_HIT;
738 info.hit_next_htbl = next_nic_matcher->s_htbl;
739 next_nic_matcher->s_htbl->pointing_ste = prev_anchor->ste_arr;
740 prev_anchor->ste_arr[0].next_htbl = next_nic_matcher->s_htbl;
742 info.type = CONNECT_MISS;
743 info.miss_icm_addr = nic_tbl->default_icm_addr;
744 prev_anchor->ste_arr[0].next_htbl = NULL;
747 return mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, prev_anchor,
751 static int dr_matcher_remove_from_tbl(struct mlx5dr_matcher *matcher)
753 struct mlx5dr_matcher *prev_matcher, *next_matcher;
754 struct mlx5dr_table *tbl = matcher->tbl;
755 struct mlx5dr_domain *dmn = tbl->dmn;
758 if (list_is_last(&matcher->matcher_list, &tbl->matcher_list))
761 next_matcher = list_next_entry(matcher, matcher_list);
763 if (matcher->matcher_list.prev == &tbl->matcher_list)
766 prev_matcher = list_prev_entry(matcher, matcher_list);
768 if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
769 dmn->type == MLX5DR_DOMAIN_TYPE_NIC_RX) {
770 ret = dr_matcher_disconnect(dmn, &tbl->rx,
771 next_matcher ? &next_matcher->rx : NULL,
772 prev_matcher ? &prev_matcher->rx : NULL);
777 if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB ||
778 dmn->type == MLX5DR_DOMAIN_TYPE_NIC_TX) {
779 ret = dr_matcher_disconnect(dmn, &tbl->tx,
780 next_matcher ? &next_matcher->tx : NULL,
781 prev_matcher ? &prev_matcher->tx : NULL);
786 list_del(&matcher->matcher_list);
791 int mlx5dr_matcher_destroy(struct mlx5dr_matcher *matcher)
793 struct mlx5dr_table *tbl = matcher->tbl;
795 if (refcount_read(&matcher->refcount) > 1)
798 mlx5dr_domain_lock(tbl->dmn);
800 dr_matcher_remove_from_tbl(matcher);
801 dr_matcher_uninit(matcher);
802 refcount_dec(&matcher->tbl->refcount);
804 mlx5dr_domain_unlock(tbl->dmn);