Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 NVIDIA Corporation & Affiliates
3 : : */
4 : :
5 : : #include "mlx5dr_internal.h"
6 : :
7 : : #define GTP_PDU_SC 0x85
8 : : #define BAD_PORT 0xBAD
9 : : #define ETH_TYPE_IPV4_VXLAN 0x0800
10 : : #define ETH_TYPE_IPV6_VXLAN 0x86DD
11 : : #define UDP_VXLAN_PORT 4789
12 : : #define UDP_VXLAN_GPE_PORT 4790
13 : : #define UDP_GTPU_PORT 2152
14 : : #define UDP_PORT_MPLS 6635
15 : : #define UDP_GENEVE_PORT 6081
16 : : #define UDP_ROCEV2_PORT 4791
17 : : #define DR_FLOW_LAYER_TUNNEL_NO_MPLS (MLX5_FLOW_LAYER_TUNNEL & ~MLX5_FLOW_LAYER_MPLS)
18 : :
19 : : #define STE_NO_VLAN 0x0
20 : : #define STE_SVLAN 0x1
21 : : #define STE_CVLAN 0x2
22 : : #define STE_NO_L3 0x0
23 : : #define STE_IPV4 0x1
24 : : #define STE_IPV6 0x2
25 : : #define STE_NO_L4 0x0
26 : : #define STE_TCP 0x1
27 : : #define STE_UDP 0x2
28 : : #define STE_ICMP 0x3
29 : : #define STE_NO_TUN 0x0
30 : : #define STE_ESP 0x3
31 : :
32 : : #define MLX5DR_DEFINER_QUOTA_BLOCK 0
33 : : #define MLX5DR_DEFINER_QUOTA_PASS 2
34 : :
35 : : /* Setter function based on bit offset and mask, for 32bit DW*/
36 : : #define _DR_SET_32(p, v, byte_off, bit_off, mask) \
37 : : do { \
38 : : u32 _v = v; \
39 : : *((rte_be32_t *)(p) + ((byte_off) / 4)) = \
40 : : rte_cpu_to_be_32((rte_be_to_cpu_32(*((u32 *)(p) + \
41 : : ((byte_off) / 4))) & \
42 : : (~((mask) << (bit_off)))) | \
43 : : (((_v) & (mask)) << \
44 : : (bit_off))); \
45 : : } while (0)
46 : :
47 : : /* Getter function based on bit offset and mask, for 32bit DW*/
48 : : #define DR_GET_32(p, byte_off, bit_off, mask) \
49 : : ((rte_be_to_cpu_32(*((const rte_be32_t *)(p) + ((byte_off) / 4))) >> (bit_off)) & (mask))
50 : :
51 : : /* Setter function based on bit offset and mask */
52 : : #define DR_SET(p, v, byte_off, bit_off, mask) \
53 : : do { \
54 : : if (unlikely((bit_off) < 0)) { \
55 : : u32 _bit_off = -1 * (bit_off); \
56 : : u32 second_dw_mask = (mask) & ((1 << _bit_off) - 1); \
57 : : _DR_SET_32(p, (v) >> _bit_off, byte_off, 0, (mask) >> _bit_off); \
58 : : _DR_SET_32(p, (v) & second_dw_mask, (byte_off) + DW_SIZE, \
59 : : (bit_off) % BITS_IN_DW, second_dw_mask); \
60 : : } else { \
61 : : _DR_SET_32(p, v, byte_off, (bit_off), (mask)); \
62 : : } \
63 : : } while (0)
64 : :
65 : : /* Setter function based on byte offset to directly set FULL BE32 value */
66 : : #define DR_SET_BE32(p, v, byte_off, bit_off, mask) \
67 : : (*((rte_be32_t *)((uint8_t *)(p) + (byte_off))) = (v))
68 : :
69 : : /* Setter function based on byte offset to directly set FULL BE32 value from ptr */
70 : : #define DR_SET_BE32P(p, v_ptr, byte_off, bit_off, mask) \
71 : : memcpy((uint8_t *)(p) + (byte_off), v_ptr, 4)
72 : :
73 : : /* Setter function based on byte offset to directly set FULL BE16 value */
74 : : #define DR_SET_BE16(p, v, byte_off, bit_off, mask) \
75 : : (*((rte_be16_t *)((uint8_t *)(p) + (byte_off))) = (v))
76 : :
77 : : /* Setter function based on byte offset to directly set FULL BE16 value from ptr */
78 : : #define DR_SET_BE16P(p, v_ptr, byte_off, bit_off, mask) \
79 : : memcpy((uint8_t *)(p) + (byte_off), v_ptr, 2)
80 : :
81 : : #define DR_CALC_FNAME(field, inner) \
82 : : ((inner) ? MLX5DR_DEFINER_FNAME_##field##_I : \
83 : : MLX5DR_DEFINER_FNAME_##field##_O)
84 : :
85 : : #define DR_CALC_SET_HDR(fc, hdr, field) \
86 : : do { \
87 : : (fc)->bit_mask = __mlx5_mask(definer_hl, hdr.field); \
88 : : (fc)->bit_off = __mlx5_dw_bit_off(definer_hl, hdr.field); \
89 : : (fc)->byte_off = MLX5_BYTE_OFF(definer_hl, hdr.field); \
90 : : } while (0)
91 : :
92 : : /* Helper to calculate data used by DR_SET */
93 : : #define DR_CALC_SET(fc, hdr, field, is_inner) \
94 : : do { \
95 : : if (is_inner) { \
96 : : DR_CALC_SET_HDR(fc, hdr##_inner, field); \
97 : : } else { \
98 : : DR_CALC_SET_HDR(fc, hdr##_outer, field); \
99 : : } \
100 : : } while (0)
101 : :
102 : : #define DR_GET(typ, p, fld) \
103 : : ((rte_be_to_cpu_32(*((const rte_be32_t *)(p) + \
104 : : __mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
105 : : __mlx5_mask(typ, fld))
106 : :
107 : : #define MAX_ROW_LOG 31
108 : :
109 : : enum header_layout {
110 : : MLX5DR_HL_IPV4_SRC = 64,
111 : : MLX5DR_HL_IPV4_DST = 65,
112 : : MAX_HL_PRIO,
113 : : };
114 : :
115 : : /* Each row (i) indicates a different matcher size, and each column (j)
116 : : * represents {DW5, DW4, DW3, DW2, DW1, DW0}.
117 : : * For values 0,..,2^i, and j (DW) 0,..,5: optimal_dist_dw[i][j] is 1 if the
118 : : * number of different hash results on these values equals 2^i, meaning this
119 : : * DW hash distribution is complete.
120 : : */
121 : : int optimal_dist_dw[MAX_ROW_LOG][DW_SELECTORS_MATCH] = {
122 : : {1, 1, 1, 1, 1, 1}, {0, 1, 1, 0, 1, 0}, {0, 1, 1, 0, 1, 0},
123 : : {1, 0, 1, 0, 1, 0}, {0, 0, 0, 1, 1, 0}, {0, 1, 1, 0, 1, 0},
124 : : {0, 0, 0, 0, 1, 0}, {0, 1, 1, 0, 1, 0}, {0, 0, 0, 0, 0, 0},
125 : : {1, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 1, 0, 1, 0, 0},
126 : : {1, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 1}, {1, 1, 1, 0, 0, 0},
127 : : {1, 1, 1, 0, 1, 0}, {0, 0, 1, 1, 0, 0}, {0, 1, 1, 0, 0, 1},
128 : : {0, 0, 1, 0, 0, 1}, {0, 0, 1, 0, 0, 0}, {1, 0, 1, 1, 0, 0},
129 : : {1, 0, 1, 0, 0, 1}, {0, 0, 1, 1, 0, 1}, {1, 1, 1, 0, 0, 0},
130 : : {0, 1, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 1, 1, 1},
131 : : {0, 0, 1, 0, 0, 1}, {1, 1, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 0},
132 : : {0, 0, 0, 1, 1, 0}};
133 : :
134 : : struct mlx5dr_definer_sel_ctrl {
135 : : uint8_t allowed_full_dw; /* Full DW selectors cover all offsets */
136 : : uint8_t allowed_lim_dw; /* Limited DW selectors cover offset < 64 */
137 : : uint8_t allowed_bytes; /* Bytes selectors, up to offset 255 */
138 : : uint8_t used_full_dw;
139 : : uint8_t used_lim_dw;
140 : : uint8_t used_bytes;
141 : : uint8_t full_dw_selector[DW_SELECTORS];
142 : : uint8_t lim_dw_selector[DW_SELECTORS_LIMITED];
143 : : uint8_t byte_selector[BYTE_SELECTORS];
144 : : };
145 : :
146 : : struct mlx5dr_definer_conv_data {
147 : : struct mlx5dr_context *ctx;
148 : : struct mlx5dr_definer_fc *fc;
149 : : uint8_t relaxed;
150 : : uint8_t tunnel;
151 : : uint8_t mpls_idx;
152 : : uint8_t geneve_opt_ok_idx;
153 : : uint8_t geneve_opt_data_idx;
154 : : enum rte_flow_item_type last_item;
155 : : };
156 : :
157 : : /* Xmacro used to create generic item setter from items */
158 : : #define LIST_OF_FIELDS_INFO \
159 : : X(SET_BE16, eth_type, v->hdr.ether_type, rte_flow_item_eth) \
160 : : X(SET_BE32P, eth_smac_47_16, &v->hdr.src_addr.addr_bytes[0], rte_flow_item_eth) \
161 : : X(SET_BE16P, eth_smac_15_0, &v->hdr.src_addr.addr_bytes[4], rte_flow_item_eth) \
162 : : X(SET_BE32P, eth_dmac_47_16, &v->hdr.dst_addr.addr_bytes[0], rte_flow_item_eth) \
163 : : X(SET_BE16P, eth_dmac_15_0, &v->hdr.dst_addr.addr_bytes[4], rte_flow_item_eth) \
164 : : X(SET_BE16, tci, v->hdr.vlan_tci, rte_flow_item_vlan) \
165 : : X(SET, ipv4_ihl, v->ihl, rte_ipv4_hdr) \
166 : : X(SET, ipv4_tos, v->type_of_service, rte_ipv4_hdr) \
167 : : X(SET, ipv4_time_to_live, v->time_to_live, rte_ipv4_hdr) \
168 : : X(SET_BE32, ipv4_dst_addr, v->dst_addr, rte_ipv4_hdr) \
169 : : X(SET_BE32, ipv4_src_addr, v->src_addr, rte_ipv4_hdr) \
170 : : X(SET, ipv4_next_proto, v->next_proto_id, rte_ipv4_hdr) \
171 : : X(SET, ipv4_version, STE_IPV4, rte_ipv4_hdr) \
172 : : X(SET_BE16, ipv4_frag, v->fragment_offset, rte_ipv4_hdr) \
173 : : X(SET_BE16, ipv4_len, v->total_length, rte_ipv4_hdr) \
174 : : X(SET, ip_fragmented, !!v->fragment_offset, rte_ipv4_hdr) \
175 : : X(SET_BE16, ipv6_payload_len, v->hdr.payload_len, rte_flow_item_ipv6) \
176 : : X(SET, ipv6_proto, v->hdr.proto, rte_flow_item_ipv6) \
177 : : X(SET, ipv6_routing_hdr, IPPROTO_ROUTING, rte_flow_item_ipv6) \
178 : : X(SET, ipv6_hop_limits, v->hdr.hop_limits, rte_flow_item_ipv6) \
179 : : X(SET_BE32P, ipv6_src_addr_127_96, &v->hdr.src_addr[0], rte_flow_item_ipv6) \
180 : : X(SET_BE32P, ipv6_src_addr_95_64, &v->hdr.src_addr[4], rte_flow_item_ipv6) \
181 : : X(SET_BE32P, ipv6_src_addr_63_32, &v->hdr.src_addr[8], rte_flow_item_ipv6) \
182 : : X(SET_BE32P, ipv6_src_addr_31_0, &v->hdr.src_addr[12], rte_flow_item_ipv6) \
183 : : X(SET_BE32P, ipv6_dst_addr_127_96, &v->hdr.dst_addr[0], rte_flow_item_ipv6) \
184 : : X(SET_BE32P, ipv6_dst_addr_95_64, &v->hdr.dst_addr[4], rte_flow_item_ipv6) \
185 : : X(SET_BE32P, ipv6_dst_addr_63_32, &v->hdr.dst_addr[8], rte_flow_item_ipv6) \
186 : : X(SET_BE32P, ipv6_dst_addr_31_0, &v->hdr.dst_addr[12], rte_flow_item_ipv6) \
187 : : X(SET, ipv6_version, STE_IPV6, rte_flow_item_ipv6) \
188 : : X(SET, ipv6_frag, v->has_frag_ext, rte_flow_item_ipv6) \
189 : : X(SET, icmp_protocol, STE_ICMP, rte_flow_item_icmp) \
190 : : X(SET, udp_protocol, STE_UDP, rte_flow_item_udp) \
191 : : X(SET_BE16, udp_src_port, v->hdr.src_port, rte_flow_item_udp) \
192 : : X(SET_BE16, udp_dst_port, v->hdr.dst_port, rte_flow_item_udp) \
193 : : X(SET, tcp_flags, v->hdr.tcp_flags, rte_flow_item_tcp) \
194 : : X(SET, tcp_protocol, STE_TCP, rte_flow_item_tcp) \
195 : : X(SET_BE16, tcp_src_port, v->hdr.src_port, rte_flow_item_tcp) \
196 : : X(SET_BE16, tcp_dst_port, v->hdr.dst_port, rte_flow_item_tcp) \
197 : : X(SET, gtp_udp_port, UDP_GTPU_PORT, rte_flow_item_gtp) \
198 : : X(SET_BE32, gtp_teid, v->hdr.teid, rte_flow_item_gtp) \
199 : : X(SET, gtp_msg_type, v->hdr.msg_type, rte_flow_item_gtp) \
200 : : X(SET, gtp_ext_flag, !!v->hdr.gtp_hdr_info, rte_flow_item_gtp) \
201 : : X(SET, gtp_next_ext_hdr, GTP_PDU_SC, rte_flow_item_gtp_psc) \
202 : : X(SET, gtp_ext_hdr_pdu, v->hdr.type, rte_flow_item_gtp_psc) \
203 : : X(SET, gtp_ext_hdr_qfi, v->hdr.qfi, rte_flow_item_gtp_psc) \
204 : : X(SET, vxlan_flags, v->flags, rte_flow_item_vxlan) \
205 : : X(SET, vxlan_udp_port, UDP_VXLAN_PORT, rte_flow_item_vxlan) \
206 : : X(SET, vxlan_gpe_udp_port, UDP_VXLAN_GPE_PORT, rte_flow_item_vxlan_gpe) \
207 : : X(SET, vxlan_gpe_flags, v->flags, rte_flow_item_vxlan_gpe) \
208 : : X(SET, vxlan_gpe_protocol, v->protocol, rte_flow_item_vxlan_gpe) \
209 : : X(SET, vxlan_gpe_rsvd1, v->rsvd1, rte_flow_item_vxlan_gpe) \
210 : : X(SET, mpls_udp_port, UDP_PORT_MPLS, rte_flow_item_mpls) \
211 : : X(SET, source_qp, v->queue, mlx5_rte_flow_item_sq) \
212 : : X(SET, tag, v->data, rte_flow_item_tag) \
213 : : X(SET, metadata, v->data, rte_flow_item_meta) \
214 : : X(SET_BE16, geneve_protocol, v->protocol, rte_flow_item_geneve) \
215 : : X(SET, geneve_udp_port, UDP_GENEVE_PORT, rte_flow_item_geneve) \
216 : : X(SET_BE16, geneve_ctrl, v->ver_opt_len_o_c_rsvd0, rte_flow_item_geneve) \
217 : : X(SET_BE16, gre_c_ver, v->c_rsvd0_ver, rte_flow_item_gre) \
218 : : X(SET_BE16, gre_protocol_type, v->protocol, rte_flow_item_gre) \
219 : : X(SET, ipv4_protocol_gre, IPPROTO_GRE, rte_flow_item_gre) \
220 : : X(SET_BE32, gre_opt_key, v->key.key, rte_flow_item_gre_opt) \
221 : : X(SET_BE32, gre_opt_seq, v->sequence.sequence, rte_flow_item_gre_opt) \
222 : : X(SET_BE16, gre_opt_checksum, v->checksum_rsvd.checksum, rte_flow_item_gre_opt) \
223 : : X(SET, meter_color, rte_col_2_mlx5_col(v->color), rte_flow_item_meter_color) \
224 : : X(SET_BE32, ipsec_spi, v->hdr.spi, rte_flow_item_esp) \
225 : : X(SET_BE32, ipsec_sequence_number, v->hdr.seq, rte_flow_item_esp) \
226 : : X(SET, ib_l4_udp_port, UDP_ROCEV2_PORT, rte_flow_item_ib_bth) \
227 : : X(SET, ib_l4_opcode, v->hdr.opcode, rte_flow_item_ib_bth) \
228 : : X(SET, random_number, v->value, rte_flow_item_random) \
229 : : X(SET, ib_l4_bth_a, v->hdr.a, rte_flow_item_ib_bth) \
230 : : X(SET, cvlan, STE_CVLAN, rte_flow_item_vlan) \
231 : : X(SET_BE16, inner_type, v->inner_type, rte_flow_item_vlan) \
232 : :
233 : : /* Item set function format */
234 : : #define X(set_type, func_name, value, item_type) \
235 : : static void mlx5dr_definer_##func_name##_set( \
236 : : struct mlx5dr_definer_fc *fc, \
237 : : const void *item_spec, \
238 : : uint8_t *tag) \
239 : : { \
240 : : __rte_unused const struct item_type *v = item_spec; \
241 : : DR_##set_type(tag, value, fc->byte_off, fc->bit_off, fc->bit_mask); \
242 : : }
243 [ # # # # : 0 : LIST_OF_FIELDS_INFO
# # # # #
# # # #
# ]
244 : : #undef X
245 : :
246 : : static void
247 : 0 : mlx5dr_definer_ones_set(struct mlx5dr_definer_fc *fc,
248 : : __rte_unused const void *item_spec,
249 : : __rte_unused uint8_t *tag)
250 : : {
251 [ # # # # : 0 : DR_SET(tag, -1, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
252 : 0 : }
253 : :
254 : : static void
255 : 0 : mlx5dr_definer_eth_first_vlan_q_set(struct mlx5dr_definer_fc *fc,
256 : : const void *item_spec,
257 : : uint8_t *tag)
258 : : {
259 : : const struct rte_flow_item_eth *v = item_spec;
260 : : uint8_t vlan_type;
261 : :
262 : 0 : vlan_type = v->has_vlan ? STE_CVLAN : STE_NO_VLAN;
263 : :
264 [ # # # # : 0 : DR_SET(tag, vlan_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
265 : 0 : }
266 : :
267 : : static void
268 : 0 : mlx5dr_definer_first_vlan_q_set(struct mlx5dr_definer_fc *fc,
269 : : const void *item_spec,
270 : : uint8_t *tag)
271 : : {
272 : : const struct rte_flow_item_vlan *v = item_spec;
273 : : uint8_t vlan_type;
274 : :
275 [ # # ]: 0 : vlan_type = v->has_more_vlan ? STE_SVLAN : STE_CVLAN;
276 : :
277 [ # # # # : 0 : DR_SET(tag, vlan_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
278 : 0 : }
279 : :
280 : : static void
281 : 0 : mlx5dr_definer_conntrack_mask(struct mlx5dr_definer_fc *fc,
282 : : const void *item_spec,
283 : : uint8_t *tag)
284 : : {
285 : : const struct rte_flow_item_conntrack *m = item_spec;
286 : : uint32_t reg_mask = 0;
287 : :
288 [ # # ]: 0 : if (m->flags & (RTE_FLOW_CONNTRACK_PKT_STATE_VALID |
289 : : RTE_FLOW_CONNTRACK_PKT_STATE_INVALID |
290 : : RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED))
291 : : reg_mask |= (MLX5_CT_SYNDROME_VALID | MLX5_CT_SYNDROME_INVALID |
292 : : MLX5_CT_SYNDROME_TRAP);
293 : :
294 [ # # ]: 0 : if (m->flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
295 : 0 : reg_mask |= MLX5_CT_SYNDROME_STATE_CHANGE;
296 : :
297 [ # # ]: 0 : if (m->flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
298 : 0 : reg_mask |= MLX5_CT_SYNDROME_BAD_PACKET;
299 : :
300 [ # # # # : 0 : DR_SET(tag, reg_mask, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
301 : 0 : }
302 : :
303 : : static void
304 : 0 : mlx5dr_definer_conntrack_tag(struct mlx5dr_definer_fc *fc,
305 : : const void *item_spec,
306 : : uint8_t *tag)
307 : : {
308 : : const struct rte_flow_item_conntrack *v = item_spec;
309 : : uint32_t reg_value = 0;
310 : :
311 : : /* The conflict should be checked in the validation. */
312 : 0 : if (v->flags & RTE_FLOW_CONNTRACK_PKT_STATE_VALID)
313 : : reg_value |= MLX5_CT_SYNDROME_VALID;
314 : :
315 [ # # ]: 0 : if (v->flags & RTE_FLOW_CONNTRACK_PKT_STATE_CHANGED)
316 : : reg_value |= MLX5_CT_SYNDROME_STATE_CHANGE;
317 : :
318 [ # # ]: 0 : if (v->flags & RTE_FLOW_CONNTRACK_PKT_STATE_INVALID)
319 : 0 : reg_value |= MLX5_CT_SYNDROME_INVALID;
320 : :
321 [ # # ]: 0 : if (v->flags & RTE_FLOW_CONNTRACK_PKT_STATE_DISABLED)
322 : 0 : reg_value |= MLX5_CT_SYNDROME_TRAP;
323 : :
324 [ # # ]: 0 : if (v->flags & RTE_FLOW_CONNTRACK_PKT_STATE_BAD)
325 : 0 : reg_value |= MLX5_CT_SYNDROME_BAD_PACKET;
326 : :
327 [ # # # # : 0 : DR_SET(tag, reg_value, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
328 : 0 : }
329 : :
330 : : static void
331 : 0 : mlx5dr_definer_ptype_l2_set(struct mlx5dr_definer_fc *fc,
332 : : const void *item_spec,
333 : : uint8_t *tag)
334 : : {
335 : 0 : bool inner = (fc->fname == MLX5DR_DEFINER_FNAME_PTYPE_L2_I);
336 : : const struct rte_flow_item_ptype *v = item_spec;
337 : 0 : uint32_t packet_type = v->packet_type &
338 [ # # ]: 0 : (inner ? RTE_PTYPE_INNER_L2_MASK : RTE_PTYPE_L2_MASK);
339 : : uint8_t l2_type = STE_NO_VLAN;
340 : :
341 [ # # # # ]: 0 : if (packet_type == (inner ? RTE_PTYPE_INNER_L2_ETHER : RTE_PTYPE_L2_ETHER))
342 : : l2_type = STE_NO_VLAN;
343 [ # # # # ]: 0 : else if (packet_type == (inner ? RTE_PTYPE_INNER_L2_ETHER_VLAN : RTE_PTYPE_L2_ETHER_VLAN))
344 : : l2_type = STE_CVLAN;
345 [ # # # # ]: 0 : else if (packet_type == (inner ? RTE_PTYPE_INNER_L2_ETHER_QINQ : RTE_PTYPE_L2_ETHER_QINQ))
346 : : l2_type = STE_SVLAN;
347 : :
348 [ # # # # : 0 : DR_SET(tag, l2_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
349 : 0 : }
350 : :
351 : : static void
352 : 0 : mlx5dr_definer_ptype_l3_set(struct mlx5dr_definer_fc *fc,
353 : : const void *item_spec,
354 : : uint8_t *tag)
355 : : {
356 : 0 : bool inner = (fc->fname == MLX5DR_DEFINER_FNAME_PTYPE_L3_I);
357 : : const struct rte_flow_item_ptype *v = item_spec;
358 : 0 : uint32_t packet_type = v->packet_type &
359 [ # # ]: 0 : (inner ? RTE_PTYPE_INNER_L3_MASK : RTE_PTYPE_L3_MASK);
360 : : uint8_t l3_type = STE_NO_L3;
361 : :
362 [ # # # # ]: 0 : if (packet_type == (inner ? RTE_PTYPE_INNER_L3_IPV4 : RTE_PTYPE_L3_IPV4))
363 : : l3_type = STE_IPV4;
364 [ # # # # ]: 0 : else if (packet_type == (inner ? RTE_PTYPE_INNER_L3_IPV6 : RTE_PTYPE_L3_IPV6))
365 : : l3_type = STE_IPV6;
366 : :
367 [ # # # # : 0 : DR_SET(tag, l3_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
368 : 0 : }
369 : :
370 : : static void
371 : 0 : mlx5dr_definer_ptype_l4_set(struct mlx5dr_definer_fc *fc,
372 : : const void *item_spec,
373 : : uint8_t *tag)
374 : : {
375 : 0 : bool inner = (fc->fname == MLX5DR_DEFINER_FNAME_PTYPE_L4_I);
376 : : const struct rte_flow_item_ptype *v = item_spec;
377 : 0 : uint32_t packet_type = v->packet_type &
378 [ # # ]: 0 : (inner ? RTE_PTYPE_INNER_L4_MASK : RTE_PTYPE_L4_MASK);
379 : : uint8_t l4_type = STE_NO_L4;
380 : :
381 [ # # # # ]: 0 : if (packet_type == (inner ? RTE_PTYPE_INNER_L4_TCP : RTE_PTYPE_L4_TCP))
382 : : l4_type = STE_TCP;
383 [ # # # # ]: 0 : else if (packet_type == (inner ? RTE_PTYPE_INNER_L4_UDP : RTE_PTYPE_L4_UDP))
384 : : l4_type = STE_UDP;
385 [ # # # # ]: 0 : else if (packet_type == (inner ? RTE_PTYPE_INNER_L4_ICMP : RTE_PTYPE_L4_ICMP))
386 : : l4_type = STE_ICMP;
387 : :
388 [ # # # # : 0 : DR_SET(tag, l4_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
389 : 0 : }
390 : :
391 : : static void
392 : 0 : mlx5dr_definer_ptype_tunnel_set(struct mlx5dr_definer_fc *fc,
393 : : const void *item_spec,
394 : : uint8_t *tag)
395 : : {
396 : : const struct rte_flow_item_ptype *v = item_spec;
397 : 0 : uint32_t packet_type = v->packet_type & RTE_PTYPE_TUNNEL_MASK;
398 : : uint8_t tun_type = STE_NO_TUN;
399 : :
400 [ # # ]: 0 : if (packet_type == RTE_PTYPE_TUNNEL_ESP)
401 : : tun_type = STE_ESP;
402 : :
403 [ # # # # : 0 : DR_SET(tag, tun_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
404 : 0 : }
405 : :
406 : : static void
407 : 0 : mlx5dr_definer_ptype_frag_set(struct mlx5dr_definer_fc *fc,
408 : : const void *item_spec,
409 : : uint8_t *tag)
410 : : {
411 : 0 : bool inner = (fc->fname == MLX5DR_DEFINER_FNAME_PTYPE_FRAG_I);
412 : : const struct rte_flow_item_ptype *v = item_spec;
413 : 0 : uint32_t packet_type = v->packet_type &
414 [ # # ]: 0 : (inner ? RTE_PTYPE_INNER_L4_FRAG : RTE_PTYPE_L4_FRAG);
415 : :
416 [ # # # # : 0 : DR_SET(tag, !!packet_type, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
417 : 0 : }
418 : :
419 : : static void
420 : 0 : mlx5dr_definer_compare_base_value_set(const void *item_spec,
421 : : uint8_t *tag)
422 : : {
423 : : uint32_t *ctrl = &(((uint32_t *)tag)[MLX5DR_DEFINER_COMPARE_STE_ARGUMENT_1]);
424 : : uint32_t *base = &(((uint32_t *)tag)[MLX5DR_DEFINER_COMPARE_STE_BASE_0]);
425 : : const struct rte_flow_item_compare *v = item_spec;
426 : : const struct rte_flow_field_data *a = &v->a;
427 : : const struct rte_flow_field_data *b = &v->b;
428 : : const uint32_t *value;
429 : :
430 : : value = (const uint32_t *)&b->value[0];
431 : :
432 [ # # # # ]: 0 : switch (a->field) {
433 : 0 : case RTE_FLOW_FIELD_RANDOM:
434 : 0 : *base = htobe32(*value << 16);
435 : 0 : break;
436 : 0 : case RTE_FLOW_FIELD_TAG:
437 : : case RTE_FLOW_FIELD_META:
438 : 0 : *base = htobe32(*value);
439 : 0 : break;
440 : 0 : case RTE_FLOW_FIELD_ESP_SEQ_NUM:
441 : 0 : *base = *value;
442 : 0 : break;
443 : : default:
444 : : break;
445 : : }
446 : :
447 [ # # ]: 0 : MLX5_SET(ste_match_4dw_range_ctrl_dw, ctrl, base0, 1);
448 : 0 : }
449 : :
450 : : static void
451 [ # # ]: 0 : mlx5dr_definer_compare_op_translate(enum rte_flow_item_compare_op op,
452 : : uint8_t *tag)
453 : : {
454 : : uint32_t *ctrl = &(((uint32_t *)tag)[MLX5DR_DEFINER_COMPARE_STE_ARGUMENT_1]);
455 : : uint8_t operator = 0;
456 : : uint8_t inverse = 0;
457 : :
458 : : switch (op) {
459 : : case RTE_FLOW_ITEM_COMPARE_EQ:
460 : : operator = 2;
461 : : break;
462 : : case RTE_FLOW_ITEM_COMPARE_NE:
463 : : operator = 2;
464 : : inverse = 1;
465 : : break;
466 : : case RTE_FLOW_ITEM_COMPARE_LT:
467 : : inverse = 1;
468 : : break;
469 : : case RTE_FLOW_ITEM_COMPARE_LE:
470 : : operator = 1;
471 : : break;
472 : : case RTE_FLOW_ITEM_COMPARE_GT:
473 : : operator = 1;
474 : : inverse = 1;
475 : : break;
476 : : case RTE_FLOW_ITEM_COMPARE_GE:
477 : : break;
478 : 0 : default:
479 : 0 : DR_LOG(ERR, "Invalid operation type %d", op);
480 : 0 : assert(false);
481 : : }
482 : :
483 [ # # ]: 0 : MLX5_SET(ste_match_4dw_range_ctrl_dw, ctrl, inverse0, inverse);
484 [ # # ]: 0 : MLX5_SET(ste_match_4dw_range_ctrl_dw, ctrl, operator0, operator);
485 : 0 : }
486 : :
487 : : static void
488 : : mlx5dr_definer_compare_arg_set(const void *item_spec,
489 : : uint8_t *tag)
490 : : {
491 : : const struct rte_flow_item_compare *v = item_spec;
492 : 0 : enum rte_flow_item_compare_op op = v->operation;
493 : :
494 : 0 : mlx5dr_definer_compare_op_translate(op, tag);
495 : : }
496 : :
497 : : static void
498 : 0 : mlx5dr_definer_compare_set(struct mlx5dr_definer_fc *fc,
499 : : const void *item_spec,
500 : : uint8_t *tag)
501 : : {
502 [ # # ]: 0 : if (fc->compare_idx == MLX5DR_DEFINER_COMPARE_ARGUMENT_0) {
503 : : mlx5dr_definer_compare_arg_set(item_spec, tag);
504 [ # # ]: 0 : if (fc->compare_set_base)
505 : 0 : mlx5dr_definer_compare_base_value_set(item_spec, tag);
506 : : }
507 : 0 : }
508 : :
509 : : static void
510 : 0 : mlx5dr_definer_integrity_set(struct mlx5dr_definer_fc *fc,
511 : : const void *item_spec,
512 : : uint8_t *tag)
513 : : {
514 : 0 : bool inner = (fc->fname == MLX5DR_DEFINER_FNAME_INTEGRITY_I);
515 : : const struct rte_flow_item_integrity *v = item_spec;
516 [ # # ]: 0 : uint32_t ok1_bits = DR_GET_32(tag, fc->byte_off, fc->bit_off, fc->bit_mask);
517 : :
518 [ # # ]: 0 : if (v->l3_ok)
519 [ # # ]: 0 : ok1_bits |= inner ? BIT(MLX5DR_DEFINER_OKS1_SECOND_L3_OK) :
520 : : BIT(MLX5DR_DEFINER_OKS1_FIRST_L3_OK);
521 : :
522 [ # # ]: 0 : if (v->ipv4_csum_ok)
523 [ # # ]: 0 : ok1_bits |= inner ? BIT(MLX5DR_DEFINER_OKS1_SECOND_IPV4_CSUM_OK) :
524 : : BIT(MLX5DR_DEFINER_OKS1_FIRST_IPV4_CSUM_OK);
525 : :
526 [ # # ]: 0 : if (v->l4_ok)
527 [ # # ]: 0 : ok1_bits |= inner ? BIT(MLX5DR_DEFINER_OKS1_SECOND_L4_OK) |
528 : : BIT(MLX5DR_DEFINER_OKS1_SECOND_L4_CSUM_OK) :
529 : : BIT(MLX5DR_DEFINER_OKS1_FIRST_L4_OK) |
530 : : BIT(MLX5DR_DEFINER_OKS1_FIRST_L4_CSUM_OK);
531 : :
532 [ # # ]: 0 : if (v->l4_csum_ok)
533 [ # # ]: 0 : ok1_bits |= inner ? BIT(MLX5DR_DEFINER_OKS1_SECOND_L4_CSUM_OK) :
534 : : BIT(MLX5DR_DEFINER_OKS1_FIRST_L4_CSUM_OK);
535 : :
536 [ # # # # : 0 : DR_SET(tag, ok1_bits, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
537 : 0 : }
538 : :
539 : : static void
540 : 0 : mlx5dr_definer_ipv6_routing_ext_set(struct mlx5dr_definer_fc *fc,
541 : : const void *item,
542 : : uint8_t *tag)
543 : : {
544 : : const struct rte_flow_item_ipv6_routing_ext *v = item;
545 : : uint32_t val;
546 : :
547 : 0 : val = v->hdr.next_hdr << __mlx5_dw_bit_off(header_ipv6_routing_ext, next_hdr);
548 : 0 : val |= v->hdr.type << __mlx5_dw_bit_off(header_ipv6_routing_ext, type);
549 : 0 : val |= v->hdr.segments_left <<
550 : : __mlx5_dw_bit_off(header_ipv6_routing_ext, segments_left);
551 [ # # ]: 0 : DR_SET(tag, val, fc->byte_off, 0, fc->bit_mask);
552 : 0 : }
553 : :
554 : : static void
555 : 0 : mlx5dr_definer_flex_parser_set(struct mlx5dr_definer_fc *fc,
556 : : const void *item,
557 : : uint8_t *tag, bool is_inner)
558 : : {
559 : : const struct rte_flow_item_flex *flex = item;
560 : : uint32_t byte_off, val, idx;
561 : : int ret;
562 : :
563 : 0 : val = 0;
564 : : byte_off = MLX5_BYTE_OFF(definer_hl, flex_parser.flex_parser_0);
565 : 0 : idx = fc->fname - MLX5DR_DEFINER_FNAME_FLEX_PARSER_0;
566 : 0 : byte_off -= idx * sizeof(uint32_t);
567 : 0 : ret = mlx5_flex_get_parser_value_per_byte_off(flex, flex->handle, byte_off,
568 : : false, is_inner, &val);
569 [ # # # # ]: 0 : if (ret == -1 || !val)
570 : 0 : return;
571 : :
572 [ # # ]: 0 : DR_SET(tag, val, fc->byte_off, 0, fc->bit_mask);
573 : : }
574 : :
575 : : static void
576 : 0 : mlx5dr_definer_flex_parser_inner_set(struct mlx5dr_definer_fc *fc,
577 : : const void *item,
578 : : uint8_t *tag)
579 : : {
580 : 0 : mlx5dr_definer_flex_parser_set(fc, item, tag, true);
581 : 0 : }
582 : :
583 : : static void
584 : 0 : mlx5dr_definer_flex_parser_outer_set(struct mlx5dr_definer_fc *fc,
585 : : const void *item,
586 : : uint8_t *tag)
587 : : {
588 : 0 : mlx5dr_definer_flex_parser_set(fc, item, tag, false);
589 : 0 : }
590 : :
591 : : static void
592 : 0 : mlx5dr_definer_gre_key_set(struct mlx5dr_definer_fc *fc,
593 : : const void *item_spec,
594 : : uint8_t *tag)
595 : : {
596 : : const rte_be32_t *v = item_spec;
597 : :
598 : 0 : DR_SET_BE32(tag, *v, fc->byte_off, fc->bit_off, fc->bit_mask);
599 : 0 : }
600 : :
601 : : static void
602 : 0 : mlx5dr_definer_vxlan_vni_set(struct mlx5dr_definer_fc *fc,
603 : : const void *item_spec,
604 : : uint8_t *tag)
605 : : {
606 : : const struct rte_flow_item_vxlan *v = item_spec;
607 : :
608 : 0 : memcpy(tag + fc->byte_off, v->vni, sizeof(v->vni));
609 : 0 : }
610 : :
611 : : static void
612 : 0 : mlx5dr_definer_ipv6_tos_set(struct mlx5dr_definer_fc *fc,
613 : : const void *item_spec,
614 : : uint8_t *tag)
615 : : {
616 : : const struct rte_flow_item_ipv6 *v = item_spec;
617 [ # # ]: 0 : uint8_t tos = DR_GET(header_ipv6_vtc, &v->hdr.vtc_flow, tos);
618 : :
619 [ # # # # : 0 : DR_SET(tag, tos, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
620 : 0 : }
621 : :
622 : : static void
623 : 0 : mlx5dr_definer_icmp_dw1_set(struct mlx5dr_definer_fc *fc,
624 : : const void *item_spec,
625 : : uint8_t *tag)
626 : : {
627 : : const struct rte_flow_item_icmp *v = item_spec;
628 : : rte_be32_t icmp_dw1;
629 : :
630 : 0 : icmp_dw1 = (v->hdr.icmp_type << __mlx5_dw_bit_off(header_icmp, type)) |
631 : 0 : (v->hdr.icmp_code << __mlx5_dw_bit_off(header_icmp, code)) |
632 [ # # ]: 0 : (rte_be_to_cpu_16(v->hdr.icmp_cksum) << __mlx5_dw_bit_off(header_icmp, cksum));
633 : :
634 [ # # # # : 0 : DR_SET(tag, icmp_dw1, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
635 : 0 : }
636 : :
637 : : static void
638 : 0 : mlx5dr_definer_icmp_dw2_set(struct mlx5dr_definer_fc *fc,
639 : : const void *item_spec,
640 : : uint8_t *tag)
641 : : {
642 : : const struct rte_flow_item_icmp *v = item_spec;
643 : : rte_be32_t icmp_dw2;
644 : :
645 [ # # ]: 0 : icmp_dw2 = (rte_be_to_cpu_16(v->hdr.icmp_ident) << __mlx5_dw_bit_off(header_icmp, ident)) |
646 [ # # ]: 0 : (rte_be_to_cpu_16(v->hdr.icmp_seq_nb) << __mlx5_dw_bit_off(header_icmp, seq_nb));
647 : :
648 [ # # # # : 0 : DR_SET(tag, icmp_dw2, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
649 : 0 : }
650 : :
651 : : static void
652 : 0 : mlx5dr_definer_icmp6_dw1_set(struct mlx5dr_definer_fc *fc,
653 : : const void *item_spec,
654 : : uint8_t *tag)
655 : : {
656 : : const struct rte_flow_item_icmp6 *v = item_spec;
657 : : rte_be32_t icmp_dw1;
658 : :
659 : 0 : icmp_dw1 = (v->type << __mlx5_dw_bit_off(header_icmp, type)) |
660 : 0 : (v->code << __mlx5_dw_bit_off(header_icmp, code)) |
661 [ # # ]: 0 : (rte_be_to_cpu_16(v->checksum) << __mlx5_dw_bit_off(header_icmp, cksum));
662 : :
663 [ # # # # : 0 : DR_SET(tag, icmp_dw1, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
664 : 0 : }
665 : :
666 : : static void
667 : 0 : mlx5dr_definer_icmp6_echo_dw1_mask_set(struct mlx5dr_definer_fc *fc,
668 : : __rte_unused const void *item_spec,
669 : : uint8_t *tag)
670 : : {
671 : 0 : const struct rte_flow_item_icmp6 spec = {0xFF, 0xFF, 0x0};
672 : 0 : mlx5dr_definer_icmp6_dw1_set(fc, &spec, tag);
673 : 0 : }
674 : :
675 : : static void
676 : 0 : mlx5dr_definer_icmp6_echo_request_dw1_set(struct mlx5dr_definer_fc *fc,
677 : : __rte_unused const void *item_spec,
678 : : uint8_t *tag)
679 : : {
680 : 0 : const struct rte_flow_item_icmp6 spec = {RTE_ICMP6_ECHO_REQUEST, 0, 0};
681 : 0 : mlx5dr_definer_icmp6_dw1_set(fc, &spec, tag);
682 : 0 : }
683 : :
684 : : static void
685 : 0 : mlx5dr_definer_icmp6_echo_reply_dw1_set(struct mlx5dr_definer_fc *fc,
686 : : __rte_unused const void *item_spec,
687 : : uint8_t *tag)
688 : : {
689 : 0 : const struct rte_flow_item_icmp6 spec = {RTE_ICMP6_ECHO_REPLY, 0, 0};
690 : 0 : mlx5dr_definer_icmp6_dw1_set(fc, &spec, tag);
691 : 0 : }
692 : :
693 : : static void
694 : 0 : mlx5dr_definer_icmp6_echo_dw2_set(struct mlx5dr_definer_fc *fc,
695 : : const void *item_spec,
696 : : uint8_t *tag)
697 : : {
698 : : const struct rte_flow_item_icmp6_echo *v = item_spec;
699 : : rte_be32_t dw2;
700 : :
701 [ # # ]: 0 : dw2 = (rte_be_to_cpu_16(v->hdr.identifier) << __mlx5_dw_bit_off(header_icmp, ident)) |
702 [ # # ]: 0 : (rte_be_to_cpu_16(v->hdr.sequence) << __mlx5_dw_bit_off(header_icmp, seq_nb));
703 : :
704 [ # # # # : 0 : DR_SET(tag, dw2, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
705 : 0 : }
706 : :
707 : : static void
708 : 0 : mlx5dr_definer_ipv6_flow_label_set(struct mlx5dr_definer_fc *fc,
709 : : const void *item_spec,
710 : : uint8_t *tag)
711 : : {
712 : : const struct rte_flow_item_ipv6 *v = item_spec;
713 [ # # ]: 0 : uint32_t flow_label = DR_GET(header_ipv6_vtc, &v->hdr.vtc_flow, flow_label);
714 : :
715 [ # # # # : 0 : DR_SET(tag, flow_label, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
716 : 0 : }
717 : :
718 : : static void
719 : 0 : mlx5dr_definer_vport_set(struct mlx5dr_definer_fc *fc,
720 : : const void *item_spec,
721 : : uint8_t *tag)
722 : : {
723 : : const struct rte_flow_item_ethdev *v = item_spec;
724 : : const struct flow_hw_port_info *port_info;
725 : : uint32_t regc_value;
726 : :
727 [ # # ]: 0 : port_info = flow_hw_conv_port_id(v->port_id);
728 [ # # ]: 0 : if (unlikely(!port_info))
729 : : regc_value = BAD_PORT;
730 : : else
731 : 0 : regc_value = port_info->regc_value >> fc->bit_off;
732 : :
733 : : /* Bit offset is set to 0 to since regc value is 32bit */
734 [ # # # # : 0 : DR_SET(tag, regc_value, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
735 : 0 : }
736 : :
737 : : static struct mlx5dr_definer_fc *
738 : 0 : mlx5dr_definer_get_mpls_fc(struct mlx5dr_definer_conv_data *cd, bool inner)
739 : : {
740 : 0 : uint8_t mpls_idx = cd->mpls_idx;
741 : : struct mlx5dr_definer_fc *fc;
742 : :
743 [ # # # # : 0 : switch (mpls_idx) {
# # ]
744 : 0 : case 0:
745 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(MPLS0, inner)];
746 : 0 : DR_CALC_SET_HDR(fc, mpls_inner, mpls0_label);
747 : 0 : break;
748 : 0 : case 1:
749 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(MPLS1, inner)];
750 : 0 : DR_CALC_SET_HDR(fc, mpls_inner, mpls1_label);
751 : 0 : break;
752 : 0 : case 2:
753 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(MPLS2, inner)];
754 : 0 : DR_CALC_SET_HDR(fc, mpls_inner, mpls2_label);
755 : 0 : break;
756 : 0 : case 3:
757 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(MPLS3, inner)];
758 : 0 : DR_CALC_SET_HDR(fc, mpls_inner, mpls3_label);
759 : 0 : break;
760 : 0 : case 4:
761 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(MPLS4, inner)];
762 : 0 : DR_CALC_SET_HDR(fc, mpls_inner, mpls4_label);
763 : 0 : break;
764 : 0 : default:
765 : 0 : rte_errno = ENOTSUP;
766 : 0 : DR_LOG(ERR, "MPLS index %d is not supported", mpls_idx);
767 : 0 : return NULL;
768 : : }
769 : :
770 : : return fc;
771 : : }
772 : :
773 : : static struct mlx5dr_definer_fc *
774 : 0 : mlx5dr_definer_get_mpls_oks_fc(struct mlx5dr_definer_conv_data *cd, bool inner)
775 : : {
776 : 0 : uint8_t mpls_idx = cd->mpls_idx;
777 : : struct mlx5dr_definer_fc *fc;
778 : :
779 [ # # # # : 0 : switch (mpls_idx) {
# # ]
780 : 0 : case 0:
781 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(OKS2_MPLS0, inner)];
782 : 0 : DR_CALC_SET_HDR(fc, oks2, second_mpls0_qualifier);
783 : 0 : break;
784 : 0 : case 1:
785 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(OKS2_MPLS1, inner)];
786 : 0 : DR_CALC_SET_HDR(fc, oks2, second_mpls1_qualifier);
787 : 0 : break;
788 : 0 : case 2:
789 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(OKS2_MPLS2, inner)];
790 : 0 : DR_CALC_SET_HDR(fc, oks2, second_mpls2_qualifier);
791 : 0 : break;
792 : 0 : case 3:
793 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(OKS2_MPLS3, inner)];
794 : 0 : DR_CALC_SET_HDR(fc, oks2, second_mpls3_qualifier);
795 : 0 : break;
796 : 0 : case 4:
797 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(OKS2_MPLS4, inner)];
798 : 0 : DR_CALC_SET_HDR(fc, oks2, second_mpls4_qualifier);
799 : 0 : break;
800 : 0 : default:
801 : 0 : rte_errno = ENOTSUP;
802 : 0 : DR_LOG(ERR, "MPLS index %d is not supported", mpls_idx);
803 : 0 : return NULL;
804 : : }
805 : :
806 : : return fc;
807 : : }
808 : :
809 : : static void
810 : 0 : mlx5dr_definer_mpls_label_set(struct mlx5dr_definer_fc *fc,
811 : : const void *item_spec,
812 : : uint8_t *tag)
813 : : {
814 : : const struct rte_flow_item_mpls *v = item_spec;
815 : :
816 : 0 : memcpy(tag + fc->byte_off, v->label_tc_s, sizeof(v->label_tc_s));
817 : 0 : memcpy(tag + fc->byte_off + sizeof(v->label_tc_s), &v->ttl, sizeof(v->ttl));
818 : 0 : }
819 : :
820 : : static void
821 : 0 : mlx5dr_definer_geneve_vni_set(struct mlx5dr_definer_fc *fc,
822 : : const void *item_spec,
823 : : uint8_t *tag)
824 : : {
825 : : const struct rte_flow_item_geneve *v = item_spec;
826 : :
827 : 0 : memcpy(tag + fc->byte_off, v->vni, sizeof(v->vni));
828 : 0 : }
829 : :
830 : : static void
831 : 0 : mlx5dr_definer_geneve_opt_ctrl_set(struct mlx5dr_definer_fc *fc,
832 : : const void *item_spec,
833 : : uint8_t *tag)
834 : : {
835 : : const struct rte_flow_item_geneve_opt *v = item_spec;
836 : : uint32_t dw0 = 0;
837 : :
838 : 0 : dw0 |= v->option_type << __mlx5_dw_bit_off(header_geneve_opt, type);
839 [ # # ]: 0 : dw0 |= rte_cpu_to_be_16(v->option_class) << __mlx5_dw_bit_off(header_geneve_opt, class);
840 [ # # # # : 0 : DR_SET(tag, dw0, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
841 : 0 : }
842 : :
843 : : static void
844 : 0 : mlx5dr_definer_geneve_opt_data_set(struct mlx5dr_definer_fc *fc,
845 : : const void *item_spec,
846 : : uint8_t *tag)
847 : : {
848 : : const struct rte_flow_item_geneve_opt *v = item_spec;
849 : :
850 : 0 : DR_SET_BE32(tag, v->data[fc->extra_data], fc->byte_off, fc->bit_off, fc->bit_mask);
851 : 0 : }
852 : :
853 : : static void
854 : 0 : mlx5dr_definer_ib_l4_qp_set(struct mlx5dr_definer_fc *fc,
855 : : const void *item_spec,
856 : : uint8_t *tag)
857 : : {
858 : : const struct rte_flow_item_ib_bth *v = item_spec;
859 : :
860 : 0 : memcpy(tag + fc->byte_off, &v->hdr.dst_qp, sizeof(v->hdr.dst_qp));
861 : 0 : }
862 : :
863 : : static void
864 : 0 : mlx5dr_definer_vxlan_gpe_vni_set(struct mlx5dr_definer_fc *fc,
865 : : const void *item_spec,
866 : : uint8_t *tag)
867 : : {
868 : : const struct rte_flow_item_vxlan_gpe *v = item_spec;
869 : :
870 : 0 : memcpy(tag + fc->byte_off, v->vni, sizeof(v->vni));
871 : 0 : }
872 : :
873 : : static void
874 : 0 : mlx5dr_definer_vxlan_gpe_rsvd0_set(struct mlx5dr_definer_fc *fc,
875 : : const void *item_spec,
876 : : uint8_t *tag)
877 : : {
878 : : const struct rte_flow_item_vxlan_gpe *v = item_spec;
879 : : uint16_t rsvd0;
880 : :
881 : 0 : rsvd0 = (v->rsvd0[0] << 8 | v->rsvd0[1]);
882 [ # # # # : 0 : DR_SET(tag, rsvd0, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
883 : 0 : }
884 : :
885 : : static int
886 : 0 : mlx5dr_definer_conv_item_eth(struct mlx5dr_definer_conv_data *cd,
887 : : struct rte_flow_item *item,
888 : : int item_idx)
889 : : {
890 : 0 : const struct rte_flow_item_eth *m = item->mask;
891 : 0 : uint8_t empty_mac[RTE_ETHER_ADDR_LEN] = {0};
892 : : struct mlx5dr_definer_fc *fc;
893 : 0 : bool inner = cd->tunnel;
894 : :
895 [ # # ]: 0 : if (!m)
896 : : return 0;
897 : :
898 [ # # ]: 0 : if (m->reserved) {
899 : 0 : rte_errno = ENOTSUP;
900 : 0 : return rte_errno;
901 : : }
902 : :
903 [ # # ]: 0 : if (m->hdr.ether_type) {
904 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(ETH_TYPE, inner)];
905 : 0 : fc->item_idx = item_idx;
906 : 0 : fc->tag_set = &mlx5dr_definer_eth_type_set;
907 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_ethertype, inner);
908 : : }
909 : :
910 : : /* Check SMAC 47_16 */
911 [ # # ]: 0 : if (memcmp(m->hdr.src_addr.addr_bytes, empty_mac, 4)) {
912 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(ETH_SMAC_48_16, inner)];
913 : 0 : fc->item_idx = item_idx;
914 : 0 : fc->tag_set = &mlx5dr_definer_eth_smac_47_16_set;
915 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2_src, smac_47_16, inner);
916 : : }
917 : :
918 : : /* Check SMAC 15_0 */
919 [ # # ]: 0 : if (memcmp(m->hdr.src_addr.addr_bytes + 4, empty_mac + 4, 2)) {
920 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(ETH_SMAC_15_0, inner)];
921 : 0 : fc->item_idx = item_idx;
922 : 0 : fc->tag_set = &mlx5dr_definer_eth_smac_15_0_set;
923 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2_src, smac_15_0, inner);
924 : : }
925 : :
926 : : /* Check DMAC 47_16 */
927 [ # # ]: 0 : if (memcmp(m->hdr.dst_addr.addr_bytes, empty_mac, 4)) {
928 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(ETH_DMAC_48_16, inner)];
929 : 0 : fc->item_idx = item_idx;
930 : 0 : fc->tag_set = &mlx5dr_definer_eth_dmac_47_16_set;
931 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, dmac_47_16, inner);
932 : : }
933 : :
934 : : /* Check DMAC 15_0 */
935 [ # # ]: 0 : if (memcmp(m->hdr.dst_addr.addr_bytes + 4, empty_mac + 4, 2)) {
936 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(ETH_DMAC_15_0, inner)];
937 : 0 : fc->item_idx = item_idx;
938 : 0 : fc->tag_set = &mlx5dr_definer_eth_dmac_15_0_set;
939 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, dmac_15_0, inner);
940 : : }
941 : :
942 [ # # ]: 0 : if (m->has_vlan) {
943 : : /* Mark packet as tagged (CVLAN) */
944 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(VLAN_TYPE, inner)];
945 : 0 : fc->item_idx = item_idx;
946 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
947 : 0 : fc->tag_set = &mlx5dr_definer_eth_first_vlan_q_set;
948 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, first_vlan_qualifier, inner);
949 : : }
950 : :
951 : : return 0;
952 : : }
953 : :
954 : : static int
955 : 0 : mlx5dr_definer_conv_item_vlan(struct mlx5dr_definer_conv_data *cd,
956 : : struct rte_flow_item *item,
957 : : int item_idx)
958 : : {
959 : 0 : const struct rte_flow_item_vlan *m = item->mask;
960 : : struct mlx5dr_definer_fc *fc;
961 : 0 : bool inner = cd->tunnel;
962 : :
963 [ # # ]: 0 : if (!cd->relaxed) {
964 : : /* Mark packet as tagged (CVLAN) */
965 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(VLAN_TYPE, inner)];
966 : 0 : fc->item_idx = item_idx;
967 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
968 : 0 : fc->tag_set = &mlx5dr_definer_cvlan_set;
969 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, first_vlan_qualifier, inner);
970 : : }
971 : :
972 [ # # ]: 0 : if (!m)
973 : : return 0;
974 : :
975 [ # # ]: 0 : if (m->reserved) {
976 : 0 : rte_errno = ENOTSUP;
977 : 0 : return rte_errno;
978 : : }
979 : :
980 [ # # ]: 0 : if (m->has_more_vlan) {
981 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(VLAN_TYPE, inner)];
982 : 0 : fc->item_idx = item_idx;
983 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
984 : 0 : fc->tag_set = &mlx5dr_definer_first_vlan_q_set;
985 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, first_vlan_qualifier, inner);
986 : : }
987 : :
988 [ # # ]: 0 : if (m->hdr.vlan_tci) {
989 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(VLAN_TCI, inner)];
990 : 0 : fc->item_idx = item_idx;
991 : 0 : fc->tag_set = &mlx5dr_definer_tci_set;
992 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, tci, inner);
993 : : }
994 : :
995 [ # # ]: 0 : if (m->hdr.eth_proto) {
996 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(ETH_TYPE, inner)];
997 : 0 : fc->item_idx = item_idx;
998 : 0 : fc->tag_set = &mlx5dr_definer_inner_type_set;
999 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_ethertype, inner);
1000 : : }
1001 : :
1002 : : return 0;
1003 : : }
1004 : :
1005 : : static int
1006 : 0 : mlx5dr_definer_conv_item_ipv4(struct mlx5dr_definer_conv_data *cd,
1007 : : struct rte_flow_item *item,
1008 : : int item_idx)
1009 : : {
1010 : 0 : const struct rte_ipv4_hdr *m = item->mask;
1011 : 0 : const struct rte_ipv4_hdr *l = item->last;
1012 : : struct mlx5dr_definer_fc *fc;
1013 : 0 : bool inner = cd->tunnel;
1014 : :
1015 [ # # ]: 0 : if (!cd->relaxed) {
1016 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_VERSION, inner)];
1017 : 0 : fc->item_idx = item_idx;
1018 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_version_set;
1019 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1020 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_type, inner);
1021 : :
1022 : : /* Overwrite - Unset ethertype if present */
1023 [ # # ]: 0 : memset(&cd->fc[DR_CALC_FNAME(ETH_TYPE, inner)], 0, sizeof(*fc));
1024 : : }
1025 : :
1026 [ # # ]: 0 : if (!m)
1027 : : return 0;
1028 : :
1029 [ # # # # : 0 : if (m->packet_id || m->hdr_checksum ||
# # ]
1030 [ # # # # ]: 0 : (l && (l->next_proto_id || l->type_of_service))) {
1031 : 0 : rte_errno = ENOTSUP;
1032 : 0 : return rte_errno;
1033 : : }
1034 : :
1035 [ # # ]: 0 : if (m->version) {
1036 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_VERSION, inner)];
1037 : 0 : fc->item_idx = item_idx;
1038 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_version_set;
1039 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1040 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_type, inner);
1041 : : }
1042 : :
1043 [ # # ]: 0 : if (m->fragment_offset) {
1044 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_FRAG, inner)];
1045 : 0 : fc->item_idx = item_idx;
1046 [ # # # # ]: 0 : if (rte_be_to_cpu_16(m->fragment_offset) == 0x3fff) {
1047 : 0 : fc->tag_set = &mlx5dr_definer_ip_fragmented_set;
1048 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, ip_fragmented, inner);
1049 : : } else {
1050 [ # # # # ]: 0 : fc->is_range = l && l->fragment_offset;
1051 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_frag_set;
1052 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, ipv4_frag, inner);
1053 : : }
1054 : : }
1055 : :
1056 [ # # ]: 0 : if (m->next_proto_id) {
1057 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
1058 : 0 : fc->item_idx = item_idx;
1059 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_next_proto_set;
1060 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, protocol_next_header, inner);
1061 : : }
1062 : :
1063 [ # # ]: 0 : if (m->total_length) {
1064 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_LEN, inner)];
1065 : 0 : fc->item_idx = item_idx;
1066 [ # # # # ]: 0 : fc->is_range = l && l->total_length;
1067 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_len_set;
1068 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, ipv4_total_length, inner);
1069 : : }
1070 : :
1071 [ # # ]: 0 : if (m->dst_addr) {
1072 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV4_DST, inner)];
1073 : 0 : fc->item_idx = item_idx;
1074 [ # # # # ]: 0 : fc->is_range = l && l->dst_addr;
1075 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_dst_addr_set;
1076 [ # # ]: 0 : DR_CALC_SET(fc, ipv4_src_dest, destination_address, inner);
1077 : : }
1078 : :
1079 [ # # ]: 0 : if (m->src_addr) {
1080 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV4_SRC, inner)];
1081 : 0 : fc->item_idx = item_idx;
1082 [ # # # # ]: 0 : fc->is_range = l && l->src_addr;
1083 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_src_addr_set;
1084 [ # # ]: 0 : DR_CALC_SET(fc, ipv4_src_dest, source_address, inner);
1085 : : }
1086 : :
1087 [ # # ]: 0 : if (m->ihl) {
1088 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV4_IHL, inner)];
1089 : 0 : fc->item_idx = item_idx;
1090 [ # # # # ]: 0 : fc->is_range = l && l->ihl;
1091 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_ihl_set;
1092 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, ihl, inner);
1093 : : }
1094 : :
1095 [ # # ]: 0 : if (m->time_to_live) {
1096 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_TTL, inner)];
1097 : 0 : fc->item_idx = item_idx;
1098 [ # # # # ]: 0 : fc->is_range = l && l->time_to_live;
1099 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_time_to_live_set;
1100 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, time_to_live_hop_limit, inner);
1101 : : }
1102 : :
1103 [ # # ]: 0 : if (m->type_of_service) {
1104 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_TOS, inner)];
1105 : 0 : fc->item_idx = item_idx;
1106 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_tos_set;
1107 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, tos, inner);
1108 : : }
1109 : :
1110 : : return 0;
1111 : : }
1112 : :
1113 : : static int
1114 : 0 : mlx5dr_definer_conv_item_ipv6(struct mlx5dr_definer_conv_data *cd,
1115 : : struct rte_flow_item *item,
1116 : : int item_idx)
1117 : : {
1118 : 0 : const struct rte_flow_item_ipv6 *m = item->mask;
1119 : 0 : const struct rte_flow_item_ipv6 *l = item->last;
1120 : : struct mlx5dr_definer_fc *fc;
1121 : 0 : bool inner = cd->tunnel;
1122 : :
1123 [ # # ]: 0 : if (!cd->relaxed) {
1124 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_VERSION, inner)];
1125 : 0 : fc->item_idx = item_idx;
1126 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_version_set;
1127 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1128 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_type, inner);
1129 : :
1130 : : /* Overwrite - Unset ethertype if present */
1131 [ # # ]: 0 : memset(&cd->fc[DR_CALC_FNAME(ETH_TYPE, inner)], 0, sizeof(*fc));
1132 : : }
1133 : :
1134 [ # # ]: 0 : if (!m)
1135 : : return 0;
1136 : :
1137 : 0 : if (m->has_hop_ext || m->has_route_ext || m->has_auth_ext ||
1138 : : m->has_esp_ext || m->has_dest_ext || m->has_mobil_ext ||
1139 [ # # # # ]: 0 : m->has_hip_ext || m->has_shim6_ext ||
1140 [ # # # # : 0 : (l && (l->has_frag_ext || l->hdr.vtc_flow || l->hdr.proto ||
# # # # ]
1141 [ # # ]: 0 : !is_mem_zero(l->hdr.src_addr, 16) ||
1142 : 0 : !is_mem_zero(l->hdr.dst_addr, 16)))) {
1143 : 0 : rte_errno = ENOTSUP;
1144 : 0 : return rte_errno;
1145 : : }
1146 : :
1147 [ # # ]: 0 : if (m->has_frag_ext) {
1148 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_FRAG, inner)];
1149 : 0 : fc->item_idx = item_idx;
1150 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_frag_set;
1151 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, ip_fragmented, inner);
1152 : : }
1153 : :
1154 [ # # # # ]: 0 : if (DR_GET(header_ipv6_vtc, &m->hdr.vtc_flow, version)) {
1155 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_VERSION, inner)];
1156 : 0 : fc->item_idx = item_idx;
1157 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_version_set;
1158 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1159 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_type, inner);
1160 : : }
1161 : :
1162 [ # # # # ]: 0 : if (DR_GET(header_ipv6_vtc, &m->hdr.vtc_flow, tos)) {
1163 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_TOS, inner)];
1164 : 0 : fc->item_idx = item_idx;
1165 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_tos_set;
1166 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, tos, inner);
1167 : : }
1168 : :
1169 [ # # # # ]: 0 : if (DR_GET(header_ipv6_vtc, &m->hdr.vtc_flow, flow_label)) {
1170 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_FLOW_LABEL, inner)];
1171 : 0 : fc->item_idx = item_idx;
1172 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_flow_label_set;
1173 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, flow_label, inner);
1174 : : }
1175 : :
1176 [ # # ]: 0 : if (m->hdr.payload_len) {
1177 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_LEN, inner)];
1178 : 0 : fc->item_idx = item_idx;
1179 [ # # # # ]: 0 : fc->is_range = l && l->hdr.payload_len;
1180 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_payload_len_set;
1181 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, ipv6_payload_length, inner);
1182 : : }
1183 : :
1184 [ # # ]: 0 : if (m->hdr.proto) {
1185 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
1186 : 0 : fc->item_idx = item_idx;
1187 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_proto_set;
1188 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, protocol_next_header, inner);
1189 : : }
1190 : :
1191 [ # # ]: 0 : if (m->hdr.hop_limits) {
1192 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_TTL, inner)];
1193 : 0 : fc->item_idx = item_idx;
1194 [ # # # # ]: 0 : fc->is_range = l && l->hdr.hop_limits;
1195 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_hop_limits_set;
1196 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, time_to_live_hop_limit, inner);
1197 : : }
1198 : :
1199 [ # # ]: 0 : if (!is_mem_zero(m->hdr.src_addr, 4)) {
1200 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_127_96, inner)];
1201 : 0 : fc->item_idx = item_idx;
1202 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_src_addr_127_96_set;
1203 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_src, ipv6_address_127_96, inner);
1204 : : }
1205 : :
1206 [ # # ]: 0 : if (!is_mem_zero(m->hdr.src_addr + 4, 4)) {
1207 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_95_64, inner)];
1208 : 0 : fc->item_idx = item_idx;
1209 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_src_addr_95_64_set;
1210 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_src, ipv6_address_95_64, inner);
1211 : : }
1212 : :
1213 [ # # ]: 0 : if (!is_mem_zero(m->hdr.src_addr + 8, 4)) {
1214 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_63_32, inner)];
1215 : 0 : fc->item_idx = item_idx;
1216 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_src_addr_63_32_set;
1217 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_src, ipv6_address_63_32, inner);
1218 : : }
1219 : :
1220 [ # # ]: 0 : if (!is_mem_zero(m->hdr.src_addr + 12, 4)) {
1221 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_SRC_31_0, inner)];
1222 : 0 : fc->item_idx = item_idx;
1223 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_src_addr_31_0_set;
1224 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_src, ipv6_address_31_0, inner);
1225 : : }
1226 : :
1227 [ # # ]: 0 : if (!is_mem_zero(m->hdr.dst_addr, 4)) {
1228 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_127_96, inner)];
1229 : 0 : fc->item_idx = item_idx;
1230 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_127_96_set;
1231 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_dst, ipv6_address_127_96, inner);
1232 : : }
1233 : :
1234 [ # # ]: 0 : if (!is_mem_zero(m->hdr.dst_addr + 4, 4)) {
1235 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_95_64, inner)];
1236 : 0 : fc->item_idx = item_idx;
1237 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_95_64_set;
1238 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_dst, ipv6_address_95_64, inner);
1239 : : }
1240 : :
1241 [ # # ]: 0 : if (!is_mem_zero(m->hdr.dst_addr + 8, 4)) {
1242 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_63_32, inner)];
1243 : 0 : fc->item_idx = item_idx;
1244 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_63_32_set;
1245 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_dst, ipv6_address_63_32, inner);
1246 : : }
1247 : :
1248 [ # # ]: 0 : if (!is_mem_zero(m->hdr.dst_addr + 12, 4)) {
1249 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IPV6_DST_31_0, inner)];
1250 : 0 : fc->item_idx = item_idx;
1251 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_dst_addr_31_0_set;
1252 [ # # ]: 0 : DR_CALC_SET(fc, ipv6_dst, ipv6_address_31_0, inner);
1253 : : }
1254 : :
1255 : : return 0;
1256 : : }
1257 : :
1258 : : static int
1259 : 0 : mlx5dr_definer_conv_item_udp(struct mlx5dr_definer_conv_data *cd,
1260 : : struct rte_flow_item *item,
1261 : : int item_idx)
1262 : : {
1263 : 0 : const struct rte_flow_item_udp *m = item->mask;
1264 : 0 : const struct rte_flow_item_udp *l = item->last;
1265 : : struct mlx5dr_definer_fc *fc;
1266 : 0 : bool inner = cd->tunnel;
1267 : :
1268 : : /* Set match on L4 type UDP */
1269 [ # # ]: 0 : if (!cd->relaxed) {
1270 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
1271 [ # # ]: 0 : if (!fc->not_overwrite) {
1272 : 0 : fc->item_idx = item_idx;
1273 : 0 : fc->tag_set = &mlx5dr_definer_udp_protocol_set;
1274 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1275 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, inner);
1276 : : }
1277 : : }
1278 : :
1279 [ # # ]: 0 : if (!m)
1280 : : return 0;
1281 : :
1282 [ # # # # ]: 0 : if (m->hdr.dgram_cksum || m->hdr.dgram_len) {
1283 : 0 : rte_errno = ENOTSUP;
1284 : 0 : return rte_errno;
1285 : : }
1286 : :
1287 [ # # ]: 0 : if (m->hdr.src_port) {
1288 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(L4_SPORT, inner)];
1289 : 0 : fc->item_idx = item_idx;
1290 [ # # # # ]: 0 : fc->is_range = l && l->hdr.src_port;
1291 : 0 : fc->tag_set = &mlx5dr_definer_udp_src_port_set;
1292 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, source_port, inner);
1293 : : }
1294 : :
1295 [ # # ]: 0 : if (m->hdr.dst_port) {
1296 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, inner)];
1297 : 0 : fc->item_idx = item_idx;
1298 [ # # # # ]: 0 : fc->is_range = l && l->hdr.dst_port;
1299 : 0 : fc->tag_set = &mlx5dr_definer_udp_dst_port_set;
1300 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, destination_port, inner);
1301 : : }
1302 : :
1303 : : return 0;
1304 : : }
1305 : :
1306 : : static int
1307 : 0 : mlx5dr_definer_conv_item_tcp(struct mlx5dr_definer_conv_data *cd,
1308 : : struct rte_flow_item *item,
1309 : : int item_idx)
1310 : : {
1311 : 0 : const struct rte_flow_item_tcp *m = item->mask;
1312 : 0 : const struct rte_flow_item_tcp *l = item->last;
1313 : : struct mlx5dr_definer_fc *fc;
1314 : 0 : bool inner = cd->tunnel;
1315 : :
1316 : : /* Overwrite match on L4 type TCP */
1317 [ # # ]: 0 : if (!cd->relaxed) {
1318 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
1319 [ # # ]: 0 : if (!fc->not_overwrite) {
1320 : 0 : fc->item_idx = item_idx;
1321 : 0 : fc->tag_set = &mlx5dr_definer_tcp_protocol_set;
1322 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1323 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, inner);
1324 : : }
1325 : : }
1326 : :
1327 [ # # ]: 0 : if (!m)
1328 : : return 0;
1329 : :
1330 [ # # # # : 0 : if (m->hdr.sent_seq || m->hdr.recv_ack || m->hdr.data_off ||
# # ]
1331 [ # # # # : 0 : m->hdr.rx_win || m->hdr.cksum || m->hdr.tcp_urp) {
# # ]
1332 : 0 : rte_errno = ENOTSUP;
1333 : 0 : return rte_errno;
1334 : : }
1335 : :
1336 [ # # ]: 0 : if (m->hdr.tcp_flags) {
1337 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(TCP_FLAGS, inner)];
1338 : 0 : fc->item_idx = item_idx;
1339 [ # # # # ]: 0 : fc->is_range = l && l->hdr.tcp_flags;
1340 : 0 : fc->tag_set = &mlx5dr_definer_tcp_flags_set;
1341 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, tcp_flags, inner);
1342 : : }
1343 : :
1344 [ # # ]: 0 : if (m->hdr.src_port) {
1345 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(L4_SPORT, inner)];
1346 : 0 : fc->item_idx = item_idx;
1347 [ # # # # ]: 0 : fc->is_range = l && l->hdr.src_port;
1348 : 0 : fc->tag_set = &mlx5dr_definer_tcp_src_port_set;
1349 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, source_port, inner);
1350 : : }
1351 : :
1352 [ # # ]: 0 : if (m->hdr.dst_port) {
1353 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, inner)];
1354 : 0 : fc->item_idx = item_idx;
1355 [ # # # # ]: 0 : fc->is_range = l && l->hdr.dst_port;
1356 : 0 : fc->tag_set = &mlx5dr_definer_tcp_dst_port_set;
1357 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, destination_port, inner);
1358 : : }
1359 : :
1360 : : return 0;
1361 : : }
1362 : :
1363 : : static int
1364 : 0 : mlx5dr_definer_conv_item_gtp(struct mlx5dr_definer_conv_data *cd,
1365 : : struct rte_flow_item *item,
1366 : : int item_idx)
1367 : : {
1368 : 0 : struct mlx5dr_cmd_query_caps *caps = cd->ctx->caps;
1369 : 0 : const struct rte_flow_item_gtp *m = item->mask;
1370 : : struct mlx5dr_definer_fc *fc;
1371 : :
1372 [ # # ]: 0 : if (cd->tunnel) {
1373 : 0 : DR_LOG(ERR, "Inner GTPU item not supported");
1374 : 0 : rte_errno = ENOTSUP;
1375 : 0 : return rte_errno;
1376 : : }
1377 : :
1378 : : /* Overwrite GTPU dest port if not present */
1379 : 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, false)];
1380 [ # # # # ]: 0 : if (!fc->tag_set && !cd->relaxed) {
1381 : 0 : fc->item_idx = item_idx;
1382 : 0 : fc->tag_set = &mlx5dr_definer_gtp_udp_port_set;
1383 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1384 : 0 : DR_CALC_SET(fc, eth_l4, destination_port, false);
1385 : : }
1386 : :
1387 [ # # ]: 0 : if (!m)
1388 : : return 0;
1389 : :
1390 [ # # # # ]: 0 : if (m->hdr.plen || m->hdr.gtp_hdr_info & ~MLX5DR_DEFINER_GTP_EXT_HDR_BIT) {
1391 : 0 : rte_errno = ENOTSUP;
1392 : 0 : return rte_errno;
1393 : : }
1394 : :
1395 [ # # ]: 0 : if (m->hdr.teid) {
1396 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_TEID_ENABLED)) {
1397 : 0 : rte_errno = ENOTSUP;
1398 : 0 : return rte_errno;
1399 : : }
1400 : : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_TEID];
1401 : 0 : fc->item_idx = item_idx;
1402 : 0 : fc->tag_set = &mlx5dr_definer_gtp_teid_set;
1403 : 0 : fc->bit_mask = __mlx5_mask(header_gtp, teid);
1404 : 0 : fc->byte_off = caps->format_select_gtpu_dw_1 * DW_SIZE;
1405 : : }
1406 : :
1407 [ # # ]: 0 : if (m->hdr.gtp_hdr_info) {
1408 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_DW_0_ENABLED)) {
1409 : 0 : rte_errno = ENOTSUP;
1410 : 0 : return rte_errno;
1411 : : }
1412 : : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_EXT_FLAG];
1413 : 0 : fc->item_idx = item_idx;
1414 : 0 : fc->tag_set = &mlx5dr_definer_gtp_ext_flag_set;
1415 : 0 : fc->bit_mask = __mlx5_mask(header_gtp, ext_hdr_flag);
1416 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gtp, ext_hdr_flag);
1417 : 0 : fc->byte_off = caps->format_select_gtpu_dw_0 * DW_SIZE;
1418 : : }
1419 : :
1420 : :
1421 [ # # ]: 0 : if (m->hdr.msg_type) {
1422 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_DW_0_ENABLED)) {
1423 : 0 : rte_errno = ENOTSUP;
1424 : 0 : return rte_errno;
1425 : : }
1426 : : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_MSG_TYPE];
1427 : 0 : fc->item_idx = item_idx;
1428 : 0 : fc->tag_set = &mlx5dr_definer_gtp_msg_type_set;
1429 : 0 : fc->bit_mask = __mlx5_mask(header_gtp, msg_type);
1430 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gtp, msg_type);
1431 : 0 : fc->byte_off = caps->format_select_gtpu_dw_0 * DW_SIZE;
1432 : : }
1433 : :
1434 : : return 0;
1435 : : }
1436 : :
1437 : : static int
1438 : 0 : mlx5dr_definer_conv_item_gtp_psc(struct mlx5dr_definer_conv_data *cd,
1439 : : struct rte_flow_item *item,
1440 : : int item_idx)
1441 : : {
1442 : 0 : struct mlx5dr_cmd_query_caps *caps = cd->ctx->caps;
1443 : 0 : const struct rte_flow_item_gtp_psc *m = item->mask;
1444 : : struct mlx5dr_definer_fc *fc;
1445 : :
1446 : : /* Overwrite GTP extension flag to be 1 */
1447 [ # # ]: 0 : if (!cd->relaxed) {
1448 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_DW_0_ENABLED)) {
1449 : 0 : rte_errno = ENOTSUP;
1450 : 0 : return rte_errno;
1451 : : }
1452 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_EXT_FLAG];
1453 : 0 : fc->item_idx = item_idx;
1454 : 0 : fc->tag_set = &mlx5dr_definer_ones_set;
1455 : 0 : fc->bit_mask = __mlx5_mask(header_gtp, ext_hdr_flag);
1456 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gtp, ext_hdr_flag);
1457 : 0 : fc->byte_off = caps->format_select_gtpu_dw_0 * DW_SIZE;
1458 : : }
1459 : :
1460 : : /* Overwrite next extension header type */
1461 [ # # ]: 0 : if (!cd->relaxed) {
1462 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_DW_2_ENABLED)) {
1463 : 0 : rte_errno = ENOTSUP;
1464 : 0 : return rte_errno;
1465 : : }
1466 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_NEXT_EXT_HDR];
1467 : 0 : fc->item_idx = item_idx;
1468 : 0 : fc->tag_set = &mlx5dr_definer_gtp_next_ext_hdr_set;
1469 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1470 : 0 : fc->bit_mask = __mlx5_mask(header_opt_gtp, next_ext_hdr_type);
1471 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_opt_gtp, next_ext_hdr_type);
1472 : 0 : fc->byte_off = caps->format_select_gtpu_dw_2 * DW_SIZE;
1473 : : }
1474 : :
1475 [ # # ]: 0 : if (!m)
1476 : : return 0;
1477 : :
1478 [ # # ]: 0 : if (m->hdr.type) {
1479 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_FIRST_EXT_DW_0_ENABLED)) {
1480 : 0 : rte_errno = ENOTSUP;
1481 : 0 : return rte_errno;
1482 : : }
1483 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_EXT_HDR_PDU];
1484 : 0 : fc->item_idx = item_idx;
1485 : 0 : fc->tag_set = &mlx5dr_definer_gtp_ext_hdr_pdu_set;
1486 : 0 : fc->bit_mask = __mlx5_mask(header_gtp_psc, pdu_type);
1487 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gtp_psc, pdu_type);
1488 : 0 : fc->byte_off = caps->format_select_gtpu_ext_dw_0 * DW_SIZE;
1489 : : }
1490 : :
1491 [ # # ]: 0 : if (m->hdr.qfi) {
1492 [ # # ]: 0 : if (!(caps->flex_protocols & MLX5_HCA_FLEX_GTPU_FIRST_EXT_DW_0_ENABLED)) {
1493 : 0 : rte_errno = ENOTSUP;
1494 : 0 : return rte_errno;
1495 : : }
1496 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GTP_EXT_HDR_QFI];
1497 : 0 : fc->item_idx = item_idx;
1498 : 0 : fc->tag_set = &mlx5dr_definer_gtp_ext_hdr_qfi_set;
1499 : 0 : fc->bit_mask = __mlx5_mask(header_gtp_psc, qfi);
1500 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gtp_psc, qfi);
1501 : 0 : fc->byte_off = caps->format_select_gtpu_ext_dw_0 * DW_SIZE;
1502 : : }
1503 : :
1504 : : return 0;
1505 : : }
1506 : :
1507 : : static int
1508 : 0 : mlx5dr_definer_conv_item_port(struct mlx5dr_definer_conv_data *cd,
1509 : : struct rte_flow_item *item,
1510 : : int item_idx)
1511 : : {
1512 : 0 : struct mlx5dr_cmd_query_caps *caps = cd->ctx->caps;
1513 : 0 : const struct rte_flow_item_ethdev *m = item->mask;
1514 : : struct mlx5dr_definer_fc *fc;
1515 : :
1516 [ # # ]: 0 : if (m->port_id) {
1517 [ # # ]: 0 : if (!caps->wire_regc_mask) {
1518 : 0 : DR_LOG(ERR, "Port ID item not supported, missing wire REGC mask");
1519 : 0 : rte_errno = ENOTSUP;
1520 : 0 : return rte_errno;
1521 : : }
1522 : :
1523 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VPORT_REG_C_0];
1524 : 0 : fc->item_idx = item_idx;
1525 : 0 : fc->tag_set = &mlx5dr_definer_vport_set;
1526 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1527 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_0);
1528 : 0 : fc->bit_off = __builtin_ctz(caps->wire_regc_mask);
1529 : 0 : fc->bit_mask = caps->wire_regc_mask >> fc->bit_off;
1530 : : } else {
1531 : 0 : DR_LOG(ERR, "Pord ID item mask must specify ID mask");
1532 : 0 : rte_errno = EINVAL;
1533 : 0 : return rte_errno;
1534 : : }
1535 : :
1536 : 0 : return 0;
1537 : : }
1538 : :
1539 : : static int
1540 : 0 : mlx5dr_definer_conv_item_vxlan(struct mlx5dr_definer_conv_data *cd,
1541 : : struct rte_flow_item *item,
1542 : : int item_idx)
1543 : : {
1544 : 0 : const struct rte_flow_item_vxlan *m = item->mask;
1545 : : struct mlx5dr_definer_fc *fc;
1546 : 0 : bool inner = cd->tunnel;
1547 : :
1548 [ # # # # : 0 : if (m && (m->rsvd0[0] != 0 || m->rsvd0[1] != 0 || m->rsvd0[2] != 0 ||
# # # # ]
1549 [ # # ]: 0 : m->rsvd1 != 0)) {
1550 : 0 : DR_LOG(ERR, "reserved fields are not supported");
1551 : 0 : rte_errno = ENOTSUP;
1552 : 0 : return rte_errno;
1553 : : }
1554 : :
1555 [ # # ]: 0 : if (inner) {
1556 : 0 : DR_LOG(ERR, "Inner VXLAN item not supported");
1557 : 0 : rte_errno = ENOTSUP;
1558 : 0 : return rte_errno;
1559 : : }
1560 : :
1561 : : /* In order to match on VXLAN we must match on ip_protocol and l4_dport */
1562 [ # # ]: 0 : if (!cd->relaxed) {
1563 : 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
1564 [ # # ]: 0 : if (!fc->tag_set) {
1565 : 0 : fc->item_idx = item_idx;
1566 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1567 : 0 : fc->tag_set = &mlx5dr_definer_udp_protocol_set;
1568 : 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, inner);
1569 : : }
1570 : :
1571 : 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, inner)];
1572 [ # # ]: 0 : if (!fc->tag_set) {
1573 : 0 : fc->item_idx = item_idx;
1574 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1575 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_udp_port_set;
1576 : 0 : DR_CALC_SET(fc, eth_l4, destination_port, inner);
1577 : : }
1578 : : }
1579 : :
1580 [ # # ]: 0 : if (!m)
1581 : : return 0;
1582 : :
1583 [ # # ]: 0 : if (m->flags) {
1584 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_FLAGS];
1585 : 0 : fc->item_idx = item_idx;
1586 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_flags_set;
1587 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
1588 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan, flags);
1589 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_vxlan, flags);
1590 : : }
1591 : :
1592 [ # # ]: 0 : if (!is_mem_zero(m->vni, 3)) {
1593 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_VNI];
1594 : 0 : fc->item_idx = item_idx;
1595 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_vni_set;
1596 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_1);
1597 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan, vni);
1598 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_vxlan, vni);
1599 : : }
1600 : :
1601 : : return 0;
1602 : : }
1603 : :
1604 : : static int
1605 : 0 : mlx5dr_definer_conv_item_mpls(struct mlx5dr_definer_conv_data *cd,
1606 : : struct rte_flow_item *item,
1607 : : int item_idx)
1608 : : {
1609 : 0 : const struct rte_flow_item_mpls *m = item->mask;
1610 : : struct mlx5dr_definer_fc *fc;
1611 : 0 : bool inner = cd->tunnel;
1612 : :
1613 [ # # ]: 0 : if (inner) {
1614 : 0 : DR_LOG(ERR, "Inner MPLS item not supported");
1615 : 0 : rte_errno = ENOTSUP;
1616 : 0 : return rte_errno;
1617 : : }
1618 : :
1619 [ # # ]: 0 : if (!cd->relaxed) {
1620 : : /* In order to match on MPLS we must match on ip_protocol and l4_dport. */
1621 : 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, false)];
1622 [ # # ]: 0 : if (!fc->tag_set) {
1623 : 0 : fc->item_idx = item_idx;
1624 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1625 : 0 : fc->tag_set = &mlx5dr_definer_udp_protocol_set;
1626 : 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, false);
1627 : : }
1628 : :
1629 : : /* Currently support only MPLSoUDP */
1630 : : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, false)];
1631 [ # # ]: 0 : if (!fc->tag_set) {
1632 : 0 : fc->item_idx = item_idx;
1633 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1634 : 0 : fc->tag_set = &mlx5dr_definer_mpls_udp_port_set;
1635 : 0 : DR_CALC_SET(fc, eth_l4, destination_port, false);
1636 : : }
1637 : : }
1638 : :
1639 [ # # # # : 0 : if (m && (!is_mem_zero(m->label_tc_s, 3) || m->ttl)) {
# # ]
1640 : : /* According to HW MPLSoUDP is handled as inner */
1641 : 0 : fc = mlx5dr_definer_get_mpls_fc(cd, true);
1642 [ # # ]: 0 : if (!fc)
1643 : 0 : return rte_errno;
1644 : :
1645 : 0 : fc->item_idx = item_idx;
1646 : 0 : fc->tag_set = &mlx5dr_definer_mpls_label_set;
1647 : : } else { /* Mask relevant oks2 bit, indicates MPLS label exists.
1648 : : * According to HW MPLSoUDP is handled as inner
1649 : : */
1650 : 0 : fc = mlx5dr_definer_get_mpls_oks_fc(cd, true);
1651 [ # # ]: 0 : if (!fc)
1652 : 0 : return rte_errno;
1653 : :
1654 : 0 : fc->item_idx = item_idx;
1655 : 0 : fc->tag_set = mlx5dr_definer_ones_set;
1656 : : }
1657 : :
1658 : : return 0;
1659 : : }
1660 : :
1661 : : static struct mlx5dr_definer_fc *
1662 : 0 : mlx5dr_definer_get_register_fc(struct mlx5dr_definer_conv_data *cd, int reg)
1663 : : {
1664 : : struct mlx5dr_definer_fc *fc;
1665 : :
1666 [ # # # # : 0 : switch (reg) {
# # # # #
# # # # #
# ]
1667 : 0 : case REG_C_0:
1668 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_0];
1669 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_0);
1670 : 0 : break;
1671 : 0 : case REG_C_1:
1672 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_1];
1673 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_1);
1674 : 0 : break;
1675 : 0 : case REG_C_2:
1676 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_2];
1677 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_2);
1678 : 0 : break;
1679 : 0 : case REG_C_3:
1680 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_3];
1681 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_3);
1682 : 0 : break;
1683 : 0 : case REG_C_4:
1684 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_4];
1685 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_4);
1686 : 0 : break;
1687 : 0 : case REG_C_5:
1688 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_5];
1689 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_5);
1690 : 0 : break;
1691 : 0 : case REG_C_6:
1692 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_6];
1693 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_6);
1694 : 0 : break;
1695 : 0 : case REG_C_7:
1696 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_7];
1697 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_7);
1698 : 0 : break;
1699 : 0 : case REG_C_8:
1700 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_8];
1701 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_8);
1702 : 0 : break;
1703 : 0 : case REG_C_9:
1704 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_9];
1705 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_9);
1706 : 0 : break;
1707 : 0 : case REG_C_10:
1708 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_10];
1709 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_10);
1710 : 0 : break;
1711 : 0 : case REG_C_11:
1712 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_11];
1713 : 0 : DR_CALC_SET_HDR(fc, registers, register_c_11);
1714 : 0 : break;
1715 : 0 : case REG_A:
1716 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_A];
1717 : 0 : DR_CALC_SET_HDR(fc, metadata, general_purpose);
1718 : 0 : break;
1719 : 0 : case REG_B:
1720 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_REG_B];
1721 : 0 : DR_CALC_SET_HDR(fc, metadata, metadata_to_cqe);
1722 : 0 : break;
1723 : 0 : default:
1724 : 0 : rte_errno = ENOTSUP;
1725 : 0 : return NULL;
1726 : : }
1727 : :
1728 : : return fc;
1729 : : }
1730 : :
1731 : : static int
1732 : 0 : mlx5dr_definer_conv_item_tag(struct mlx5dr_definer_conv_data *cd,
1733 : : struct rte_flow_item *item,
1734 : : int item_idx)
1735 : : {
1736 : 0 : const struct rte_flow_item_tag *m = item->mask;
1737 : 0 : const struct rte_flow_item_tag *v = item->spec;
1738 : 0 : const struct rte_flow_item_tag *l = item->last;
1739 : : struct mlx5dr_definer_fc *fc;
1740 : : int reg;
1741 : :
1742 [ # # ]: 0 : if (!m || !v)
1743 : : return 0;
1744 : :
1745 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_TAG)
1746 : 0 : reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
1747 : : RTE_FLOW_ITEM_TYPE_TAG,
1748 : : MLX5DR_TABLE_TYPE_DONTCARE,
1749 : 0 : v->index);
1750 : : else
1751 : 0 : reg = (int)v->index;
1752 : :
1753 [ # # ]: 0 : if (reg <= 0) {
1754 : 0 : DR_LOG(ERR, "Invalid register for item tag");
1755 : 0 : rte_errno = EINVAL;
1756 : 0 : return rte_errno;
1757 : : }
1758 : :
1759 : 0 : fc = mlx5dr_definer_get_register_fc(cd, reg);
1760 [ # # ]: 0 : if (!fc)
1761 : 0 : return rte_errno;
1762 : :
1763 : 0 : fc->item_idx = item_idx;
1764 [ # # # # ]: 0 : fc->is_range = l && l->index;
1765 : 0 : fc->tag_set = &mlx5dr_definer_tag_set;
1766 : :
1767 : 0 : return 0;
1768 : : }
1769 : :
1770 : : static void
1771 : 0 : mlx5dr_definer_quota_set(struct mlx5dr_definer_fc *fc,
1772 : : const void *item_data, uint8_t *tag)
1773 : : {
1774 : : /**
1775 : : * MLX5 PMD implements QUOTA with Meter object.
1776 : : * PMD Quota action translation implicitly increments
1777 : : * Meter register value after HW assigns it.
1778 : : * Meter register values are:
1779 : : * HW QUOTA(HW+1) QUOTA state
1780 : : * RED 0 1 (01b) BLOCK
1781 : : * YELLOW 1 2 (10b) PASS
1782 : : * GREEN 2 3 (11b) PASS
1783 : : *
1784 : : * Quota item checks Meter register bit 1 value to determine state:
1785 : : * SPEC MASK
1786 : : * PASS 2 (10b) 2 (10b)
1787 : : * BLOCK 0 (00b) 2 (10b)
1788 : : *
1789 : : * item_data is NULL when template quota item is non-masked:
1790 : : * .. / quota / ..
1791 : : */
1792 : :
1793 : : const struct rte_flow_item_quota *quota = item_data;
1794 : : uint32_t val;
1795 : :
1796 [ # # # # ]: 0 : if (quota && quota->state == RTE_FLOW_QUOTA_STATE_BLOCK)
1797 : : val = MLX5DR_DEFINER_QUOTA_BLOCK;
1798 : : else
1799 : : val = MLX5DR_DEFINER_QUOTA_PASS;
1800 : :
1801 [ # # # # : 0 : DR_SET(tag, val, fc->byte_off, fc->bit_off, fc->bit_mask);
# # # # ]
1802 : 0 : }
1803 : :
1804 : : static int
1805 : 0 : mlx5dr_definer_conv_item_quota(struct mlx5dr_definer_conv_data *cd,
1806 : : __rte_unused struct rte_flow_item *item,
1807 : : int item_idx)
1808 : : {
1809 : 0 : int mtr_reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
1810 : : RTE_FLOW_ITEM_TYPE_METER_COLOR,
1811 : : MLX5DR_TABLE_TYPE_DONTCARE,
1812 : : 0);
1813 : : struct mlx5dr_definer_fc *fc;
1814 : :
1815 [ # # ]: 0 : if (mtr_reg < 0) {
1816 : 0 : rte_errno = EINVAL;
1817 : 0 : return rte_errno;
1818 : : }
1819 : :
1820 : 0 : fc = mlx5dr_definer_get_register_fc(cd, mtr_reg);
1821 [ # # ]: 0 : if (!fc)
1822 : 0 : return rte_errno;
1823 : :
1824 : 0 : fc->tag_set = &mlx5dr_definer_quota_set;
1825 : 0 : fc->item_idx = item_idx;
1826 : 0 : return 0;
1827 : : }
1828 : :
1829 : : static int
1830 : 0 : mlx5dr_definer_conv_item_metadata(struct mlx5dr_definer_conv_data *cd,
1831 : : enum mlx5dr_table_type table_domain_type,
1832 : : struct rte_flow_item *item,
1833 : : int item_idx)
1834 : : {
1835 : 0 : const struct rte_flow_item_meta *m = item->mask;
1836 : 0 : const struct rte_flow_item_meta *l = item->last;
1837 : : struct mlx5dr_definer_fc *fc;
1838 : : int reg;
1839 : :
1840 [ # # ]: 0 : if (!m)
1841 : : return 0;
1842 : :
1843 : 0 : reg = flow_hw_get_reg_id_from_ctx(cd->ctx, RTE_FLOW_ITEM_TYPE_META,
1844 : : table_domain_type, -1);
1845 : : if (reg <= 0) {
1846 : 0 : DR_LOG(ERR, "Invalid register for item metadata");
1847 : 0 : rte_errno = EINVAL;
1848 : 0 : return rte_errno;
1849 : : }
1850 : :
1851 : 0 : fc = mlx5dr_definer_get_register_fc(cd, reg);
1852 [ # # ]: 0 : if (!fc)
1853 : 0 : return rte_errno;
1854 : :
1855 : 0 : fc->item_idx = item_idx;
1856 [ # # # # ]: 0 : fc->is_range = l && l->data;
1857 : 0 : fc->tag_set = &mlx5dr_definer_metadata_set;
1858 : :
1859 : 0 : return 0;
1860 : : }
1861 : :
1862 : : static int
1863 : : mlx5dr_definer_conv_item_sq(struct mlx5dr_definer_conv_data *cd,
1864 : : struct rte_flow_item *item,
1865 : : int item_idx)
1866 : : {
1867 : 0 : const struct mlx5_rte_flow_item_sq *m = item->mask;
1868 : : struct mlx5dr_definer_fc *fc;
1869 : :
1870 [ # # ]: 0 : if (!m)
1871 : : return 0;
1872 : :
1873 [ # # ]: 0 : if (m->queue) {
1874 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_SOURCE_QP];
1875 : 0 : fc->item_idx = item_idx;
1876 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1877 : 0 : fc->tag_set = &mlx5dr_definer_source_qp_set;
1878 : 0 : DR_CALC_SET_HDR(fc, source_qp_gvmi, source_qp);
1879 : : }
1880 : :
1881 : : return 0;
1882 : : }
1883 : :
1884 : : static int
1885 : 0 : mlx5dr_definer_conv_item_gre(struct mlx5dr_definer_conv_data *cd,
1886 : : struct rte_flow_item *item,
1887 : : int item_idx)
1888 : : {
1889 : 0 : const struct rte_flow_item_gre *m = item->mask;
1890 : : struct mlx5dr_definer_fc *fc;
1891 : 0 : bool inner = cd->tunnel;
1892 : :
1893 [ # # ]: 0 : if (inner) {
1894 : 0 : DR_LOG(ERR, "Inner GRE item not supported");
1895 : 0 : rte_errno = ENOTSUP;
1896 : 0 : return rte_errno;
1897 : : }
1898 : :
1899 [ # # ]: 0 : if (!cd->relaxed) {
1900 : 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
1901 : 0 : fc->item_idx = item_idx;
1902 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1903 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_protocol_gre_set;
1904 : 0 : DR_CALC_SET(fc, eth_l3, protocol_next_header, inner);
1905 : : }
1906 : :
1907 [ # # ]: 0 : if (!m)
1908 : : return 0;
1909 : :
1910 [ # # ]: 0 : if (m->c_rsvd0_ver) {
1911 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_C_VER];
1912 : 0 : fc->item_idx = item_idx;
1913 : 0 : fc->tag_set = &mlx5dr_definer_gre_c_ver_set;
1914 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
1915 : 0 : fc->bit_mask = __mlx5_mask(header_gre, c_rsvd0_ver);
1916 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gre, c_rsvd0_ver);
1917 : : }
1918 : :
1919 [ # # ]: 0 : if (m->protocol) {
1920 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_PROTOCOL];
1921 : 0 : fc->item_idx = item_idx;
1922 : 0 : fc->tag_set = &mlx5dr_definer_gre_protocol_type_set;
1923 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
1924 : 0 : fc->byte_off += MLX5_BYTE_OFF(header_gre, gre_protocol);
1925 : 0 : fc->bit_mask = __mlx5_mask(header_gre, gre_protocol);
1926 : : fc->bit_off = __mlx5_dw_bit_off(header_gre, gre_protocol);
1927 : : }
1928 : :
1929 : : return 0;
1930 : : }
1931 : :
1932 : : static int
1933 : 0 : mlx5dr_definer_conv_item_gre_opt(struct mlx5dr_definer_conv_data *cd,
1934 : : struct rte_flow_item *item,
1935 : : int item_idx)
1936 : : {
1937 : 0 : const struct rte_flow_item_gre_opt *m = item->mask;
1938 : : struct mlx5dr_definer_fc *fc;
1939 : :
1940 [ # # ]: 0 : if (!cd->relaxed) {
1941 : 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, false)];
1942 [ # # ]: 0 : if (!fc->tag_set) {
1943 : 0 : fc->item_idx = item_idx;
1944 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1945 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_protocol_gre_set;
1946 : 0 : DR_CALC_SET(fc, eth_l3, protocol_next_header, false);
1947 : : }
1948 : : }
1949 : :
1950 [ # # ]: 0 : if (!m)
1951 : : return 0;
1952 : :
1953 [ # # ]: 0 : if (m->checksum_rsvd.checksum) {
1954 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_OPT_CHECKSUM];
1955 : 0 : fc->item_idx = item_idx;
1956 : 0 : fc->tag_set = &mlx5dr_definer_gre_opt_checksum_set;
1957 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_1);
1958 : : }
1959 : :
1960 [ # # ]: 0 : if (m->key.key) {
1961 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_OPT_KEY];
1962 : 0 : fc->item_idx = item_idx;
1963 : 0 : fc->tag_set = &mlx5dr_definer_gre_opt_key_set;
1964 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_2);
1965 : : }
1966 : :
1967 [ # # ]: 0 : if (m->sequence.sequence) {
1968 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_OPT_SEQ];
1969 : 0 : fc->item_idx = item_idx;
1970 : 0 : fc->tag_set = &mlx5dr_definer_gre_opt_seq_set;
1971 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_3);
1972 : : }
1973 : :
1974 : : return 0;
1975 : : }
1976 : :
1977 : : static int
1978 : 0 : mlx5dr_definer_conv_item_gre_key(struct mlx5dr_definer_conv_data *cd,
1979 : : struct rte_flow_item *item,
1980 : : int item_idx)
1981 : : {
1982 : 0 : const rte_be32_t *m = item->mask;
1983 : : struct mlx5dr_definer_fc *fc;
1984 : :
1985 [ # # ]: 0 : if (!cd->relaxed) {
1986 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_KEY_PRESENT];
1987 : 0 : fc->item_idx = item_idx;
1988 : 0 : fc->tag_set = &mlx5dr_definer_ones_set;
1989 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
1990 : 0 : fc->bit_mask = __mlx5_mask(header_gre, gre_k_present);
1991 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_gre, gre_k_present);
1992 : :
1993 : : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, false)];
1994 [ # # ]: 0 : if (!fc->tag_set) {
1995 : 0 : fc->item_idx = item_idx;
1996 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
1997 : 0 : fc->tag_set = &mlx5dr_definer_ipv4_protocol_gre_set;
1998 : 0 : DR_CALC_SET(fc, eth_l3, protocol_next_header, false);
1999 : : }
2000 : : }
2001 : :
2002 [ # # ]: 0 : if (!m)
2003 : : return 0;
2004 : :
2005 [ # # ]: 0 : if (*m) {
2006 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GRE_OPT_KEY];
2007 : 0 : fc->item_idx = item_idx;
2008 : 0 : fc->tag_set = &mlx5dr_definer_gre_key_set;
2009 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_2);
2010 : : }
2011 : :
2012 : : return 0;
2013 : : }
2014 : :
2015 : : static int
2016 : 0 : mlx5dr_definer_conv_item_ptype(struct mlx5dr_definer_conv_data *cd,
2017 : : struct rte_flow_item *item,
2018 : : int item_idx)
2019 : : {
2020 : 0 : const struct rte_flow_item_ptype *m = item->mask;
2021 : : struct mlx5dr_definer_fc *fc;
2022 : :
2023 [ # # ]: 0 : if (!m)
2024 : : return 0;
2025 : :
2026 [ # # ]: 0 : if (!(m->packet_type &
2027 : : (RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK | RTE_PTYPE_L4_MASK | RTE_PTYPE_TUNNEL_MASK |
2028 : : RTE_PTYPE_INNER_L2_MASK | RTE_PTYPE_INNER_L3_MASK | RTE_PTYPE_INNER_L4_MASK))) {
2029 : 0 : rte_errno = ENOTSUP;
2030 : 0 : return rte_errno;
2031 : : }
2032 : :
2033 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_L2_MASK) {
2034 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_L2, false)];
2035 : 0 : fc->item_idx = item_idx;
2036 : 0 : fc->tag_set = &mlx5dr_definer_ptype_l2_set;
2037 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2038 : 0 : DR_CALC_SET(fc, eth_l2, first_vlan_qualifier, false);
2039 : : }
2040 : :
2041 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_INNER_L2_MASK) {
2042 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_L2, true)];
2043 : 0 : fc->item_idx = item_idx;
2044 : 0 : fc->tag_set = &mlx5dr_definer_ptype_l2_set;
2045 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2046 : 0 : DR_CALC_SET(fc, eth_l2, first_vlan_qualifier, true);
2047 : : }
2048 : :
2049 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_L3_MASK) {
2050 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_L3, false)];
2051 : 0 : fc->item_idx = item_idx;
2052 : 0 : fc->tag_set = &mlx5dr_definer_ptype_l3_set;
2053 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2054 : 0 : DR_CALC_SET(fc, eth_l2, l3_type, false);
2055 : : }
2056 : :
2057 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_INNER_L3_MASK) {
2058 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_L3, true)];
2059 : 0 : fc->item_idx = item_idx;
2060 : 0 : fc->tag_set = &mlx5dr_definer_ptype_l3_set;
2061 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2062 : 0 : DR_CALC_SET(fc, eth_l2, l3_type, true);
2063 : : }
2064 : :
2065 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_L4_MASK) {
2066 : : /*
2067 : : * Fragmented IP (Internet Protocol) packet type.
2068 : : * Cannot be combined with Layer 4 Types (TCP/UDP).
2069 : : * The exact value must be specified in the mask.
2070 : : */
2071 [ # # ]: 0 : if (m->packet_type == RTE_PTYPE_L4_FRAG) {
2072 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_FRAG, false)];
2073 : 0 : fc->item_idx = item_idx;
2074 : 0 : fc->tag_set = &mlx5dr_definer_ptype_frag_set;
2075 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2076 : 0 : DR_CALC_SET(fc, eth_l2, ip_fragmented, false);
2077 : : } else {
2078 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_L4, false)];
2079 : 0 : fc->item_idx = item_idx;
2080 : 0 : fc->tag_set = &mlx5dr_definer_ptype_l4_set;
2081 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2082 : 0 : DR_CALC_SET(fc, eth_l2, l4_type, false);
2083 : : }
2084 : : }
2085 : :
2086 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_INNER_L4_MASK) {
2087 [ # # ]: 0 : if (m->packet_type == RTE_PTYPE_INNER_L4_FRAG) {
2088 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_FRAG, true)];
2089 : 0 : fc->item_idx = item_idx;
2090 : 0 : fc->tag_set = &mlx5dr_definer_ptype_frag_set;
2091 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2092 : 0 : DR_CALC_SET(fc, eth_l2, ip_fragmented, true);
2093 : : } else {
2094 : 0 : fc = &cd->fc[DR_CALC_FNAME(PTYPE_L4, true)];
2095 : 0 : fc->item_idx = item_idx;
2096 : 0 : fc->tag_set = &mlx5dr_definer_ptype_l4_set;
2097 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2098 : 0 : DR_CALC_SET(fc, eth_l2, l4_type, true);
2099 : : }
2100 : : }
2101 : :
2102 [ # # ]: 0 : if (m->packet_type & RTE_PTYPE_TUNNEL_MASK) {
2103 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_PTYPE_TUNNEL];
2104 : 0 : fc->item_idx = item_idx;
2105 : 0 : fc->tag_set = &mlx5dr_definer_ptype_tunnel_set;
2106 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2107 : 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, false);
2108 : : }
2109 : :
2110 : : return 0;
2111 : : }
2112 : :
2113 : : static int
2114 : 0 : mlx5dr_definer_conv_item_integrity(struct mlx5dr_definer_conv_data *cd,
2115 : : struct rte_flow_item *item,
2116 : : int item_idx)
2117 : : {
2118 : 0 : const struct rte_flow_item_integrity *m = item->mask;
2119 : : struct mlx5dr_definer_fc *fc;
2120 : :
2121 [ # # ]: 0 : if (!m)
2122 : : return 0;
2123 : :
2124 [ # # ]: 0 : if (m->packet_ok || m->l2_ok || m->l2_crc_ok || m->l3_len_ok) {
2125 : 0 : rte_errno = ENOTSUP;
2126 : 0 : return rte_errno;
2127 : : }
2128 : :
2129 [ # # ]: 0 : if (m->l3_ok || m->ipv4_csum_ok || m->l4_ok || m->l4_csum_ok) {
2130 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(INTEGRITY, m->level)];
2131 : 0 : fc->item_idx = item_idx;
2132 : 0 : fc->tag_set = &mlx5dr_definer_integrity_set;
2133 : 0 : DR_CALC_SET_HDR(fc, oks1, oks1_bits);
2134 : : }
2135 : :
2136 : : return 0;
2137 : : }
2138 : :
2139 : : static int
2140 : 0 : mlx5dr_definer_conv_item_conntrack(struct mlx5dr_definer_conv_data *cd,
2141 : : struct rte_flow_item *item,
2142 : : int item_idx)
2143 : : {
2144 : 0 : const struct rte_flow_item_conntrack *m = item->mask;
2145 : : struct mlx5dr_definer_fc *fc;
2146 : : int reg;
2147 : :
2148 [ # # ]: 0 : if (!m)
2149 : : return 0;
2150 : :
2151 : 0 : reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
2152 : : RTE_FLOW_ITEM_TYPE_CONNTRACK,
2153 : : MLX5DR_TABLE_TYPE_DONTCARE, -1);
2154 [ # # ]: 0 : if (reg <= 0) {
2155 : 0 : DR_LOG(ERR, "Invalid register for item conntrack");
2156 : 0 : rte_errno = EINVAL;
2157 : 0 : return rte_errno;
2158 : : }
2159 : :
2160 : 0 : fc = mlx5dr_definer_get_register_fc(cd, reg);
2161 [ # # ]: 0 : if (!fc)
2162 : 0 : return rte_errno;
2163 : :
2164 : 0 : fc->item_idx = item_idx;
2165 : 0 : fc->tag_mask_set = &mlx5dr_definer_conntrack_mask;
2166 : 0 : fc->tag_set = &mlx5dr_definer_conntrack_tag;
2167 : :
2168 : 0 : return 0;
2169 : : }
2170 : :
2171 : : static int
2172 : 0 : mlx5dr_definer_conv_item_icmp(struct mlx5dr_definer_conv_data *cd,
2173 : : struct rte_flow_item *item,
2174 : : int item_idx)
2175 : : {
2176 : 0 : const struct rte_flow_item_icmp *m = item->mask;
2177 : : struct mlx5dr_definer_fc *fc;
2178 : 0 : bool inner = cd->tunnel;
2179 : :
2180 : : /* Overwrite match on L4 type ICMP */
2181 [ # # ]: 0 : if (!cd->relaxed) {
2182 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2183 : 0 : fc->item_idx = item_idx;
2184 : 0 : fc->tag_set = &mlx5dr_definer_icmp_protocol_set;
2185 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2186 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l4_type, inner);
2187 : : }
2188 : :
2189 [ # # ]: 0 : if (!m)
2190 : : return 0;
2191 : :
2192 [ # # # # : 0 : if (m->hdr.icmp_type || m->hdr.icmp_code || m->hdr.icmp_cksum) {
# # ]
2193 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ICMP_DW1];
2194 : 0 : fc->item_idx = item_idx;
2195 : 0 : fc->tag_set = &mlx5dr_definer_icmp_dw1_set;
2196 : 0 : DR_CALC_SET_HDR(fc, tcp_icmp, icmp_dw1);
2197 : : }
2198 : :
2199 [ # # # # ]: 0 : if (m->hdr.icmp_ident || m->hdr.icmp_seq_nb) {
2200 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ICMP_DW2];
2201 : 0 : fc->item_idx = item_idx;
2202 : 0 : fc->tag_set = &mlx5dr_definer_icmp_dw2_set;
2203 : 0 : DR_CALC_SET_HDR(fc, tcp_icmp, icmp_dw2);
2204 : : }
2205 : :
2206 : : return 0;
2207 : : }
2208 : :
2209 : : static int
2210 : 0 : mlx5dr_definer_conv_item_icmp6(struct mlx5dr_definer_conv_data *cd,
2211 : : struct rte_flow_item *item,
2212 : : int item_idx)
2213 : : {
2214 : 0 : const struct rte_flow_item_icmp6 *m = item->mask;
2215 : : struct mlx5dr_definer_fc *fc;
2216 : 0 : bool inner = cd->tunnel;
2217 : :
2218 : : /* Overwrite match on L4 type ICMP6 */
2219 [ # # ]: 0 : if (!cd->relaxed) {
2220 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2221 : 0 : fc->item_idx = item_idx;
2222 : 0 : fc->tag_set = &mlx5dr_definer_icmp_protocol_set;
2223 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2224 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l4_type, inner);
2225 : : }
2226 : :
2227 [ # # ]: 0 : if (!m)
2228 : : return 0;
2229 : :
2230 [ # # # # ]: 0 : if (m->type || m->code || m->checksum) {
2231 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ICMP_DW1];
2232 : 0 : fc->item_idx = item_idx;
2233 : 0 : fc->tag_set = &mlx5dr_definer_icmp6_dw1_set;
2234 : 0 : DR_CALC_SET_HDR(fc, tcp_icmp, icmp_dw1);
2235 : : }
2236 : :
2237 : : return 0;
2238 : : }
2239 : :
2240 : : static int
2241 : 0 : mlx5dr_definer_conv_item_icmp6_echo(struct mlx5dr_definer_conv_data *cd,
2242 : : struct rte_flow_item *item,
2243 : : int item_idx)
2244 : : {
2245 : 0 : const struct rte_flow_item_icmp6_echo *m = item->mask;
2246 : : struct mlx5dr_definer_fc *fc;
2247 : 0 : bool inner = cd->tunnel;
2248 : :
2249 [ # # ]: 0 : if (!cd->relaxed) {
2250 : : /* Overwrite match on L4 type ICMP6 */
2251 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2252 : 0 : fc->item_idx = item_idx;
2253 : 0 : fc->tag_set = &mlx5dr_definer_icmp_protocol_set;
2254 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2255 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l4_type, inner);
2256 : :
2257 : : /* Set fixed type and code for icmp6 echo request/reply */
2258 : : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ICMP_DW1];
2259 : 0 : fc->item_idx = item_idx;
2260 : 0 : fc->tag_mask_set = &mlx5dr_definer_icmp6_echo_dw1_mask_set;
2261 [ # # ]: 0 : if (item->type == RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST)
2262 : 0 : fc->tag_set = &mlx5dr_definer_icmp6_echo_request_dw1_set;
2263 : : else /* RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY */
2264 : 0 : fc->tag_set = &mlx5dr_definer_icmp6_echo_reply_dw1_set;
2265 : 0 : DR_CALC_SET_HDR(fc, tcp_icmp, icmp_dw1);
2266 : : }
2267 : :
2268 [ # # ]: 0 : if (!m)
2269 : : return 0;
2270 : :
2271 : : /* Set identifier & sequence into icmp_dw2 */
2272 [ # # # # ]: 0 : if (m->hdr.identifier || m->hdr.sequence) {
2273 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ICMP_DW2];
2274 : 0 : fc->item_idx = item_idx;
2275 : 0 : fc->tag_set = &mlx5dr_definer_icmp6_echo_dw2_set;
2276 : 0 : DR_CALC_SET_HDR(fc, tcp_icmp, icmp_dw2);
2277 : : }
2278 : :
2279 : : return 0;
2280 : : }
2281 : :
2282 : : static int
2283 : 0 : mlx5dr_definer_conv_item_meter_color(struct mlx5dr_definer_conv_data *cd,
2284 : : struct rte_flow_item *item,
2285 : : int item_idx)
2286 : : {
2287 : 0 : const struct rte_flow_item_meter_color *m = item->mask;
2288 : : struct mlx5dr_definer_fc *fc;
2289 : : int reg;
2290 : :
2291 [ # # ]: 0 : if (!m)
2292 : : return 0;
2293 : :
2294 : 0 : reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
2295 : : RTE_FLOW_ITEM_TYPE_METER_COLOR,
2296 : : MLX5DR_TABLE_TYPE_DONTCARE, 0);
2297 : : MLX5_ASSERT(reg > 0);
2298 : :
2299 : 0 : fc = mlx5dr_definer_get_register_fc(cd, reg);
2300 [ # # ]: 0 : if (!fc)
2301 : 0 : return rte_errno;
2302 : :
2303 : 0 : fc->item_idx = item_idx;
2304 : 0 : fc->tag_set = &mlx5dr_definer_meter_color_set;
2305 : 0 : return 0;
2306 : : }
2307 : :
2308 : : static struct mlx5dr_definer_fc *
2309 : : mlx5dr_definer_get_flex_parser_fc(struct mlx5dr_definer_conv_data *cd, uint32_t byte_off)
2310 : : {
2311 : : uint32_t byte_off_fp7 = MLX5_BYTE_OFF(definer_hl, flex_parser.flex_parser_7);
2312 : : uint32_t byte_off_fp0 = MLX5_BYTE_OFF(definer_hl, flex_parser.flex_parser_0);
2313 : : enum mlx5dr_definer_fname fname = MLX5DR_DEFINER_FNAME_FLEX_PARSER_0;
2314 : : struct mlx5dr_definer_fc *fc;
2315 : : uint32_t idx;
2316 : :
2317 : 0 : if (byte_off < byte_off_fp7 || byte_off > byte_off_fp0) {
2318 : 0 : rte_errno = EINVAL;
2319 : : return NULL;
2320 : : }
2321 : 0 : idx = (byte_off_fp0 - byte_off) / (sizeof(uint32_t));
2322 : 0 : fname += (enum mlx5dr_definer_fname)idx;
2323 : 0 : fc = &cd->fc[fname];
2324 : 0 : fc->byte_off = byte_off;
2325 : 0 : fc->bit_mask = UINT32_MAX;
2326 : : return fc;
2327 : : }
2328 : :
2329 : : static int
2330 : 0 : mlx5dr_definer_conv_item_ipv6_routing_ext(struct mlx5dr_definer_conv_data *cd,
2331 : : struct rte_flow_item *item,
2332 : : int item_idx)
2333 : : {
2334 : 0 : const struct rte_flow_item_ipv6_routing_ext *m = item->mask;
2335 : : struct mlx5dr_definer_fc *fc;
2336 : 0 : bool inner = cd->tunnel;
2337 : : uint32_t byte_off;
2338 : :
2339 [ # # ]: 0 : if (!cd->relaxed) {
2340 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_VERSION, inner)];
2341 : 0 : fc->item_idx = item_idx;
2342 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_version_set;
2343 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2344 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l3_type, inner);
2345 : :
2346 : : /* Overwrite - Unset ethertype if present */
2347 [ # # # # ]: 0 : memset(&cd->fc[DR_CALC_FNAME(ETH_TYPE, inner)], 0, sizeof(*fc));
2348 : :
2349 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2350 [ # # ]: 0 : if (!fc->tag_set) {
2351 : 0 : fc->item_idx = item_idx;
2352 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_routing_hdr_set;
2353 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2354 : 0 : fc->not_overwrite = 1;
2355 [ # # ]: 0 : DR_CALC_SET(fc, eth_l3, protocol_next_header, inner);
2356 : : }
2357 : : } else {
2358 : 0 : rte_errno = ENOTSUP;
2359 : 0 : return rte_errno;
2360 : : }
2361 : :
2362 [ # # ]: 0 : if (!m)
2363 : : return 0;
2364 : :
2365 [ # # # # ]: 0 : if (m->hdr.hdr_len || m->hdr.flags) {
2366 : 0 : rte_errno = ENOTSUP;
2367 : 0 : return rte_errno;
2368 : : }
2369 : :
2370 [ # # # # : 0 : if (m->hdr.next_hdr || m->hdr.type || m->hdr.segments_left) {
# # ]
2371 [ # # ]: 0 : byte_off = flow_hw_get_srh_flex_parser_byte_off_from_ctx(cd->ctx);
2372 : : fc = mlx5dr_definer_get_flex_parser_fc(cd, byte_off);
2373 : : if (!fc)
2374 : 0 : return rte_errno;
2375 : :
2376 : 0 : fc->item_idx = item_idx;
2377 : 0 : fc->tag_set = &mlx5dr_definer_ipv6_routing_ext_set;
2378 : : }
2379 : : return 0;
2380 : : }
2381 : :
2382 : : static int
2383 : 0 : mlx5dr_definer_conv_item_random(struct mlx5dr_definer_conv_data *cd,
2384 : : struct rte_flow_item *item,
2385 : : int item_idx)
2386 : : {
2387 : 0 : const struct rte_flow_item_random *m = item->mask;
2388 : 0 : const struct rte_flow_item_random *l = item->last;
2389 : : struct mlx5dr_definer_fc *fc;
2390 : :
2391 [ # # ]: 0 : if (!m)
2392 : : return 0;
2393 : :
2394 [ # # ]: 0 : if (m->value != (m->value & UINT16_MAX)) {
2395 : 0 : DR_LOG(ERR, "Random value is 16 bits only");
2396 : 0 : rte_errno = EINVAL;
2397 : 0 : return rte_errno;
2398 : : }
2399 : :
2400 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_RANDOM_NUM];
2401 : 0 : fc->item_idx = item_idx;
2402 : 0 : fc->tag_set = &mlx5dr_definer_random_number_set;
2403 [ # # # # ]: 0 : fc->is_range = l && l->value;
2404 : 0 : DR_CALC_SET_HDR(fc, random_number, random_number);
2405 : :
2406 : 0 : return 0;
2407 : : }
2408 : :
2409 : : static int
2410 : 0 : mlx5dr_definer_conv_item_geneve(struct mlx5dr_definer_conv_data *cd,
2411 : : struct rte_flow_item *item,
2412 : : int item_idx)
2413 : : {
2414 : 0 : const struct rte_flow_item_geneve *m = item->mask;
2415 : : struct mlx5dr_definer_fc *fc;
2416 : 0 : bool inner = cd->tunnel;
2417 : :
2418 [ # # ]: 0 : if (inner) {
2419 : 0 : DR_LOG(ERR, "Inner GENEVE item not supported");
2420 : 0 : rte_errno = ENOTSUP;
2421 : 0 : return rte_errno;
2422 : : }
2423 : :
2424 : : /* In order to match on Geneve we must match on ip_protocol and l4_dport */
2425 [ # # ]: 0 : if (!cd->relaxed) {
2426 : 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2427 [ # # ]: 0 : if (!fc->tag_set) {
2428 : 0 : fc->item_idx = item_idx;
2429 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2430 : 0 : fc->tag_set = &mlx5dr_definer_udp_protocol_set;
2431 : 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, inner);
2432 : : }
2433 : :
2434 : 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, inner)];
2435 [ # # ]: 0 : if (!fc->tag_set) {
2436 : 0 : fc->item_idx = item_idx;
2437 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2438 : 0 : fc->tag_set = &mlx5dr_definer_geneve_udp_port_set;
2439 : 0 : DR_CALC_SET(fc, eth_l4, destination_port, inner);
2440 : : }
2441 : : }
2442 : :
2443 [ # # ]: 0 : if (!m)
2444 : : return 0;
2445 : :
2446 [ # # ]: 0 : if (m->rsvd1) {
2447 : 0 : rte_errno = ENOTSUP;
2448 : 0 : return rte_errno;
2449 : : }
2450 : :
2451 [ # # ]: 0 : if (m->ver_opt_len_o_c_rsvd0) {
2452 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GENEVE_CTRL];
2453 : 0 : fc->item_idx = item_idx;
2454 : 0 : fc->tag_set = &mlx5dr_definer_geneve_ctrl_set;
2455 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
2456 : 0 : fc->bit_mask = __mlx5_mask(header_geneve, ver_opt_len_o_c_rsvd);
2457 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_geneve, ver_opt_len_o_c_rsvd);
2458 : : }
2459 : :
2460 [ # # ]: 0 : if (m->protocol) {
2461 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GENEVE_PROTO];
2462 : 0 : fc->item_idx = item_idx;
2463 : 0 : fc->tag_set = &mlx5dr_definer_geneve_protocol_set;
2464 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
2465 : 0 : fc->byte_off += MLX5_BYTE_OFF(header_geneve, protocol_type);
2466 : 0 : fc->bit_mask = __mlx5_mask(header_geneve, protocol_type);
2467 : : fc->bit_off = __mlx5_dw_bit_off(header_geneve, protocol_type);
2468 : : }
2469 : :
2470 [ # # ]: 0 : if (!is_mem_zero(m->vni, 3)) {
2471 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GENEVE_VNI];
2472 : 0 : fc->item_idx = item_idx;
2473 : 0 : fc->tag_set = &mlx5dr_definer_geneve_vni_set;
2474 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_1);
2475 : 0 : fc->bit_mask = __mlx5_mask(header_geneve, vni);
2476 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_geneve, vni);
2477 : : }
2478 : :
2479 : : return 0;
2480 : : }
2481 : :
2482 : : static int
2483 : 0 : mlx5dr_definer_conv_item_geneve_opt(struct mlx5dr_definer_conv_data *cd,
2484 : : struct rte_flow_item *item,
2485 : : int item_idx)
2486 : : {
2487 : 0 : const struct rte_flow_item_geneve_opt *m = item->mask;
2488 : 0 : const struct rte_flow_item_geneve_opt *v = item->spec;
2489 : : struct mlx5_hl_data *hl_ok_bit, *hl_dws;
2490 : : struct mlx5dr_definer_fc *fc;
2491 : : uint8_t num_of_dws, i;
2492 : : bool ok_bit_on_class;
2493 : : int ret;
2494 : :
2495 [ # # # # : 0 : if (!m || !(m->option_class || m->option_type || m->data))
# # ]
2496 : : return 0;
2497 : :
2498 [ # # # # ]: 0 : if (!v || m->option_type != 0xff) {
2499 : 0 : DR_LOG(ERR, "Cannot match geneve opt without valid opt type");
2500 : 0 : goto out_not_supp;
2501 : : }
2502 : :
2503 [ # # ]: 0 : if (m->option_class && m->option_class != RTE_BE16(UINT16_MAX)) {
2504 : 0 : DR_LOG(ERR, "Geneve option class has invalid mask");
2505 : 0 : goto out_not_supp;
2506 : : }
2507 : :
2508 : 0 : ret = mlx5_get_geneve_hl_data(cd->ctx,
2509 : 0 : v->option_type,
2510 : 0 : v->option_class,
2511 : : &hl_ok_bit,
2512 : : &num_of_dws,
2513 : : &hl_dws,
2514 : : &ok_bit_on_class);
2515 [ # # ]: 0 : if (ret) {
2516 : 0 : DR_LOG(ERR, "Geneve opt type and class %d not supported", v->option_type);
2517 : 0 : goto out_not_supp;
2518 : : }
2519 : :
2520 [ # # # # ]: 0 : if (!ok_bit_on_class && m->option_class) {
2521 : : /* DW0 is used, we will match type, class */
2522 [ # # # # ]: 0 : if (!num_of_dws || hl_dws[0].dw_mask != UINT32_MAX) {
2523 : 0 : DR_LOG(ERR, "Geneve opt type %d DW0 not supported", v->option_type);
2524 : 0 : goto out_not_supp;
2525 : : }
2526 : :
2527 [ # # ]: 0 : if (MLX5DR_DEFINER_FNAME_GENEVE_OPT_DW_0 + cd->geneve_opt_data_idx >
2528 : : MLX5DR_DEFINER_FNAME_GENEVE_OPT_DW_7) {
2529 : 0 : DR_LOG(ERR, "Max match geneve opt DWs reached");
2530 : 0 : goto out_not_supp;
2531 : : }
2532 : :
2533 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GENEVE_OPT_DW_0 + cd->geneve_opt_data_idx++];
2534 : 0 : fc->item_idx = item_idx;
2535 : 0 : fc->tag_set = &mlx5dr_definer_geneve_opt_ctrl_set;
2536 : 0 : fc->byte_off = hl_dws[0].dw_offset * DW_SIZE;
2537 : 0 : fc->bit_mask = UINT32_MAX;
2538 : : } else {
2539 : : /* DW0 is not used, we must verify geneve opt type exists in packet */
2540 [ # # ]: 0 : if (!hl_ok_bit->dw_mask) {
2541 : 0 : DR_LOG(ERR, "Geneve opt OK bits not supported");
2542 : 0 : goto out_not_supp;
2543 : : }
2544 : :
2545 [ # # ]: 0 : if (MLX5DR_DEFINER_FNAME_GENEVE_OPT_OK_0 + cd->geneve_opt_ok_idx >
2546 : : MLX5DR_DEFINER_FNAME_GENEVE_OPT_OK_7) {
2547 : 0 : DR_LOG(ERR, "Max match geneve opt reached");
2548 : 0 : goto out_not_supp;
2549 : : }
2550 : :
2551 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GENEVE_OPT_OK_0 + cd->geneve_opt_ok_idx++];
2552 : 0 : fc->item_idx = item_idx;
2553 : 0 : fc->tag_set = &mlx5dr_definer_ones_set;
2554 : 0 : fc->byte_off = hl_ok_bit->dw_offset * DW_SIZE +
2555 : 0 : __builtin_clz(hl_ok_bit->dw_mask) / 8;
2556 : 0 : fc->bit_off = __builtin_ctz(hl_ok_bit->dw_mask);
2557 : 0 : fc->bit_mask = 0x1;
2558 : : }
2559 : :
2560 [ # # ]: 0 : for (i = 1; i < num_of_dws; i++) {
2561 : : /* Process each valid geneve option data DW1..N */
2562 [ # # ]: 0 : if (!m->data[i - 1])
2563 : 0 : continue;
2564 : :
2565 [ # # ]: 0 : if (hl_dws[i].dw_mask != UINT32_MAX) {
2566 : 0 : DR_LOG(ERR, "Matching Geneve opt data[%d] not supported", i - 1);
2567 : 0 : goto out_not_supp;
2568 : : }
2569 : :
2570 [ # # ]: 0 : if (MLX5DR_DEFINER_FNAME_GENEVE_OPT_DW_0 + cd->geneve_opt_data_idx >
2571 : : MLX5DR_DEFINER_FNAME_GENEVE_OPT_DW_7) {
2572 : 0 : DR_LOG(ERR, "Max match geneve options DWs reached");
2573 : 0 : goto out_not_supp;
2574 : : }
2575 : :
2576 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_GENEVE_OPT_DW_0 + cd->geneve_opt_data_idx++];
2577 : 0 : fc->item_idx = item_idx;
2578 : 0 : fc->tag_set = &mlx5dr_definer_geneve_opt_data_set;
2579 : 0 : fc->byte_off = hl_dws[i].dw_offset * DW_SIZE;
2580 : 0 : fc->bit_mask = m->data[i - 1];
2581 : : /* Use extra_data for data[] set offset */
2582 : 0 : fc->extra_data = i - 1;
2583 : : }
2584 : :
2585 : : return 0;
2586 : :
2587 : 0 : out_not_supp:
2588 : 0 : rte_errno = ENOTSUP;
2589 : 0 : return rte_errno;
2590 : : }
2591 : :
2592 : : static int
2593 : 0 : mlx5dr_definer_mt_set_fc(struct mlx5dr_match_template *mt,
2594 : : struct mlx5dr_definer_fc *fc,
2595 : : uint8_t *hl)
2596 : : {
2597 : : uint32_t fc_sz = 0, fcr_sz = 0;
2598 : : int i;
2599 : :
2600 [ # # ]: 0 : for (i = 0; i < MLX5DR_DEFINER_FNAME_MAX; i++)
2601 [ # # ]: 0 : if (fc[i].tag_set)
2602 [ # # ]: 0 : fc[i].is_range ? fcr_sz++ : fc_sz++;
2603 : :
2604 : 0 : mt->fc = simple_calloc(fc_sz + fcr_sz, sizeof(*mt->fc));
2605 [ # # ]: 0 : if (!mt->fc) {
2606 : 0 : rte_errno = ENOMEM;
2607 : 0 : return rte_errno;
2608 : : }
2609 : :
2610 : 0 : mt->fcr = mt->fc + fc_sz;
2611 : :
2612 [ # # ]: 0 : for (i = 0; i < MLX5DR_DEFINER_FNAME_MAX; i++) {
2613 [ # # ]: 0 : if (!fc[i].tag_set)
2614 : 0 : continue;
2615 : :
2616 : 0 : fc[i].fname = i;
2617 : :
2618 [ # # ]: 0 : if (fc[i].is_range) {
2619 : 0 : memcpy(&mt->fcr[mt->fcr_sz++], &fc[i], sizeof(*mt->fcr));
2620 : : } else {
2621 [ # # ]: 0 : memcpy(&mt->fc[mt->fc_sz++], &fc[i], sizeof(*mt->fc));
2622 [ # # # # : 0 : DR_SET(hl, -1, fc[i].byte_off, fc[i].bit_off, fc[i].bit_mask);
# # # # ]
2623 : : }
2624 : : }
2625 : :
2626 : : return 0;
2627 : : }
2628 : :
2629 : : static int
2630 : 0 : mlx5dr_definer_check_item_range_supp(struct rte_flow_item *item)
2631 : : {
2632 [ # # ]: 0 : if (!item->last)
2633 : : return 0;
2634 : :
2635 [ # # ]: 0 : switch ((int)item->type) {
2636 : : case RTE_FLOW_ITEM_TYPE_IPV4:
2637 : : case RTE_FLOW_ITEM_TYPE_IPV6:
2638 : : case RTE_FLOW_ITEM_TYPE_UDP:
2639 : : case RTE_FLOW_ITEM_TYPE_TCP:
2640 : : case RTE_FLOW_ITEM_TYPE_TAG:
2641 : : case RTE_FLOW_ITEM_TYPE_META:
2642 : : case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
2643 : : case RTE_FLOW_ITEM_TYPE_RANDOM:
2644 : : return 0;
2645 : 0 : default:
2646 : 0 : DR_LOG(ERR, "Range not supported over item type %d", item->type);
2647 : 0 : rte_errno = ENOTSUP;
2648 : 0 : return rte_errno;
2649 : : }
2650 : : }
2651 : :
2652 : : static int
2653 : 0 : mlx5dr_definer_conv_item_esp(struct mlx5dr_definer_conv_data *cd,
2654 : : struct rte_flow_item *item,
2655 : : int item_idx)
2656 : : {
2657 : 0 : const struct rte_flow_item_esp *m = item->mask;
2658 : : struct mlx5dr_definer_fc *fc;
2659 : :
2660 [ # # ]: 0 : if (!m)
2661 : : return 0;
2662 [ # # ]: 0 : if (m->hdr.spi) {
2663 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ESP_SPI];
2664 : 0 : fc->item_idx = item_idx;
2665 : 0 : fc->tag_set = &mlx5dr_definer_ipsec_spi_set;
2666 : 0 : DR_CALC_SET_HDR(fc, ipsec, spi);
2667 : : }
2668 [ # # ]: 0 : if (m->hdr.seq) {
2669 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ESP_SEQUENCE_NUMBER];
2670 : 0 : fc->item_idx = item_idx;
2671 : 0 : fc->tag_set = &mlx5dr_definer_ipsec_sequence_number_set;
2672 : 0 : DR_CALC_SET_HDR(fc, ipsec, sequence_number);
2673 : : }
2674 : : return 0;
2675 : : }
2676 : :
2677 : : static void mlx5dr_definer_set_conv_tunnel(enum rte_flow_item_type cur_type,
2678 : : uint64_t item_flags,
2679 : : struct mlx5dr_definer_conv_data *cd)
2680 : : {
2681 : : /* Already tunnel nothing to change */
2682 [ # # ]: 0 : if (cd->tunnel)
2683 : : return;
2684 : :
2685 : : /* We can have more than one MPLS label at each level (inner/outer), so
2686 : : * consider tunnel only when it is already under tunnel or if we moved to the
2687 : : * second MPLS level.
2688 : : */
2689 [ # # ]: 0 : if (cur_type != RTE_FLOW_ITEM_TYPE_MPLS)
2690 : 0 : cd->tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
2691 : : else
2692 : 0 : cd->tunnel = !!(item_flags & DR_FLOW_LAYER_TUNNEL_NO_MPLS);
2693 : : }
2694 : :
2695 : : static int
2696 : 0 : mlx5dr_definer_conv_item_flex_parser(struct mlx5dr_definer_conv_data *cd,
2697 : : struct rte_flow_item *item,
2698 : : int item_idx)
2699 : : {
2700 : : uint32_t base_off = MLX5_BYTE_OFF(definer_hl, flex_parser.flex_parser_0);
2701 : : const struct rte_flow_item_flex *v, *m;
2702 : : enum mlx5dr_definer_fname fname;
2703 : : struct mlx5dr_definer_fc *fc;
2704 : : uint32_t i, mask, byte_off;
2705 : 0 : bool is_inner = cd->tunnel;
2706 : : int ret;
2707 : :
2708 : 0 : m = item->mask;
2709 : 0 : v = item->spec;
2710 : 0 : mask = 0;
2711 [ # # ]: 0 : for (i = 0; i < MLX5_GRAPH_NODE_SAMPLE_NUM; i++) {
2712 : 0 : byte_off = base_off - i * sizeof(uint32_t);
2713 : 0 : ret = mlx5_flex_get_parser_value_per_byte_off(m, v->handle, byte_off,
2714 : : true, is_inner, &mask);
2715 [ # # ]: 0 : if (ret == -1) {
2716 : 0 : rte_errno = EINVAL;
2717 : 0 : return rte_errno;
2718 : : }
2719 : :
2720 [ # # ]: 0 : if (!mask)
2721 : 0 : continue;
2722 : :
2723 : : fname = MLX5DR_DEFINER_FNAME_FLEX_PARSER_0;
2724 : 0 : fname += (enum mlx5dr_definer_fname)i;
2725 : 0 : fc = &cd->fc[fname];
2726 : 0 : fc->byte_off = byte_off;
2727 : 0 : fc->item_idx = item_idx;
2728 [ # # ]: 0 : fc->tag_set = cd->tunnel ? &mlx5dr_definer_flex_parser_inner_set :
2729 : : &mlx5dr_definer_flex_parser_outer_set;
2730 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2731 : 0 : fc->bit_mask = mask;
2732 : : }
2733 : : return 0;
2734 : : }
2735 : :
2736 : : static int
2737 : 0 : mlx5dr_definer_conv_item_ib_l4(struct mlx5dr_definer_conv_data *cd,
2738 : : struct rte_flow_item *item,
2739 : : int item_idx)
2740 : : {
2741 : 0 : const struct rte_flow_item_ib_bth *m = item->mask;
2742 : : struct mlx5dr_definer_fc *fc;
2743 : 0 : bool inner = cd->tunnel;
2744 : :
2745 : : /* In order to match on RoCEv2(layer4 ib), we must match
2746 : : * on ip_protocol and l4_dport.
2747 : : */
2748 [ # # ]: 0 : if (!cd->relaxed) {
2749 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2750 [ # # ]: 0 : if (!fc->tag_set) {
2751 : 0 : fc->item_idx = item_idx;
2752 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2753 : 0 : fc->tag_set = &mlx5dr_definer_udp_protocol_set;
2754 [ # # ]: 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, inner);
2755 : : }
2756 : :
2757 [ # # ]: 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, inner)];
2758 [ # # ]: 0 : if (!fc->tag_set) {
2759 : 0 : fc->item_idx = item_idx;
2760 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2761 : 0 : fc->tag_set = &mlx5dr_definer_ib_l4_udp_port_set;
2762 [ # # ]: 0 : DR_CALC_SET(fc, eth_l4, destination_port, inner);
2763 : : }
2764 : : }
2765 : :
2766 [ # # ]: 0 : if (!m)
2767 : : return 0;
2768 : :
2769 [ # # ]: 0 : if (m->hdr.se || m->hdr.m || m->hdr.padcnt || m->hdr.tver ||
2770 [ # # # # : 0 : m->hdr.pkey || m->hdr.f || m->hdr.b || m->hdr.rsvd0 ||
# # ]
2771 [ # # ]: 0 : m->hdr.rsvd1 || !is_mem_zero(m->hdr.psn, 3)) {
2772 : 0 : rte_errno = ENOTSUP;
2773 : 0 : return rte_errno;
2774 : : }
2775 : :
2776 [ # # ]: 0 : if (m->hdr.opcode) {
2777 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_IB_L4_OPCODE];
2778 : 0 : fc->item_idx = item_idx;
2779 : 0 : fc->tag_set = &mlx5dr_definer_ib_l4_opcode_set;
2780 : 0 : DR_CALC_SET_HDR(fc, ib_l4, opcode);
2781 : : }
2782 : :
2783 [ # # ]: 0 : if (!is_mem_zero(m->hdr.dst_qp, 3)) {
2784 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_IB_L4_QPN];
2785 : 0 : fc->item_idx = item_idx;
2786 : 0 : fc->tag_set = &mlx5dr_definer_ib_l4_qp_set;
2787 : 0 : DR_CALC_SET_HDR(fc, ib_l4, qp);
2788 : : }
2789 : :
2790 [ # # ]: 0 : if (m->hdr.a) {
2791 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_IB_L4_A];
2792 : 0 : fc->item_idx = item_idx;
2793 : 0 : fc->tag_set = &mlx5dr_definer_ib_l4_bth_a_set;
2794 : 0 : DR_CALC_SET_HDR(fc, ib_l4, ackreq);
2795 : : }
2796 : :
2797 : : return 0;
2798 : : }
2799 : :
2800 : : static int
2801 : 0 : mlx5dr_definer_conv_item_vxlan_gpe(struct mlx5dr_definer_conv_data *cd,
2802 : : struct rte_flow_item *item,
2803 : : int item_idx)
2804 : : {
2805 : 0 : const struct rte_flow_item_vxlan_gpe *m = item->mask;
2806 : : struct mlx5dr_definer_fc *fc;
2807 : 0 : bool inner = cd->tunnel;
2808 : :
2809 [ # # ]: 0 : if (inner) {
2810 : 0 : DR_LOG(ERR, "Inner VXLAN GPE item not supported");
2811 : 0 : rte_errno = ENOTSUP;
2812 : 0 : return rte_errno;
2813 : : }
2814 : :
2815 : : /* In order to match on VXLAN GPE we must match on ip_protocol and l4_dport */
2816 [ # # ]: 0 : if (!cd->relaxed) {
2817 : 0 : fc = &cd->fc[DR_CALC_FNAME(IP_PROTOCOL, inner)];
2818 [ # # ]: 0 : if (!fc->tag_set) {
2819 : 0 : fc->item_idx = item_idx;
2820 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2821 : 0 : fc->tag_set = &mlx5dr_definer_udp_protocol_set;
2822 : 0 : DR_CALC_SET(fc, eth_l2, l4_type_bwc, inner);
2823 : : }
2824 : :
2825 : 0 : fc = &cd->fc[DR_CALC_FNAME(L4_DPORT, inner)];
2826 [ # # ]: 0 : if (!fc->tag_set) {
2827 : 0 : fc->item_idx = item_idx;
2828 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2829 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_gpe_udp_port_set;
2830 : 0 : DR_CALC_SET(fc, eth_l4, destination_port, inner);
2831 : : }
2832 : : }
2833 : :
2834 [ # # ]: 0 : if (!m)
2835 : : return 0;
2836 : :
2837 [ # # ]: 0 : if (m->flags) {
2838 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_GPE_FLAGS];
2839 : 0 : fc->item_idx = item_idx;
2840 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_gpe_flags_set;
2841 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
2842 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan_gpe, flags);
2843 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, flags);
2844 : : }
2845 : :
2846 [ # # ]: 0 : if (!is_mem_zero(m->rsvd0, 2)) {
2847 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_GPE_RSVD0];
2848 : 0 : fc->item_idx = item_idx;
2849 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_gpe_rsvd0_set;
2850 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
2851 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan_gpe, rsvd0);
2852 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, rsvd0);
2853 : : }
2854 : :
2855 [ # # ]: 0 : if (m->protocol) {
2856 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_GPE_PROTO];
2857 : 0 : fc->item_idx = item_idx;
2858 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_gpe_protocol_set;
2859 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_0);
2860 : 0 : fc->byte_off += MLX5_BYTE_OFF(header_vxlan_gpe, protocol);
2861 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan_gpe, protocol);
2862 : : fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, protocol);
2863 : : }
2864 : :
2865 [ # # ]: 0 : if (!is_mem_zero(m->vni, 3)) {
2866 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_GPE_VNI];
2867 : 0 : fc->item_idx = item_idx;
2868 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_gpe_vni_set;
2869 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_1);
2870 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan_gpe, vni);
2871 : 0 : fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, vni);
2872 : : }
2873 : :
2874 [ # # ]: 0 : if (m->rsvd1) {
2875 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_VXLAN_GPE_RSVD1];
2876 : 0 : fc->item_idx = item_idx;
2877 : 0 : fc->tag_set = &mlx5dr_definer_vxlan_gpe_rsvd1_set;
2878 : 0 : DR_CALC_SET_HDR(fc, tunnel_header, tunnel_header_1);
2879 : 0 : fc->bit_mask = __mlx5_mask(header_vxlan_gpe, rsvd1);
2880 : : fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, rsvd1);
2881 : : }
2882 : :
2883 : : return 0;
2884 : : }
2885 : :
2886 : : static int
2887 : 0 : mlx5dr_definer_conv_item_compare_field(const struct rte_flow_field_data *f,
2888 : : const struct rte_flow_field_data *other_f,
2889 : : struct mlx5dr_definer_conv_data *cd,
2890 : : int item_idx,
2891 : : enum mlx5dr_table_type table_domain_type,
2892 : : enum mlx5dr_definer_compare_dw_selectors dw_offset)
2893 : : {
2894 : : struct mlx5dr_definer_fc *fc = NULL;
2895 : : int reg;
2896 : :
2897 [ # # ]: 0 : if (f->offset) {
2898 : 0 : DR_LOG(ERR, "field offset %u is not supported, only offset zero supported",
2899 : : f->offset);
2900 : 0 : goto err_notsup;
2901 : : }
2902 : :
2903 [ # # # # : 0 : switch (f->field) {
# # ]
2904 : 0 : case RTE_FLOW_FIELD_META:
2905 : 0 : reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
2906 : : RTE_FLOW_ITEM_TYPE_META,
2907 : : table_domain_type, -1);
2908 : : if (reg <= 0) {
2909 : 0 : DR_LOG(ERR, "Invalid register for compare metadata field");
2910 : 0 : rte_errno = EINVAL;
2911 : 0 : return rte_errno;
2912 : : }
2913 : :
2914 : 0 : fc = mlx5dr_definer_get_register_fc(cd, reg);
2915 [ # # ]: 0 : if (!fc)
2916 : 0 : return rte_errno;
2917 : :
2918 : 0 : fc->item_idx = item_idx;
2919 : 0 : fc->tag_set = &mlx5dr_definer_compare_set;
2920 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2921 : 0 : fc->compare_idx = dw_offset;
2922 : 0 : break;
2923 : 0 : case RTE_FLOW_FIELD_TAG:
2924 : 0 : reg = flow_hw_get_reg_id_from_ctx(cd->ctx,
2925 : : RTE_FLOW_ITEM_TYPE_TAG,
2926 : : MLX5DR_TABLE_TYPE_DONTCARE,
2927 : 0 : f->tag_index);
2928 [ # # ]: 0 : if (reg <= 0) {
2929 : 0 : DR_LOG(ERR, "Invalid register for compare tag field");
2930 : 0 : rte_errno = EINVAL;
2931 : 0 : return rte_errno;
2932 : : }
2933 : :
2934 : 0 : fc = mlx5dr_definer_get_register_fc(cd, reg);
2935 [ # # ]: 0 : if (!fc)
2936 : 0 : return rte_errno;
2937 : :
2938 : 0 : fc->item_idx = item_idx;
2939 : 0 : fc->tag_set = &mlx5dr_definer_compare_set;
2940 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2941 : 0 : fc->compare_idx = dw_offset;
2942 : 0 : break;
2943 : 0 : case RTE_FLOW_FIELD_VALUE:
2944 [ # # ]: 0 : if (dw_offset == MLX5DR_DEFINER_COMPARE_ARGUMENT_0) {
2945 : 0 : DR_LOG(ERR, "Argument field does not support immediate value");
2946 : 0 : goto err_notsup;
2947 : : }
2948 : : break;
2949 : 0 : case RTE_FLOW_FIELD_RANDOM:
2950 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_RANDOM_NUM];
2951 : 0 : fc->item_idx = item_idx;
2952 : 0 : fc->tag_set = &mlx5dr_definer_compare_set;
2953 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2954 : 0 : fc->compare_idx = dw_offset;
2955 : 0 : DR_CALC_SET_HDR(fc, random_number, random_number);
2956 : 0 : break;
2957 : 0 : case RTE_FLOW_FIELD_ESP_SEQ_NUM:
2958 : 0 : fc = &cd->fc[MLX5DR_DEFINER_FNAME_ESP_SEQUENCE_NUMBER];
2959 : 0 : fc->item_idx = item_idx;
2960 : 0 : fc->tag_set = &mlx5dr_definer_compare_set;
2961 : 0 : fc->tag_mask_set = &mlx5dr_definer_ones_set;
2962 : 0 : fc->compare_idx = dw_offset;
2963 : 0 : DR_CALC_SET_HDR(fc, ipsec, sequence_number);
2964 : 0 : break;
2965 : 0 : default:
2966 : 0 : DR_LOG(ERR, "%u field is not supported", f->field);
2967 : 0 : goto err_notsup;
2968 : : }
2969 : :
2970 [ # # # # ]: 0 : if (fc && other_f && other_f->field == RTE_FLOW_FIELD_VALUE)
2971 : 0 : fc->compare_set_base = true;
2972 : :
2973 : : return 0;
2974 : :
2975 : 0 : err_notsup:
2976 : 0 : rte_errno = ENOTSUP;
2977 : 0 : return rte_errno;
2978 : : }
2979 : :
2980 : : static int
2981 : 0 : mlx5dr_definer_conv_item_compare(struct mlx5dr_definer_conv_data *cd,
2982 : : enum mlx5dr_table_type table_domain_type,
2983 : : struct rte_flow_item *item,
2984 : : int item_idx)
2985 : : {
2986 : 0 : const struct rte_flow_item_compare *m = item->mask;
2987 : 0 : const struct rte_flow_field_data *a = &m->a;
2988 : 0 : const struct rte_flow_field_data *b = &m->b;
2989 : : int ret;
2990 : :
2991 [ # # ]: 0 : if (m->width != 0xffffffff) {
2992 : 0 : DR_LOG(ERR, "compare item width of 0x%x is not supported, only full DW supported",
2993 : : m->width);
2994 : 0 : rte_errno = ENOTSUP;
2995 : 0 : return rte_errno;
2996 : : }
2997 : :
2998 : 0 : ret = mlx5dr_definer_conv_item_compare_field(a, b, cd, item_idx,
2999 : : table_domain_type,
3000 : : MLX5DR_DEFINER_COMPARE_ARGUMENT_0);
3001 [ # # ]: 0 : if (ret)
3002 : : return ret;
3003 : :
3004 : 0 : ret = mlx5dr_definer_conv_item_compare_field(b, NULL, cd, item_idx,
3005 : : table_domain_type,
3006 : : MLX5DR_DEFINER_COMPARE_BASE_0);
3007 [ # # ]: 0 : if (ret)
3008 : 0 : return ret;
3009 : :
3010 : : return 0;
3011 : : }
3012 : :
3013 : : static int
3014 : 0 : mlx5dr_definer_conv_items_to_hl(struct mlx5dr_context *ctx,
3015 : : struct mlx5dr_match_template *mt,
3016 : : uint8_t *hl,
3017 : : struct mlx5dr_matcher *matcher)
3018 : : {
3019 : 0 : struct mlx5dr_definer_fc fc[MLX5DR_DEFINER_FNAME_MAX] = {{0}};
3020 : 0 : struct mlx5dr_definer_conv_data cd = {0};
3021 : 0 : struct rte_flow_item *items = mt->items;
3022 : : uint64_t item_flags = 0;
3023 : : int i, ret;
3024 : :
3025 : 0 : cd.fc = fc;
3026 : 0 : cd.ctx = ctx;
3027 : 0 : cd.relaxed = mt->flags & MLX5DR_MATCH_TEMPLATE_FLAG_RELAXED_MATCH;
3028 : :
3029 : : /* Collect all RTE fields to the field array and set header layout */
3030 [ # # ]: 0 : for (i = 0; items->type != RTE_FLOW_ITEM_TYPE_END; i++, items++) {
3031 : : mlx5dr_definer_set_conv_tunnel(items->type, item_flags, &cd);
3032 : :
3033 : 0 : ret = mlx5dr_definer_check_item_range_supp(items);
3034 [ # # ]: 0 : if (ret)
3035 : 0 : return ret;
3036 : :
3037 [ # # ]: 0 : if (mlx5dr_matcher_is_compare(matcher)) {
3038 : 0 : DR_LOG(ERR, "Compare matcher not supported for more than one item");
3039 : 0 : goto not_supp;
3040 : : }
3041 : :
3042 [ # # # # : 0 : switch ((int)items->type) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
3043 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
3044 : 0 : ret = mlx5dr_definer_conv_item_eth(&cd, items, i);
3045 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
3046 : : MLX5_FLOW_LAYER_OUTER_L2;
3047 : 0 : break;
3048 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
3049 : 0 : ret = mlx5dr_definer_conv_item_vlan(&cd, items, i);
3050 : 0 : item_flags |= cd.tunnel ?
3051 [ # # ]: 0 : (MLX5_FLOW_LAYER_INNER_VLAN | MLX5_FLOW_LAYER_INNER_L2) :
3052 : : (MLX5_FLOW_LAYER_OUTER_VLAN | MLX5_FLOW_LAYER_OUTER_L2);
3053 : 0 : break;
3054 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
3055 : 0 : ret = mlx5dr_definer_conv_item_ipv4(&cd, items, i);
3056 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
3057 : : MLX5_FLOW_LAYER_OUTER_L3_IPV4;
3058 : 0 : break;
3059 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
3060 : 0 : ret = mlx5dr_definer_conv_item_ipv6(&cd, items, i);
3061 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
3062 : : MLX5_FLOW_LAYER_OUTER_L3_IPV6;
3063 : 0 : break;
3064 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
3065 : 0 : ret = mlx5dr_definer_conv_item_udp(&cd, items, i);
3066 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
3067 : : MLX5_FLOW_LAYER_OUTER_L4_UDP;
3068 : 0 : break;
3069 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
3070 : 0 : ret = mlx5dr_definer_conv_item_tcp(&cd, items, i);
3071 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
3072 : : MLX5_FLOW_LAYER_OUTER_L4_TCP;
3073 : 0 : break;
3074 : 0 : case RTE_FLOW_ITEM_TYPE_GTP:
3075 : 0 : ret = mlx5dr_definer_conv_item_gtp(&cd, items, i);
3076 : 0 : item_flags |= MLX5_FLOW_LAYER_GTP;
3077 : 0 : break;
3078 : 0 : case RTE_FLOW_ITEM_TYPE_GTP_PSC:
3079 : 0 : ret = mlx5dr_definer_conv_item_gtp_psc(&cd, items, i);
3080 : 0 : item_flags |= MLX5_FLOW_LAYER_GTP_PSC;
3081 : 0 : break;
3082 : 0 : case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
3083 : 0 : ret = mlx5dr_definer_conv_item_port(&cd, items, i);
3084 : 0 : item_flags |= MLX5_FLOW_ITEM_REPRESENTED_PORT;
3085 : 0 : mt->vport_item_id = i;
3086 : 0 : break;
3087 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
3088 : 0 : ret = mlx5dr_definer_conv_item_vxlan(&cd, items, i);
3089 : 0 : item_flags |= MLX5_FLOW_LAYER_VXLAN;
3090 : 0 : break;
3091 : : case MLX5_RTE_FLOW_ITEM_TYPE_SQ:
3092 : : ret = mlx5dr_definer_conv_item_sq(&cd, items, i);
3093 : 0 : item_flags |= MLX5_FLOW_ITEM_SQ;
3094 : 0 : break;
3095 : 0 : case RTE_FLOW_ITEM_TYPE_TAG:
3096 : : case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
3097 : 0 : ret = mlx5dr_definer_conv_item_tag(&cd, items, i);
3098 : 0 : item_flags |= MLX5_FLOW_ITEM_TAG;
3099 : 0 : break;
3100 : 0 : case RTE_FLOW_ITEM_TYPE_META:
3101 : 0 : ret = mlx5dr_definer_conv_item_metadata(&cd, matcher->tbl->type, items, i);
3102 : 0 : item_flags |= MLX5_FLOW_ITEM_METADATA;
3103 : 0 : break;
3104 : 0 : case RTE_FLOW_ITEM_TYPE_GRE:
3105 : 0 : ret = mlx5dr_definer_conv_item_gre(&cd, items, i);
3106 : 0 : item_flags |= MLX5_FLOW_LAYER_GRE;
3107 : 0 : break;
3108 : 0 : case RTE_FLOW_ITEM_TYPE_GRE_OPTION:
3109 : 0 : ret = mlx5dr_definer_conv_item_gre_opt(&cd, items, i);
3110 : 0 : item_flags |= MLX5_FLOW_LAYER_GRE;
3111 : 0 : break;
3112 : 0 : case RTE_FLOW_ITEM_TYPE_GRE_KEY:
3113 : 0 : ret = mlx5dr_definer_conv_item_gre_key(&cd, items, i);
3114 : 0 : item_flags |= MLX5_FLOW_LAYER_GRE_KEY;
3115 : 0 : break;
3116 : 0 : case RTE_FLOW_ITEM_TYPE_INTEGRITY:
3117 : 0 : ret = mlx5dr_definer_conv_item_integrity(&cd, items, i);
3118 : 0 : item_flags |= MLX5_FLOW_ITEM_INTEGRITY;
3119 : 0 : break;
3120 : 0 : case RTE_FLOW_ITEM_TYPE_CONNTRACK:
3121 : 0 : ret = mlx5dr_definer_conv_item_conntrack(&cd, items, i);
3122 : 0 : break;
3123 : 0 : case RTE_FLOW_ITEM_TYPE_ICMP:
3124 : 0 : ret = mlx5dr_definer_conv_item_icmp(&cd, items, i);
3125 : 0 : item_flags |= MLX5_FLOW_LAYER_ICMP;
3126 : 0 : break;
3127 : 0 : case RTE_FLOW_ITEM_TYPE_ICMP6:
3128 : 0 : ret = mlx5dr_definer_conv_item_icmp6(&cd, items, i);
3129 : 0 : item_flags |= MLX5_FLOW_LAYER_ICMP6;
3130 : 0 : break;
3131 : 0 : case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REQUEST:
3132 : : case RTE_FLOW_ITEM_TYPE_ICMP6_ECHO_REPLY:
3133 : 0 : ret = mlx5dr_definer_conv_item_icmp6_echo(&cd, items, i);
3134 : 0 : item_flags |= MLX5_FLOW_LAYER_ICMP6;
3135 : 0 : break;
3136 : 0 : case RTE_FLOW_ITEM_TYPE_METER_COLOR:
3137 : 0 : ret = mlx5dr_definer_conv_item_meter_color(&cd, items, i);
3138 : 0 : item_flags |= MLX5_FLOW_ITEM_METER_COLOR;
3139 : 0 : break;
3140 : 0 : case RTE_FLOW_ITEM_TYPE_QUOTA:
3141 : 0 : ret = mlx5dr_definer_conv_item_quota(&cd, items, i);
3142 : 0 : item_flags |= MLX5_FLOW_ITEM_QUOTA;
3143 : 0 : break;
3144 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT:
3145 : 0 : ret = mlx5dr_definer_conv_item_ipv6_routing_ext(&cd, items, i);
3146 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_ITEM_INNER_IPV6_ROUTING_EXT :
3147 : : MLX5_FLOW_ITEM_OUTER_IPV6_ROUTING_EXT;
3148 : 0 : break;
3149 : 0 : case RTE_FLOW_ITEM_TYPE_ESP:
3150 : 0 : ret = mlx5dr_definer_conv_item_esp(&cd, items, i);
3151 : 0 : item_flags |= MLX5_FLOW_ITEM_ESP;
3152 : 0 : break;
3153 : 0 : case RTE_FLOW_ITEM_TYPE_FLEX:
3154 : 0 : ret = mlx5dr_definer_conv_item_flex_parser(&cd, items, i);
3155 [ # # ]: 0 : item_flags |= cd.tunnel ? MLX5_FLOW_ITEM_INNER_FLEX :
3156 : : MLX5_FLOW_ITEM_OUTER_FLEX;
3157 : 0 : break;
3158 : 0 : case RTE_FLOW_ITEM_TYPE_MPLS:
3159 : 0 : ret = mlx5dr_definer_conv_item_mpls(&cd, items, i);
3160 : 0 : item_flags |= MLX5_FLOW_LAYER_MPLS;
3161 : 0 : cd.mpls_idx++;
3162 : 0 : break;
3163 : 0 : case RTE_FLOW_ITEM_TYPE_GENEVE:
3164 : 0 : ret = mlx5dr_definer_conv_item_geneve(&cd, items, i);
3165 : 0 : item_flags |= MLX5_FLOW_LAYER_GENEVE;
3166 : 0 : break;
3167 : 0 : case RTE_FLOW_ITEM_TYPE_GENEVE_OPT:
3168 : 0 : ret = mlx5dr_definer_conv_item_geneve_opt(&cd, items, i);
3169 : 0 : item_flags |= MLX5_FLOW_LAYER_GENEVE_OPT;
3170 : 0 : break;
3171 : 0 : case RTE_FLOW_ITEM_TYPE_IB_BTH:
3172 : 0 : ret = mlx5dr_definer_conv_item_ib_l4(&cd, items, i);
3173 : 0 : item_flags |= MLX5_FLOW_ITEM_IB_BTH;
3174 : 0 : break;
3175 : 0 : case RTE_FLOW_ITEM_TYPE_PTYPE:
3176 : 0 : ret = mlx5dr_definer_conv_item_ptype(&cd, items, i);
3177 : 0 : item_flags |= MLX5_FLOW_ITEM_PTYPE;
3178 : 0 : break;
3179 : 0 : case RTE_FLOW_ITEM_TYPE_RANDOM:
3180 : 0 : ret = mlx5dr_definer_conv_item_random(&cd, items, i);
3181 : 0 : item_flags |= MLX5_FLOW_ITEM_RANDOM;
3182 : 0 : break;
3183 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
3184 : 0 : ret = mlx5dr_definer_conv_item_vxlan_gpe(&cd, items, i);
3185 : 0 : item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
3186 : 0 : break;
3187 : 0 : case RTE_FLOW_ITEM_TYPE_COMPARE:
3188 [ # # ]: 0 : if (i) {
3189 : 0 : DR_LOG(ERR, "Compare matcher not supported for more than one item");
3190 : 0 : goto not_supp;
3191 : : }
3192 : 0 : ret = mlx5dr_definer_conv_item_compare(&cd, matcher->tbl->type, items, i);
3193 : 0 : item_flags |= MLX5_FLOW_ITEM_COMPARE;
3194 : 0 : matcher->flags |= MLX5DR_MATCHER_FLAGS_COMPARE;
3195 : 0 : break;
3196 : : case RTE_FLOW_ITEM_TYPE_VOID:
3197 : : break;
3198 : 0 : default:
3199 : 0 : DR_LOG(ERR, "Unsupported item type %d", items->type);
3200 : 0 : goto not_supp;
3201 : : }
3202 : :
3203 : 0 : cd.last_item = items->type;
3204 : :
3205 [ # # ]: 0 : if (ret) {
3206 : 0 : DR_LOG(ERR, "Failed processing item type: %d", items->type);
3207 : 0 : return ret;
3208 : : }
3209 : : }
3210 : :
3211 : 0 : mt->item_flags = item_flags;
3212 : :
3213 : : /* Fill in headers layout and allocate fc & fcr array on mt */
3214 : 0 : ret = mlx5dr_definer_mt_set_fc(mt, fc, hl);
3215 [ # # ]: 0 : if (ret) {
3216 : 0 : DR_LOG(ERR, "Failed to set field copy to match template");
3217 : 0 : return ret;
3218 : : }
3219 : :
3220 : : return 0;
3221 : :
3222 : 0 : not_supp:
3223 : 0 : rte_errno = ENOTSUP;
3224 : 0 : return rte_errno;
3225 : : }
3226 : :
3227 : : static int
3228 [ # # ]: 0 : mlx5dr_definer_find_byte_in_tag(struct mlx5dr_definer *definer,
3229 : : uint32_t hl_byte_off,
3230 : : uint32_t *tag_byte_off)
3231 : : {
3232 : : uint8_t byte_offset;
3233 : : int i, dw_to_scan;
3234 : :
3235 : : /* Avoid accessing unused DW selectors */
3236 : : dw_to_scan = mlx5dr_definer_is_jumbo(definer) ?
3237 [ # # ]: 0 : DW_SELECTORS : DW_SELECTORS_MATCH;
3238 : :
3239 : : /* Add offset since each DW covers multiple BYTEs */
3240 : 0 : byte_offset = hl_byte_off % DW_SIZE;
3241 [ # # ]: 0 : for (i = 0; i < dw_to_scan; i++) {
3242 [ # # ]: 0 : if (definer->dw_selector[i] == hl_byte_off / DW_SIZE) {
3243 : 0 : *tag_byte_off = byte_offset + DW_SIZE * (DW_SELECTORS - i - 1);
3244 : 0 : return 0;
3245 : : }
3246 : : }
3247 : :
3248 : : /* Add offset to skip DWs in definer */
3249 : : byte_offset = DW_SIZE * DW_SELECTORS;
3250 : : /* Iterate in reverse since the code uses bytes from 7 -> 0 */
3251 [ # # ]: 0 : for (i = BYTE_SELECTORS; i-- > 0 ;) {
3252 [ # # ]: 0 : if (definer->byte_selector[i] == hl_byte_off) {
3253 : 0 : *tag_byte_off = byte_offset + (BYTE_SELECTORS - i - 1);
3254 : 0 : return 0;
3255 : : }
3256 : : }
3257 : :
3258 : : /* The hl byte offset must be part of the definer */
3259 : 0 : DR_LOG(INFO, "Failed to map to definer, HL byte [%d] not found", byte_offset);
3260 : 0 : rte_errno = EINVAL;
3261 : 0 : return rte_errno;
3262 : : }
3263 : :
3264 : : static int
3265 : 0 : mlx5dr_definer_fc_bind(struct mlx5dr_definer *definer,
3266 : : struct mlx5dr_definer_fc *fc,
3267 : : uint32_t fc_sz)
3268 : : {
3269 : 0 : uint32_t tag_offset = 0;
3270 : : int ret, byte_diff;
3271 : : uint32_t i;
3272 : :
3273 [ # # ]: 0 : for (i = 0; i < fc_sz; i++) {
3274 : : /* Map header layout byte offset to byte offset in tag */
3275 : 0 : ret = mlx5dr_definer_find_byte_in_tag(definer, fc->byte_off, &tag_offset);
3276 [ # # ]: 0 : if (ret)
3277 : 0 : return ret;
3278 : :
3279 : : /* Move setter based on the location in the definer */
3280 : 0 : byte_diff = fc->byte_off % DW_SIZE - tag_offset % DW_SIZE;
3281 : 0 : fc->bit_off = fc->bit_off + byte_diff * BITS_IN_BYTE;
3282 : :
3283 : : /* Update offset in headers layout to offset in tag */
3284 : 0 : fc->byte_off = tag_offset;
3285 : 0 : fc++;
3286 : : }
3287 : :
3288 : : return 0;
3289 : : }
3290 : :
3291 : : static bool
3292 : 0 : mlx5dr_definer_best_hl_fit_recu(struct mlx5dr_definer_sel_ctrl *ctrl,
3293 : : uint32_t cur_dw,
3294 : : uint32_t *data)
3295 : : {
3296 : : uint8_t bytes_set;
3297 : : int byte_idx;
3298 : : bool ret;
3299 : : int i;
3300 : :
3301 : : /* Reached end, nothing left to do */
3302 [ # # ]: 0 : if (cur_dw == MLX5_ST_SZ_DW(definer_hl))
3303 : : return true;
3304 : :
3305 : : /* No data set, can skip to next DW */
3306 [ # # ]: 0 : while (!*data) {
3307 : 0 : cur_dw++;
3308 : 0 : data++;
3309 : :
3310 : : /* Reached end, nothing left to do */
3311 [ # # ]: 0 : if (cur_dw == MLX5_ST_SZ_DW(definer_hl))
3312 : : return true;
3313 : : }
3314 : :
3315 : : /* Used all DW selectors and Byte selectors, no possible solution */
3316 [ # # ]: 0 : if (ctrl->allowed_full_dw == ctrl->used_full_dw &&
3317 [ # # ]: 0 : ctrl->allowed_lim_dw == ctrl->used_lim_dw &&
3318 [ # # ]: 0 : ctrl->allowed_bytes == ctrl->used_bytes)
3319 : : return false;
3320 : :
3321 : : /* Try to use limited DW selectors */
3322 [ # # # # ]: 0 : if (ctrl->allowed_lim_dw > ctrl->used_lim_dw && cur_dw < 64) {
3323 : 0 : ctrl->lim_dw_selector[ctrl->used_lim_dw++] = cur_dw;
3324 : :
3325 : 0 : ret = mlx5dr_definer_best_hl_fit_recu(ctrl, cur_dw + 1, data + 1);
3326 [ # # ]: 0 : if (ret)
3327 : : return ret;
3328 : :
3329 : 0 : ctrl->lim_dw_selector[--ctrl->used_lim_dw] = 0;
3330 : : }
3331 : :
3332 : : /* Try to use DW selectors */
3333 [ # # ]: 0 : if (ctrl->allowed_full_dw > ctrl->used_full_dw) {
3334 : 0 : ctrl->full_dw_selector[ctrl->used_full_dw++] = cur_dw;
3335 : :
3336 : 0 : ret = mlx5dr_definer_best_hl_fit_recu(ctrl, cur_dw + 1, data + 1);
3337 [ # # ]: 0 : if (ret)
3338 : : return ret;
3339 : :
3340 : 0 : ctrl->full_dw_selector[--ctrl->used_full_dw] = 0;
3341 : : }
3342 : :
3343 : : /* No byte selector for offset bigger than 255 */
3344 [ # # ]: 0 : if (cur_dw * DW_SIZE > 255)
3345 : : return false;
3346 : :
3347 : 0 : bytes_set = !!(0x000000ff & *data) +
3348 : 0 : !!(0x0000ff00 & *data) +
3349 : 0 : !!(0x00ff0000 & *data) +
3350 : 0 : !!(0xff000000 & *data);
3351 : :
3352 : : /* Check if there are enough byte selectors left */
3353 [ # # ]: 0 : if (bytes_set + ctrl->used_bytes > ctrl->allowed_bytes)
3354 : : return false;
3355 : :
3356 : : /* Try to use Byte selectors */
3357 [ # # ]: 0 : for (i = 0; i < DW_SIZE; i++)
3358 [ # # # # ]: 0 : if ((0xff000000 >> (i * BITS_IN_BYTE)) & rte_be_to_cpu_32(*data)) {
3359 : : /* Use byte selectors high to low */
3360 : 0 : byte_idx = ctrl->allowed_bytes - ctrl->used_bytes - 1;
3361 : 0 : ctrl->byte_selector[byte_idx] = cur_dw * DW_SIZE + i;
3362 : 0 : ctrl->used_bytes++;
3363 : : }
3364 : :
3365 : 0 : ret = mlx5dr_definer_best_hl_fit_recu(ctrl, cur_dw + 1, data + 1);
3366 [ # # ]: 0 : if (ret)
3367 : : return ret;
3368 : :
3369 [ # # ]: 0 : for (i = 0; i < DW_SIZE; i++)
3370 [ # # # # ]: 0 : if ((0xff << (i * BITS_IN_BYTE)) & rte_be_to_cpu_32(*data)) {
3371 : 0 : ctrl->used_bytes--;
3372 : 0 : byte_idx = ctrl->allowed_bytes - ctrl->used_bytes - 1;
3373 : 0 : ctrl->byte_selector[byte_idx] = 0;
3374 : : }
3375 : :
3376 : : return false;
3377 : : }
3378 : :
3379 : : static void
3380 : 0 : mlx5dr_definer_copy_sel_ctrl(struct mlx5dr_definer_sel_ctrl *ctrl,
3381 : : struct mlx5dr_definer *definer)
3382 : : {
3383 : 0 : memcpy(definer->byte_selector, ctrl->byte_selector, ctrl->allowed_bytes);
3384 : 0 : memcpy(definer->dw_selector, ctrl->full_dw_selector, ctrl->allowed_full_dw);
3385 : 0 : memcpy(definer->dw_selector + ctrl->allowed_full_dw,
3386 : 0 : ctrl->lim_dw_selector, ctrl->allowed_lim_dw);
3387 : 0 : }
3388 : :
3389 : : static int
3390 : 0 : mlx5dr_definer_find_best_range_fit(struct mlx5dr_definer *definer,
3391 : : struct mlx5dr_matcher *matcher)
3392 : : {
3393 : 0 : uint8_t tag_byte_offset[MLX5DR_DEFINER_FNAME_MAX] = {0};
3394 : 0 : uint8_t field_select[MLX5DR_DEFINER_FNAME_MAX] = {0};
3395 : 0 : struct mlx5dr_definer_sel_ctrl ctrl = {0};
3396 : : uint32_t byte_offset, algn_byte_off;
3397 : : struct mlx5dr_definer_fc *fcr;
3398 : : bool require_dw;
3399 : : int idx, i, j;
3400 : :
3401 : : /* Try to create a range definer */
3402 : 0 : ctrl.allowed_full_dw = DW_SELECTORS_RANGE;
3403 : 0 : ctrl.allowed_bytes = BYTE_SELECTORS_RANGE;
3404 : :
3405 : : /* Multiple fields cannot share the same DW for range match.
3406 : : * The HW doesn't recognize each field but compares the full dw.
3407 : : * For example definer DW consists of FieldA_FieldB
3408 : : * FieldA: Mask 0xFFFF range 0x1 to 0x2
3409 : : * FieldB: Mask 0xFFFF range 0x3 to 0x4
3410 : : * STE DW range will be 0x00010003 - 0x00020004
3411 : : * This will cause invalid match for FieldB if FieldA=1 and FieldB=8
3412 : : * Since 0x10003 < 0x10008 < 0x20004
3413 : : */
3414 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++) {
3415 [ # # ]: 0 : for (j = 0; j < matcher->mt[i].fcr_sz; j++) {
3416 : 0 : fcr = &matcher->mt[i].fcr[j];
3417 : :
3418 : : /* Found - Reuse previous mt binding */
3419 [ # # ]: 0 : if (field_select[fcr->fname]) {
3420 : 0 : fcr->byte_off = tag_byte_offset[fcr->fname];
3421 : 0 : continue;
3422 : : }
3423 : :
3424 : : /* Not found */
3425 : 0 : require_dw = fcr->byte_off >= (64 * DW_SIZE);
3426 [ # # # # ]: 0 : if (require_dw || ctrl.used_bytes == ctrl.allowed_bytes) {
3427 : : /* Try to cover using DW selector */
3428 [ # # ]: 0 : if (ctrl.used_full_dw == ctrl.allowed_full_dw)
3429 : 0 : goto not_supported;
3430 : :
3431 : 0 : ctrl.full_dw_selector[ctrl.used_full_dw++] =
3432 : 0 : fcr->byte_off / DW_SIZE;
3433 : :
3434 : : /* Bind DW */
3435 : 0 : idx = ctrl.used_full_dw - 1;
3436 : 0 : byte_offset = fcr->byte_off % DW_SIZE;
3437 : 0 : byte_offset += DW_SIZE * (DW_SELECTORS - idx - 1);
3438 : : } else {
3439 : : /* Try to cover using Bytes selectors */
3440 : : if (ctrl.used_bytes == ctrl.allowed_bytes)
3441 : : goto not_supported;
3442 : :
3443 : 0 : algn_byte_off = DW_SIZE * (fcr->byte_off / DW_SIZE);
3444 : 0 : ctrl.byte_selector[ctrl.used_bytes++] = algn_byte_off + 3;
3445 : 0 : ctrl.byte_selector[ctrl.used_bytes++] = algn_byte_off + 2;
3446 : 0 : ctrl.byte_selector[ctrl.used_bytes++] = algn_byte_off + 1;
3447 : 0 : ctrl.byte_selector[ctrl.used_bytes++] = algn_byte_off;
3448 : :
3449 : : /* Bind BYTE */
3450 : : byte_offset = DW_SIZE * DW_SELECTORS;
3451 : 0 : byte_offset += BYTE_SELECTORS - ctrl.used_bytes;
3452 : 0 : byte_offset += fcr->byte_off % DW_SIZE;
3453 : : }
3454 : :
3455 : 0 : fcr->byte_off = byte_offset;
3456 : 0 : tag_byte_offset[fcr->fname] = byte_offset;
3457 : 0 : field_select[fcr->fname] = 1;
3458 : : }
3459 : : }
3460 : :
3461 : 0 : mlx5dr_definer_copy_sel_ctrl(&ctrl, definer);
3462 : 0 : definer->type = MLX5DR_DEFINER_TYPE_RANGE;
3463 : :
3464 : 0 : return 0;
3465 : :
3466 : : not_supported:
3467 : 0 : DR_LOG(ERR, "Unable to find supporting range definer combination");
3468 : 0 : rte_errno = ENOTSUP;
3469 : 0 : return rte_errno;
3470 : : }
3471 : :
3472 : 0 : static void mlx5dr_definer_optimize_order(struct mlx5dr_definer *definer, int num_log)
3473 : : {
3474 : 0 : uint8_t hl_prio[MAX_HL_PRIO - 1] = {MLX5DR_HL_IPV4_SRC,
3475 : : MLX5DR_HL_IPV4_DST,
3476 : : MAX_HL_PRIO};
3477 : : int dw = 0, i = 0, j;
3478 : : int *dw_flag;
3479 : : uint8_t tmp;
3480 : :
3481 : 0 : dw_flag = optimal_dist_dw[num_log];
3482 : :
3483 [ # # ]: 0 : while (hl_prio[i] != MAX_HL_PRIO) {
3484 : : j = 0;
3485 : : /* Finding a candidate to improve its hash distribution */
3486 [ # # # # ]: 0 : while (j < DW_SELECTORS_MATCH && (hl_prio[i] != definer->dw_selector[j]))
3487 : 0 : j++;
3488 : :
3489 : : /* Finding a DW location with good hash distribution */
3490 [ # # # # ]: 0 : while (dw < DW_SELECTORS_MATCH && dw_flag[dw] == 0)
3491 : 0 : dw++;
3492 : :
3493 [ # # ]: 0 : if (dw < DW_SELECTORS_MATCH && j < DW_SELECTORS_MATCH) {
3494 : 0 : tmp = definer->dw_selector[dw];
3495 : 0 : definer->dw_selector[dw] = definer->dw_selector[j];
3496 : 0 : definer->dw_selector[j] = tmp;
3497 : 0 : dw++;
3498 : : }
3499 : 0 : i++;
3500 : : }
3501 : 0 : }
3502 : :
3503 : : static int
3504 : 0 : mlx5dr_definer_find_best_match_fit(struct mlx5dr_context *ctx,
3505 : : struct mlx5dr_definer *definer,
3506 : : uint8_t *hl)
3507 : : {
3508 : 0 : struct mlx5dr_definer_sel_ctrl ctrl = {0};
3509 : : bool found;
3510 : :
3511 : : /* Try to create a match definer */
3512 : 0 : ctrl.allowed_full_dw = DW_SELECTORS_MATCH;
3513 : : ctrl.allowed_lim_dw = 0;
3514 : 0 : ctrl.allowed_bytes = BYTE_SELECTORS;
3515 : :
3516 : 0 : found = mlx5dr_definer_best_hl_fit_recu(&ctrl, 0, (uint32_t *)hl);
3517 [ # # ]: 0 : if (found) {
3518 : 0 : mlx5dr_definer_copy_sel_ctrl(&ctrl, definer);
3519 : 0 : definer->type = MLX5DR_DEFINER_TYPE_MATCH;
3520 : 0 : return 0;
3521 : : }
3522 : :
3523 : : /* Try to create a full/limited jumbo definer */
3524 [ # # ]: 0 : ctrl.allowed_full_dw = ctx->caps->full_dw_jumbo_support ? DW_SELECTORS :
3525 : : DW_SELECTORS_MATCH;
3526 [ # # ]: 0 : ctrl.allowed_lim_dw = ctx->caps->full_dw_jumbo_support ? 0 :
3527 : : DW_SELECTORS_LIMITED;
3528 : : ctrl.allowed_bytes = BYTE_SELECTORS;
3529 : :
3530 : 0 : found = mlx5dr_definer_best_hl_fit_recu(&ctrl, 0, (uint32_t *)hl);
3531 [ # # ]: 0 : if (found) {
3532 : 0 : mlx5dr_definer_copy_sel_ctrl(&ctrl, definer);
3533 : 0 : definer->type = MLX5DR_DEFINER_TYPE_JUMBO;
3534 : 0 : return 0;
3535 : : }
3536 : :
3537 : 0 : DR_LOG(ERR, "Unable to find supporting match/jumbo definer combination");
3538 : 0 : rte_errno = E2BIG;
3539 : 0 : return rte_errno;
3540 : : }
3541 : :
3542 : : static void
3543 : 0 : mlx5dr_definer_create_tag_mask(struct rte_flow_item *items,
3544 : : struct mlx5dr_definer_fc *fc,
3545 : : uint32_t fc_sz,
3546 : : uint8_t *tag)
3547 : : {
3548 : : uint32_t i;
3549 : :
3550 [ # # ]: 0 : for (i = 0; i < fc_sz; i++) {
3551 [ # # ]: 0 : if (fc->tag_mask_set)
3552 : 0 : fc->tag_mask_set(fc, items[fc->item_idx].mask, tag);
3553 : : else
3554 : 0 : fc->tag_set(fc, items[fc->item_idx].mask, tag);
3555 : 0 : fc++;
3556 : : }
3557 : 0 : }
3558 : :
3559 : 0 : void mlx5dr_definer_create_tag(const struct rte_flow_item *items,
3560 : : struct mlx5dr_definer_fc *fc,
3561 : : uint32_t fc_sz,
3562 : : uint8_t *tag)
3563 : : {
3564 : : uint32_t i;
3565 : :
3566 [ # # ]: 0 : for (i = 0; i < fc_sz; i++) {
3567 : 0 : fc->tag_set(fc, items[fc->item_idx].spec, tag);
3568 : 0 : fc++;
3569 : : }
3570 : 0 : }
3571 : :
3572 : : static uint32_t mlx5dr_definer_get_range_byte_off(uint32_t match_byte_off)
3573 : : {
3574 : 0 : uint8_t curr_dw_idx = match_byte_off / DW_SIZE;
3575 : : uint8_t new_dw_idx;
3576 : :
3577 : : /* Range DW can have the following values 7,8,9,10
3578 : : * -DW7 is mapped to DW9
3579 : : * -DW8 is mapped to DW7
3580 : : * -DW9 is mapped to DW5
3581 : : * -DW10 is mapped to DW3
3582 : : * To reduce calculation the following formula is used:
3583 : : */
3584 : 0 : new_dw_idx = curr_dw_idx * (-2) + 23;
3585 : :
3586 : 0 : return new_dw_idx * DW_SIZE + match_byte_off % DW_SIZE;
3587 : : }
3588 : :
3589 : 0 : void mlx5dr_definer_create_tag_range(const struct rte_flow_item *items,
3590 : : struct mlx5dr_definer_fc *fc,
3591 : : uint32_t fc_sz,
3592 : : uint8_t *tag)
3593 : : {
3594 : : struct mlx5dr_definer_fc tmp_fc;
3595 : : uint32_t i;
3596 : :
3597 [ # # ]: 0 : for (i = 0; i < fc_sz; i++) {
3598 : 0 : tmp_fc = *fc;
3599 : : /* Set MAX value */
3600 : 0 : tmp_fc.byte_off = mlx5dr_definer_get_range_byte_off(fc->byte_off);
3601 : 0 : tmp_fc.tag_set(&tmp_fc, items[fc->item_idx].last, tag);
3602 : : /* Set MIN value */
3603 : 0 : tmp_fc.byte_off += DW_SIZE;
3604 : 0 : tmp_fc.tag_set(&tmp_fc, items[fc->item_idx].spec, tag);
3605 : 0 : fc++;
3606 : : }
3607 : 0 : }
3608 : :
3609 : 0 : int mlx5dr_definer_get_id(struct mlx5dr_definer *definer)
3610 : : {
3611 : 0 : return definer->obj->id;
3612 : : }
3613 : :
3614 : 0 : int mlx5dr_definer_compare(struct mlx5dr_definer *definer_a,
3615 : : struct mlx5dr_definer *definer_b)
3616 : : {
3617 : : int i;
3618 : :
3619 : : /* Future: Optimize by comparing selectors with valid mask only */
3620 [ # # ]: 0 : for (i = 0; i < BYTE_SELECTORS; i++)
3621 [ # # ]: 0 : if (definer_a->byte_selector[i] != definer_b->byte_selector[i])
3622 : : return 1;
3623 : :
3624 [ # # ]: 0 : for (i = 0; i < DW_SELECTORS; i++)
3625 [ # # ]: 0 : if (definer_a->dw_selector[i] != definer_b->dw_selector[i])
3626 : : return 1;
3627 : :
3628 [ # # ]: 0 : for (i = 0; i < MLX5DR_JUMBO_TAG_SZ; i++)
3629 [ # # ]: 0 : if (definer_a->mask.jumbo[i] != definer_b->mask.jumbo[i])
3630 : : return 1;
3631 : :
3632 : : return 0;
3633 : : }
3634 : :
3635 : : static int
3636 : 0 : mlx5dr_definer_calc_layout(struct mlx5dr_matcher *matcher,
3637 : : struct mlx5dr_definer *match_definer,
3638 : : struct mlx5dr_definer *range_definer)
3639 : : {
3640 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
3641 : 0 : struct mlx5dr_match_template *mt = matcher->mt;
3642 : : struct mlx5dr_definer_fc *fc;
3643 : : uint8_t *match_hl;
3644 : : int i, ret;
3645 : :
3646 : : /* Union header-layout (hl) is used for creating a single definer
3647 : : * field layout used with different bitmasks for hash and match.
3648 : : */
3649 : : match_hl = simple_calloc(1, MLX5_ST_SZ_BYTES(definer_hl));
3650 [ # # ]: 0 : if (!match_hl) {
3651 : 0 : DR_LOG(ERR, "Failed to allocate memory for header layout");
3652 : 0 : rte_errno = ENOMEM;
3653 : 0 : return rte_errno;
3654 : : }
3655 : :
3656 : : /* Convert all mt items to header layout (hl)
3657 : : * and allocate the match and range field copy array (fc & fcr).
3658 : : */
3659 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++) {
3660 : 0 : ret = mlx5dr_definer_conv_items_to_hl(ctx, &mt[i], match_hl, matcher);
3661 [ # # ]: 0 : if (ret) {
3662 : 0 : DR_LOG(ERR, "Failed to convert items to header layout");
3663 : 0 : goto free_fc;
3664 : : }
3665 : : }
3666 : :
3667 [ # # ]: 0 : if (mlx5dr_matcher_is_compare(matcher)) {
3668 : 0 : ret = mlx5dr_matcher_validate_compare_attr(matcher);
3669 [ # # ]: 0 : if (ret)
3670 : 0 : goto free_fc;
3671 : :
3672 : : /* Due some HW limitation need to fill unused
3673 : : * DW's 0-5 and byte selectors with 0xff.
3674 : : */
3675 [ # # ]: 0 : for (i = 0; i < DW_SELECTORS_MATCH; i++)
3676 : 0 : match_definer->dw_selector[i] = 0xff;
3677 : :
3678 [ # # ]: 0 : for (i = 0; i < BYTE_SELECTORS; i++)
3679 : 0 : match_definer->byte_selector[i] = 0xff;
3680 : :
3681 [ # # ]: 0 : for (i = 0; i < mt[0].fc_sz; i++) {
3682 : 0 : fc = &mt[0].fc[i];
3683 : 0 : match_definer->dw_selector[fc->compare_idx] = fc->byte_off / DW_SIZE;
3684 : : }
3685 : :
3686 : 0 : goto out;
3687 : : }
3688 : :
3689 : : /* Find the match definer layout for header layout match union */
3690 : 0 : ret = mlx5dr_definer_find_best_match_fit(ctx, match_definer, match_hl);
3691 [ # # ]: 0 : if (ret) {
3692 : 0 : DR_LOG(ERR, "Failed to create match definer from header layout");
3693 : 0 : goto free_fc;
3694 : : }
3695 : :
3696 [ # # # # ]: 0 : if (!mlx5dr_definer_is_jumbo(match_definer) &&
3697 [ # # ]: 0 : !mlx5dr_matcher_req_fw_wqe(matcher) &&
3698 [ # # ]: 0 : !mlx5dr_matcher_is_resizable(matcher) &&
3699 : : !mlx5dr_matcher_is_insert_by_idx(matcher))
3700 : 0 : mlx5dr_definer_optimize_order(match_definer, matcher->attr.rule.num_log);
3701 : :
3702 : : /* Find the range definer layout for match templates fcrs */
3703 : 0 : ret = mlx5dr_definer_find_best_range_fit(range_definer, matcher);
3704 [ # # ]: 0 : if (ret) {
3705 : 0 : DR_LOG(ERR, "Failed to create range definer from header layout");
3706 : 0 : goto free_fc;
3707 : : }
3708 : :
3709 : 0 : out:
3710 : : simple_free(match_hl);
3711 : 0 : return 0;
3712 : :
3713 : : free_fc:
3714 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++)
3715 [ # # ]: 0 : if (mt[i].fc)
3716 : : simple_free(mt[i].fc);
3717 : :
3718 : : simple_free(match_hl);
3719 : 0 : return rte_errno;
3720 : : }
3721 : :
3722 : 0 : int mlx5dr_definer_init_cache(struct mlx5dr_definer_cache **cache)
3723 : : {
3724 : : struct mlx5dr_definer_cache *new_cache;
3725 : :
3726 : : new_cache = simple_calloc(1, sizeof(*new_cache));
3727 [ # # ]: 0 : if (!new_cache) {
3728 : 0 : rte_errno = ENOMEM;
3729 : 0 : return rte_errno;
3730 : : }
3731 : 0 : LIST_INIT(&new_cache->head);
3732 : 0 : *cache = new_cache;
3733 : :
3734 : 0 : return 0;
3735 : : }
3736 : :
3737 : 0 : void mlx5dr_definer_uninit_cache(struct mlx5dr_definer_cache *cache)
3738 : : {
3739 : : simple_free(cache);
3740 : 0 : }
3741 : :
3742 : : static struct mlx5dr_devx_obj *
3743 : 0 : mlx5dr_definer_get_obj(struct mlx5dr_context *ctx,
3744 : : struct mlx5dr_definer *definer)
3745 : : {
3746 : 0 : struct mlx5dr_definer_cache *cache = ctx->definer_cache;
3747 : 0 : struct mlx5dr_cmd_definer_create_attr def_attr = {0};
3748 : : struct mlx5dr_definer_cache_item *cached_definer;
3749 : : struct mlx5dr_devx_obj *obj;
3750 : :
3751 : : /* Search definer cache for requested definer */
3752 [ # # ]: 0 : LIST_FOREACH(cached_definer, &cache->head, next) {
3753 [ # # ]: 0 : if (mlx5dr_definer_compare(&cached_definer->definer, definer))
3754 : : continue;
3755 : :
3756 : : /* Reuse definer and set LRU (move to be first in the list) */
3757 [ # # ]: 0 : LIST_REMOVE(cached_definer, next);
3758 [ # # ]: 0 : LIST_INSERT_HEAD(&cache->head, cached_definer, next);
3759 : 0 : cached_definer->refcount++;
3760 : 0 : return cached_definer->definer.obj;
3761 : : }
3762 : :
3763 : : /* Allocate and create definer based on the bitmask tag */
3764 : 0 : def_attr.match_mask = definer->mask.jumbo;
3765 : 0 : def_attr.dw_selector = definer->dw_selector;
3766 : 0 : def_attr.byte_selector = definer->byte_selector;
3767 : :
3768 : 0 : obj = mlx5dr_cmd_definer_create(ctx->ibv_ctx, &def_attr);
3769 [ # # ]: 0 : if (!obj)
3770 : : return NULL;
3771 : :
3772 : : cached_definer = simple_calloc(1, sizeof(*cached_definer));
3773 [ # # ]: 0 : if (!cached_definer) {
3774 : 0 : rte_errno = ENOMEM;
3775 : 0 : goto free_definer_obj;
3776 : : }
3777 : :
3778 [ # # ]: 0 : memcpy(&cached_definer->definer, definer, sizeof(*definer));
3779 : 0 : cached_definer->definer.obj = obj;
3780 : 0 : cached_definer->refcount = 1;
3781 [ # # ]: 0 : LIST_INSERT_HEAD(&cache->head, cached_definer, next);
3782 : :
3783 : 0 : return obj;
3784 : :
3785 : : free_definer_obj:
3786 : 0 : mlx5dr_cmd_destroy_obj(obj);
3787 : 0 : return NULL;
3788 : : }
3789 : :
3790 : : static void
3791 : 0 : mlx5dr_definer_put_obj(struct mlx5dr_context *ctx,
3792 : : struct mlx5dr_devx_obj *obj)
3793 : : {
3794 : : struct mlx5dr_definer_cache_item *cached_definer;
3795 : :
3796 [ # # ]: 0 : LIST_FOREACH(cached_definer, &ctx->definer_cache->head, next) {
3797 [ # # ]: 0 : if (cached_definer->definer.obj != obj)
3798 : : continue;
3799 : :
3800 : : /* Object found */
3801 [ # # ]: 0 : if (--cached_definer->refcount)
3802 : : return;
3803 : :
3804 [ # # ]: 0 : LIST_REMOVE(cached_definer, next);
3805 : 0 : mlx5dr_cmd_destroy_obj(cached_definer->definer.obj);
3806 : : simple_free(cached_definer);
3807 : : return;
3808 : : }
3809 : :
3810 : : /* Programming error, object must be part of cache */
3811 : 0 : assert(false);
3812 : : }
3813 : :
3814 : : static struct mlx5dr_definer *
3815 : 0 : mlx5dr_definer_alloc(struct mlx5dr_context *ctx,
3816 : : struct mlx5dr_definer_fc *fc,
3817 : : int fc_sz,
3818 : : struct rte_flow_item *items,
3819 : : struct mlx5dr_definer *layout,
3820 : : bool bind_fc)
3821 : : {
3822 : : struct mlx5dr_definer *definer;
3823 : : int ret;
3824 : :
3825 : : definer = simple_calloc(1, sizeof(*definer));
3826 [ # # ]: 0 : if (!definer) {
3827 : 0 : DR_LOG(ERR, "Failed to allocate memory for definer");
3828 : 0 : rte_errno = ENOMEM;
3829 : 0 : return NULL;
3830 : : }
3831 : :
3832 : : memcpy(definer, layout, sizeof(*definer));
3833 : :
3834 : : /* Align field copy array based on given layout */
3835 [ # # ]: 0 : if (bind_fc) {
3836 : 0 : ret = mlx5dr_definer_fc_bind(definer, fc, fc_sz);
3837 [ # # ]: 0 : if (ret) {
3838 : 0 : DR_LOG(ERR, "Failed to bind field copy to definer");
3839 : 0 : goto free_definer;
3840 : : }
3841 : : }
3842 : :
3843 : : /* Create the tag mask used for definer creation */
3844 : 0 : mlx5dr_definer_create_tag_mask(items, fc, fc_sz, definer->mask.jumbo);
3845 : :
3846 : 0 : definer->obj = mlx5dr_definer_get_obj(ctx, definer);
3847 [ # # ]: 0 : if (!definer->obj)
3848 : 0 : goto free_definer;
3849 : :
3850 : : return definer;
3851 : :
3852 : 0 : free_definer:
3853 : : simple_free(definer);
3854 : 0 : return NULL;
3855 : : }
3856 : :
3857 : : static void
3858 : : mlx5dr_definer_free(struct mlx5dr_context *ctx,
3859 : : struct mlx5dr_definer *definer)
3860 : : {
3861 : 0 : mlx5dr_definer_put_obj(ctx, definer->obj);
3862 : : simple_free(definer);
3863 : 0 : }
3864 : :
3865 : : static int
3866 : 0 : mlx5dr_definer_matcher_match_init(struct mlx5dr_context *ctx,
3867 : : struct mlx5dr_matcher *matcher,
3868 : : struct mlx5dr_definer *match_layout)
3869 : : {
3870 : 0 : struct mlx5dr_match_template *mt = matcher->mt;
3871 : : int i;
3872 : :
3873 : : /* Create mendatory match definer */
3874 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++) {
3875 : 0 : mt[i].definer = mlx5dr_definer_alloc(ctx,
3876 : : mt[i].fc,
3877 : 0 : mt[i].fc_sz,
3878 : 0 : mt[i].items,
3879 : : match_layout,
3880 : : true);
3881 [ # # ]: 0 : if (!mt[i].definer) {
3882 : 0 : DR_LOG(ERR, "Failed to create match definer");
3883 : 0 : goto free_definers;
3884 : : }
3885 : : }
3886 : : return 0;
3887 : :
3888 : : free_definers:
3889 [ # # ]: 0 : while (i--)
3890 : 0 : mlx5dr_definer_free(ctx, mt[i].definer);
3891 : :
3892 : 0 : return rte_errno;
3893 : : }
3894 : :
3895 : : static void
3896 : 0 : mlx5dr_definer_matcher_match_uninit(struct mlx5dr_matcher *matcher)
3897 : : {
3898 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
3899 : : int i;
3900 : :
3901 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++)
3902 : 0 : mlx5dr_definer_free(ctx, matcher->mt[i].definer);
3903 : 0 : }
3904 : :
3905 : : static int
3906 : 0 : mlx5dr_definer_matcher_range_init(struct mlx5dr_context *ctx,
3907 : : struct mlx5dr_matcher *matcher,
3908 : : struct mlx5dr_definer *range_layout)
3909 : : {
3910 : 0 : struct mlx5dr_match_template *mt = matcher->mt;
3911 : : int i;
3912 : :
3913 : : /* Create optional range definers */
3914 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++) {
3915 [ # # ]: 0 : if (!mt[i].fcr_sz)
3916 : 0 : continue;
3917 : :
3918 : : /* All must use range if requested */
3919 [ # # # # ]: 0 : if (i && !mt[i - 1].range_definer) {
3920 : 0 : DR_LOG(ERR, "Using range and non range templates is not allowed");
3921 : 0 : goto free_definers;
3922 : : }
3923 : :
3924 : 0 : matcher->flags |= MLX5DR_MATCHER_FLAGS_RANGE_DEFINER;
3925 : : /* Create definer without fcr binding, already binded */
3926 : 0 : mt[i].range_definer = mlx5dr_definer_alloc(ctx,
3927 : : mt[i].fcr,
3928 : : mt[i].fcr_sz,
3929 : : mt[i].items,
3930 : : range_layout,
3931 : : false);
3932 [ # # ]: 0 : if (!mt[i].range_definer) {
3933 : 0 : DR_LOG(ERR, "Failed to create match definer");
3934 : 0 : goto free_definers;
3935 : : }
3936 : : }
3937 : : return 0;
3938 : :
3939 : : free_definers:
3940 [ # # ]: 0 : while (i--)
3941 [ # # ]: 0 : if (mt[i].range_definer)
3942 : : mlx5dr_definer_free(ctx, mt[i].range_definer);
3943 : :
3944 : 0 : return rte_errno;
3945 : : }
3946 : :
3947 : : static void
3948 : 0 : mlx5dr_definer_matcher_range_uninit(struct mlx5dr_matcher *matcher)
3949 : : {
3950 : 0 : struct mlx5dr_context *ctx = matcher->tbl->ctx;
3951 : : int i;
3952 : :
3953 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++)
3954 [ # # ]: 0 : if (matcher->mt[i].range_definer)
3955 : : mlx5dr_definer_free(ctx, matcher->mt[i].range_definer);
3956 : 0 : }
3957 : :
3958 : : static int
3959 : 0 : mlx5dr_definer_matcher_hash_init(struct mlx5dr_context *ctx,
3960 : : struct mlx5dr_matcher *matcher)
3961 : : {
3962 : 0 : struct mlx5dr_cmd_definer_create_attr def_attr = {0};
3963 : 0 : struct mlx5dr_match_template *mt = matcher->mt;
3964 : 0 : struct ibv_context *ibv_ctx = ctx->ibv_ctx;
3965 : : uint8_t *bit_mask;
3966 : : int i, j;
3967 : :
3968 [ # # ]: 0 : for (i = 1; i < matcher->num_of_mt; i++)
3969 [ # # ]: 0 : if (mlx5dr_definer_compare(mt[i].definer, mt[i - 1].definer))
3970 : 0 : matcher->flags |= MLX5DR_MATCHER_FLAGS_HASH_DEFINER;
3971 : :
3972 [ # # ]: 0 : if (!(matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER))
3973 : : return 0;
3974 : :
3975 : : /* Insert by index requires all MT using the same definer */
3976 [ # # ]: 0 : if (matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) {
3977 : 0 : DR_LOG(ERR, "Insert by index not supported with MT combination");
3978 : 0 : rte_errno = EOPNOTSUPP;
3979 : 0 : return rte_errno;
3980 : : }
3981 : :
3982 : 0 : matcher->hash_definer = simple_calloc(1, sizeof(*matcher->hash_definer));
3983 [ # # ]: 0 : if (!matcher->hash_definer) {
3984 : 0 : DR_LOG(ERR, "Failed to allocate memory for hash definer");
3985 : 0 : rte_errno = ENOMEM;
3986 : 0 : return rte_errno;
3987 : : }
3988 : :
3989 : : /* Calculate intersection between all match templates bitmasks.
3990 : : * We will use mt[0] as reference and intersect it with mt[1..n].
3991 : : * From this we will get:
3992 : : * hash_definer.selectors = mt[0].selecotrs
3993 : : * hash_definer.mask = mt[0].mask & mt[0].mask & ... & mt[n].mask
3994 : : */
3995 : :
3996 : : /* Use first definer which should also contain intersection fields */
3997 : 0 : memcpy(matcher->hash_definer, mt->definer, sizeof(struct mlx5dr_definer));
3998 : :
3999 : : /* Calculate intersection between first to all match templates bitmasks */
4000 [ # # ]: 0 : for (i = 1; i < matcher->num_of_mt; i++) {
4001 : 0 : bit_mask = (uint8_t *)&mt[i].definer->mask;
4002 [ # # ]: 0 : for (j = 0; j < MLX5DR_JUMBO_TAG_SZ; j++)
4003 : 0 : ((uint8_t *)&matcher->hash_definer->mask)[j] &= bit_mask[j];
4004 : : }
4005 : :
4006 : 0 : def_attr.match_mask = matcher->hash_definer->mask.jumbo;
4007 : 0 : def_attr.dw_selector = matcher->hash_definer->dw_selector;
4008 : 0 : def_attr.byte_selector = matcher->hash_definer->byte_selector;
4009 : 0 : matcher->hash_definer->obj = mlx5dr_cmd_definer_create(ibv_ctx, &def_attr);
4010 [ # # ]: 0 : if (!matcher->hash_definer->obj) {
4011 : 0 : DR_LOG(ERR, "Failed to create hash definer");
4012 : 0 : goto free_hash_definer;
4013 : : }
4014 : :
4015 : : return 0;
4016 : :
4017 : : free_hash_definer:
4018 : 0 : simple_free(matcher->hash_definer);
4019 : 0 : return rte_errno;
4020 : : }
4021 : :
4022 : : static void
4023 : 0 : mlx5dr_definer_matcher_hash_uninit(struct mlx5dr_matcher *matcher)
4024 : : {
4025 [ # # ]: 0 : if (!matcher->hash_definer)
4026 : : return;
4027 : :
4028 : 0 : mlx5dr_cmd_destroy_obj(matcher->hash_definer->obj);
4029 : 0 : simple_free(matcher->hash_definer);
4030 : : }
4031 : :
4032 : 0 : int mlx5dr_definer_matcher_init(struct mlx5dr_context *ctx,
4033 : : struct mlx5dr_matcher *matcher)
4034 : : {
4035 : 0 : struct mlx5dr_definer match_layout = {0};
4036 : 0 : struct mlx5dr_definer range_layout = {0};
4037 : : int ret, i;
4038 : :
4039 [ # # ]: 0 : if (matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION)
4040 : : return 0;
4041 : :
4042 : 0 : ret = mlx5dr_definer_calc_layout(matcher, &match_layout, &range_layout);
4043 [ # # ]: 0 : if (ret) {
4044 : 0 : DR_LOG(ERR, "Failed to calculate matcher definer layout");
4045 : 0 : return ret;
4046 : : }
4047 : :
4048 : : /* Calculate definers needed for exact match */
4049 : 0 : ret = mlx5dr_definer_matcher_match_init(ctx, matcher, &match_layout);
4050 [ # # ]: 0 : if (ret) {
4051 : 0 : DR_LOG(ERR, "Failed to init match definers");
4052 : 0 : goto free_fc;
4053 : : }
4054 : :
4055 : : /* Calculate definers needed for range */
4056 : 0 : ret = mlx5dr_definer_matcher_range_init(ctx, matcher, &range_layout);
4057 [ # # ]: 0 : if (ret) {
4058 : 0 : DR_LOG(ERR, "Failed to init range definers");
4059 : 0 : goto uninit_match_definer;
4060 : : }
4061 : :
4062 : : /* Calculate partial hash definer */
4063 : 0 : ret = mlx5dr_definer_matcher_hash_init(ctx, matcher);
4064 [ # # ]: 0 : if (ret) {
4065 : 0 : DR_LOG(ERR, "Failed to init hash definer");
4066 : 0 : goto uninit_range_definer;
4067 : : }
4068 : :
4069 : : return 0;
4070 : :
4071 : : uninit_range_definer:
4072 : 0 : mlx5dr_definer_matcher_range_uninit(matcher);
4073 : 0 : uninit_match_definer:
4074 : 0 : mlx5dr_definer_matcher_match_uninit(matcher);
4075 : 0 : free_fc:
4076 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++)
4077 : 0 : simple_free(matcher->mt[i].fc);
4078 : :
4079 : : return ret;
4080 : : }
4081 : :
4082 : 0 : void mlx5dr_definer_matcher_uninit(struct mlx5dr_matcher *matcher)
4083 : : {
4084 : : int i;
4085 : :
4086 [ # # ]: 0 : if (matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION)
4087 : : return;
4088 : :
4089 : 0 : mlx5dr_definer_matcher_hash_uninit(matcher);
4090 : 0 : mlx5dr_definer_matcher_range_uninit(matcher);
4091 : 0 : mlx5dr_definer_matcher_match_uninit(matcher);
4092 : :
4093 [ # # ]: 0 : for (i = 0; i < matcher->num_of_mt; i++)
4094 : 0 : simple_free(matcher->mt[i].fc);
4095 : : }
|