Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Chelsio Communications.
3 : : * All rights reserved.
4 : : */
5 : : #include "base/common.h"
6 : : #include "cxgbe_flow.h"
7 : :
8 : : #define __CXGBE_FILL_FS(__v, __m, fs, elem, e) \
9 : : do { \
10 : : if ((fs)->mask.elem && ((fs)->val.elem != (__v))) \
11 : : return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, \
12 : : NULL, "Redefined match item with" \
13 : : " different values found"); \
14 : : (fs)->val.elem = (__v); \
15 : : (fs)->mask.elem = (__m); \
16 : : } while (0)
17 : :
18 : : #define __CXGBE_FILL_FS_MEMCPY(__v, __m, fs, elem) \
19 : : do { \
20 : : memcpy(&(fs)->val.elem, &(__v), sizeof(__v)); \
21 : : memcpy(&(fs)->mask.elem, &(__m), sizeof(__m)); \
22 : : } while (0)
23 : :
24 : : #define CXGBE_FILL_FS(v, m, elem) \
25 : : __CXGBE_FILL_FS(v, m, fs, elem, e)
26 : :
27 : : #define CXGBE_FILL_FS_MEMCPY(v, m, elem) \
28 : : __CXGBE_FILL_FS_MEMCPY(v, m, fs, elem)
29 : :
30 : : static int
31 : 0 : cxgbe_validate_item(const struct rte_flow_item *i, struct rte_flow_error *e)
32 : : {
33 : : /* rte_flow specification does not allow it. */
34 [ # # # # : 0 : if (!i->spec && (i->mask || i->last))
# # ]
35 : 0 : return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
36 : : i, "last or mask given without spec");
37 : : /*
38 : : * We don't support it.
39 : : * Although, we can support values in last as 0's or last == spec.
40 : : * But this will not provide user with any additional functionality
41 : : * and will only increase the complexity for us.
42 : : */
43 [ # # ]: 0 : if (i->last)
44 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
45 : : i, "last is not supported by chelsio pmd");
46 : : return 0;
47 : : }
48 : :
49 : : /**
50 : : * Apart from the 4-tuple IPv4/IPv6 - TCP/UDP information,
51 : : * there's only 40-bits available to store match fields.
52 : : * So, to save space, optimize filter spec for some common
53 : : * known fields that hardware can parse against incoming
54 : : * packets automatically.
55 : : */
56 : : static void
57 : 0 : cxgbe_tweak_filter_spec(struct adapter *adap,
58 : : struct ch_filter_specification *fs)
59 : : {
60 : : /* Save 16-bit ethertype field space, by setting corresponding
61 : : * 1-bit flags in the filter spec for common known ethertypes.
62 : : * When hardware sees these flags, it automatically infers and
63 : : * matches incoming packets against the corresponding ethertype.
64 : : */
65 [ # # ]: 0 : if (fs->mask.ethtype == 0xffff) {
66 [ # # # # : 0 : switch (fs->val.ethtype) {
# ]
67 : 0 : case RTE_ETHER_TYPE_IPV4:
68 [ # # ]: 0 : if (adap->params.tp.ethertype_shift < 0) {
69 : 0 : fs->type = FILTER_TYPE_IPV4;
70 : 0 : fs->val.ethtype = 0;
71 : 0 : fs->mask.ethtype = 0;
72 : : }
73 : : break;
74 : 0 : case RTE_ETHER_TYPE_IPV6:
75 [ # # ]: 0 : if (adap->params.tp.ethertype_shift < 0) {
76 : 0 : fs->type = FILTER_TYPE_IPV6;
77 : 0 : fs->val.ethtype = 0;
78 : 0 : fs->mask.ethtype = 0;
79 : : }
80 : : break;
81 : 0 : case RTE_ETHER_TYPE_VLAN:
82 [ # # ]: 0 : if (adap->params.tp.ethertype_shift < 0 &&
83 [ # # ]: 0 : adap->params.tp.vlan_shift >= 0) {
84 : 0 : fs->val.ivlan_vld = 1;
85 : 0 : fs->mask.ivlan_vld = 1;
86 : 0 : fs->val.ethtype = 0;
87 : 0 : fs->mask.ethtype = 0;
88 : : }
89 : : break;
90 : 0 : case RTE_ETHER_TYPE_QINQ:
91 [ # # ]: 0 : if (adap->params.tp.ethertype_shift < 0 &&
92 [ # # ]: 0 : adap->params.tp.vnic_shift >= 0) {
93 : 0 : fs->val.ovlan_vld = 1;
94 : 0 : fs->mask.ovlan_vld = 1;
95 : 0 : fs->val.ethtype = 0;
96 : 0 : fs->mask.ethtype = 0;
97 : : }
98 : : break;
99 : : default:
100 : : break;
101 : : }
102 : : }
103 : 0 : }
104 : :
105 : : static void
106 : 0 : cxgbe_fill_filter_region(struct adapter *adap,
107 : : struct ch_filter_specification *fs)
108 : : {
109 : : struct tp_params *tp = &adap->params.tp;
110 : 0 : u64 hash_filter_mask = tp->hash_filter_mask;
111 : : u64 ntuple_mask = 0;
112 : :
113 [ # # ]: 0 : fs->cap = 0;
114 : :
115 [ # # ]: 0 : if (!is_hashfilter(adap))
116 : : return;
117 : :
118 [ # # ]: 0 : if (fs->type) {
119 : 0 : uint8_t biton[16] = {0xff, 0xff, 0xff, 0xff,
120 : : 0xff, 0xff, 0xff, 0xff,
121 : : 0xff, 0xff, 0xff, 0xff,
122 : : 0xff, 0xff, 0xff, 0xff};
123 : 0 : uint8_t bitoff[16] = {0};
124 : :
125 [ # # ]: 0 : if (!memcmp(fs->val.lip, bitoff, sizeof(bitoff)) ||
126 [ # # ]: 0 : !memcmp(fs->val.fip, bitoff, sizeof(bitoff)) ||
127 [ # # ]: 0 : memcmp(fs->mask.lip, biton, sizeof(biton)) ||
128 [ # # ]: 0 : memcmp(fs->mask.fip, biton, sizeof(biton)))
129 : 0 : return;
130 : : } else {
131 : 0 : uint32_t biton = 0xffffffff;
132 : 0 : uint32_t bitoff = 0x0U;
133 : :
134 [ # # ]: 0 : if (!memcmp(fs->val.lip, &bitoff, sizeof(bitoff)) ||
135 [ # # ]: 0 : !memcmp(fs->val.fip, &bitoff, sizeof(bitoff)) ||
136 [ # # ]: 0 : memcmp(fs->mask.lip, &biton, sizeof(biton)) ||
137 [ # # ]: 0 : memcmp(fs->mask.fip, &biton, sizeof(biton)))
138 : 0 : return;
139 : : }
140 : :
141 [ # # # # ]: 0 : if (!fs->val.lport || fs->mask.lport != 0xffff)
142 : : return;
143 [ # # # # ]: 0 : if (!fs->val.fport || fs->mask.fport != 0xffff)
144 : : return;
145 : :
146 [ # # ]: 0 : if (tp->protocol_shift >= 0)
147 : 0 : ntuple_mask |= (u64)fs->mask.proto << tp->protocol_shift;
148 [ # # ]: 0 : if (tp->ethertype_shift >= 0)
149 : 0 : ntuple_mask |= (u64)fs->mask.ethtype << tp->ethertype_shift;
150 [ # # ]: 0 : if (tp->port_shift >= 0)
151 : 0 : ntuple_mask |= (u64)fs->mask.iport << tp->port_shift;
152 [ # # ]: 0 : if (tp->macmatch_shift >= 0)
153 : 0 : ntuple_mask |= (u64)fs->mask.macidx << tp->macmatch_shift;
154 [ # # # # ]: 0 : if (tp->vlan_shift >= 0 && fs->mask.ivlan_vld)
155 : 0 : ntuple_mask |= (u64)(F_FT_VLAN_VLD | fs->mask.ivlan) <<
156 : : tp->vlan_shift;
157 [ # # ]: 0 : if (tp->vnic_shift >= 0) {
158 [ # # ]: 0 : if (fs->mask.ovlan_vld)
159 : 0 : ntuple_mask |= (u64)(fs->val.ovlan_vld << 16 |
160 : 0 : fs->mask.ovlan) << tp->vnic_shift;
161 [ # # ]: 0 : else if (fs->mask.pfvf_vld)
162 : 0 : ntuple_mask |= (u64)(fs->mask.pfvf_vld << 16 |
163 : 0 : fs->mask.pf << 13 |
164 : 0 : fs->mask.vf) << tp->vnic_shift;
165 : : }
166 [ # # ]: 0 : if (tp->tos_shift >= 0)
167 : 0 : ntuple_mask |= (u64)fs->mask.tos << tp->tos_shift;
168 : :
169 [ # # ]: 0 : if (ntuple_mask != hash_filter_mask)
170 : : return;
171 : :
172 : 0 : fs->cap = 1; /* use hash region */
173 : : }
174 : :
175 : : static int
176 : 0 : ch_rte_parsetype_eth(const void *dmask, const struct rte_flow_item *item,
177 : : struct ch_filter_specification *fs,
178 : : struct rte_flow_error *e)
179 : : {
180 : 0 : const struct rte_flow_item_eth *spec = item->spec;
181 : 0 : const struct rte_flow_item_eth *umask = item->mask;
182 : : const struct rte_flow_item_eth *mask;
183 : :
184 : : /* If user has not given any mask, then use chelsio supported mask. */
185 [ # # ]: 0 : mask = umask ? umask : (const struct rte_flow_item_eth *)dmask;
186 : :
187 [ # # ]: 0 : if (!spec)
188 : : return 0;
189 : :
190 : : /* we don't support SRC_MAC filtering*/
191 [ # # # # ]: 0 : if (!rte_is_zero_ether_addr(&spec->hdr.src_addr) ||
192 [ # # ]: 0 : (umask && !rte_is_zero_ether_addr(&umask->hdr.src_addr)))
193 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
194 : : item,
195 : : "src mac filtering not supported");
196 : :
197 [ # # # # ]: 0 : if (!rte_is_zero_ether_addr(&spec->hdr.dst_addr) ||
198 [ # # ]: 0 : (umask && !rte_is_zero_ether_addr(&umask->hdr.dst_addr))) {
199 [ # # # # ]: 0 : CXGBE_FILL_FS(0, 0x1ff, macidx);
200 : 0 : CXGBE_FILL_FS_MEMCPY(spec->hdr.dst_addr.addr_bytes, mask->hdr.dst_addr.addr_bytes,
201 : : dmac);
202 : : }
203 : :
204 [ # # # # : 0 : if (spec->hdr.ether_type || (umask && umask->hdr.ether_type))
# # ]
205 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(spec->hdr.ether_type),
# # # # #
# ]
206 : : be16_to_cpu(mask->hdr.ether_type), ethtype);
207 : :
208 : : return 0;
209 : : }
210 : :
211 : : static int
212 : 0 : ch_rte_parsetype_vlan(const void *dmask, const struct rte_flow_item *item,
213 : : struct ch_filter_specification *fs,
214 : : struct rte_flow_error *e)
215 : : {
216 : 0 : const struct rte_flow_item_vlan *spec = item->spec;
217 : 0 : const struct rte_flow_item_vlan *umask = item->mask;
218 : : const struct rte_flow_item_vlan *mask;
219 : :
220 : : /* If user has not given any mask, then use chelsio supported mask. */
221 [ # # ]: 0 : mask = umask ? umask : (const struct rte_flow_item_vlan *)dmask;
222 : :
223 : : /* If ethertype is already set and is not VLAN (0x8100) or
224 : : * QINQ(0x88A8), then don't proceed further. Otherwise,
225 : : * reset the outer ethertype, so that it can be replaced by
226 : : * innermost ethertype. Note that hardware will automatically
227 : : * match against VLAN or QINQ packets, based on 'ivlan_vld' or
228 : : * 'ovlan_vld' bit set in Chelsio filter spec, respectively.
229 : : */
230 [ # # ]: 0 : if (fs->mask.ethtype) {
231 [ # # ]: 0 : if (fs->val.ethtype != RTE_ETHER_TYPE_VLAN &&
232 : : fs->val.ethtype != RTE_ETHER_TYPE_QINQ)
233 : 0 : return rte_flow_error_set(e, EINVAL,
234 : : RTE_FLOW_ERROR_TYPE_ITEM,
235 : : item,
236 : : "Ethertype must be 0x8100 or 0x88a8");
237 : : }
238 : :
239 [ # # ]: 0 : if (fs->val.ethtype == RTE_ETHER_TYPE_QINQ) {
240 [ # # # # ]: 0 : CXGBE_FILL_FS(1, 1, ovlan_vld);
241 [ # # ]: 0 : if (spec) {
242 [ # # # # : 0 : if (spec->hdr.vlan_tci || (umask && umask->hdr.vlan_tci))
# # ]
243 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(spec->hdr.vlan_tci),
# # # # #
# ]
244 : : be16_to_cpu(mask->hdr.vlan_tci), ovlan);
245 : 0 : fs->mask.ethtype = 0;
246 : 0 : fs->val.ethtype = 0;
247 : : }
248 : : } else {
249 [ # # # # ]: 0 : CXGBE_FILL_FS(1, 1, ivlan_vld);
250 [ # # ]: 0 : if (spec) {
251 [ # # # # : 0 : if (spec->hdr.vlan_tci || (umask && umask->hdr.vlan_tci))
# # ]
252 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(spec->hdr.vlan_tci),
# # # # #
# ]
253 : : be16_to_cpu(mask->hdr.vlan_tci), ivlan);
254 : 0 : fs->mask.ethtype = 0;
255 : 0 : fs->val.ethtype = 0;
256 : : }
257 : : }
258 : :
259 [ # # # # : 0 : if (spec && (spec->hdr.eth_proto || (umask && umask->hdr.eth_proto)))
# # # # ]
260 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(spec->hdr.eth_proto),
# # # # #
# ]
261 : : be16_to_cpu(mask->hdr.eth_proto), ethtype);
262 : :
263 : : return 0;
264 : : }
265 : :
266 : : static int
267 : 0 : ch_rte_parsetype_udp(const void *dmask, const struct rte_flow_item *item,
268 : : struct ch_filter_specification *fs,
269 : : struct rte_flow_error *e)
270 : : {
271 : 0 : const struct rte_flow_item_udp *val = item->spec;
272 : 0 : const struct rte_flow_item_udp *umask = item->mask;
273 : : const struct rte_flow_item_udp *mask;
274 : :
275 [ # # ]: 0 : mask = umask ? umask : (const struct rte_flow_item_udp *)dmask;
276 : :
277 [ # # # # ]: 0 : if (mask->hdr.dgram_len || mask->hdr.dgram_cksum)
278 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
279 : : item,
280 : : "udp: only src/dst port supported");
281 : :
282 [ # # # # ]: 0 : CXGBE_FILL_FS(IPPROTO_UDP, 0xff, proto);
283 [ # # ]: 0 : if (!val)
284 : : return 0;
285 : :
286 [ # # # # : 0 : if (val->hdr.src_port || (umask && umask->hdr.src_port))
# # ]
287 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(val->hdr.src_port),
# # # # #
# ]
288 : : be16_to_cpu(mask->hdr.src_port), fport);
289 : :
290 [ # # # # : 0 : if (val->hdr.dst_port || (umask && umask->hdr.dst_port))
# # ]
291 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(val->hdr.dst_port),
# # # # #
# ]
292 : : be16_to_cpu(mask->hdr.dst_port), lport);
293 : :
294 : : return 0;
295 : : }
296 : :
297 : : static int
298 : 0 : ch_rte_parsetype_tcp(const void *dmask, const struct rte_flow_item *item,
299 : : struct ch_filter_specification *fs,
300 : : struct rte_flow_error *e)
301 : : {
302 : 0 : const struct rte_flow_item_tcp *val = item->spec;
303 : 0 : const struct rte_flow_item_tcp *umask = item->mask;
304 : : const struct rte_flow_item_tcp *mask;
305 : :
306 [ # # ]: 0 : mask = umask ? umask : (const struct rte_flow_item_tcp *)dmask;
307 : :
308 [ # # # # : 0 : if (mask->hdr.sent_seq || mask->hdr.recv_ack || mask->hdr.data_off ||
# # ]
309 [ # # # # : 0 : mask->hdr.tcp_flags || mask->hdr.rx_win || mask->hdr.cksum ||
# # ]
310 [ # # ]: 0 : mask->hdr.tcp_urp)
311 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
312 : : item,
313 : : "tcp: only src/dst port supported");
314 : :
315 [ # # # # ]: 0 : CXGBE_FILL_FS(IPPROTO_TCP, 0xff, proto);
316 [ # # ]: 0 : if (!val)
317 : : return 0;
318 : :
319 [ # # # # : 0 : if (val->hdr.src_port || (umask && umask->hdr.src_port))
# # ]
320 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(val->hdr.src_port),
# # # # #
# ]
321 : : be16_to_cpu(mask->hdr.src_port), fport);
322 : :
323 [ # # # # : 0 : if (val->hdr.dst_port || (umask && umask->hdr.dst_port))
# # ]
324 [ # # # # : 0 : CXGBE_FILL_FS(be16_to_cpu(val->hdr.dst_port),
# # # # #
# ]
325 : : be16_to_cpu(mask->hdr.dst_port), lport);
326 : :
327 : : return 0;
328 : : }
329 : :
330 : : static int
331 : 0 : ch_rte_parsetype_ipv4(const void *dmask, const struct rte_flow_item *item,
332 : : struct ch_filter_specification *fs,
333 : : struct rte_flow_error *e)
334 : : {
335 : 0 : const struct rte_flow_item_ipv4 *val = item->spec;
336 : 0 : const struct rte_flow_item_ipv4 *umask = item->mask;
337 : : const struct rte_flow_item_ipv4 *mask;
338 : :
339 [ # # ]: 0 : mask = umask ? umask : (const struct rte_flow_item_ipv4 *)dmask;
340 : :
341 [ # # ]: 0 : if (mask->hdr.time_to_live)
342 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
343 : : item, "ttl is not supported");
344 : :
345 [ # # ]: 0 : if (fs->mask.ethtype &&
346 [ # # ]: 0 : (fs->val.ethtype != RTE_ETHER_TYPE_IPV4))
347 : 0 : return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
348 : : item,
349 : : "Couldn't find IPv4 ethertype");
350 : 0 : fs->type = FILTER_TYPE_IPV4;
351 [ # # ]: 0 : if (!val)
352 : : return 0; /* ipv4 wild card */
353 : :
354 [ # # # # : 0 : if (val->hdr.next_proto_id || (umask && umask->hdr.next_proto_id))
# # ]
355 [ # # # # ]: 0 : CXGBE_FILL_FS(val->hdr.next_proto_id, mask->hdr.next_proto_id,
356 : : proto);
357 : :
358 [ # # # # : 0 : if (val->hdr.dst_addr || (umask && umask->hdr.dst_addr))
# # ]
359 : 0 : CXGBE_FILL_FS_MEMCPY(val->hdr.dst_addr, mask->hdr.dst_addr,
360 : : lip);
361 : :
362 [ # # # # : 0 : if (val->hdr.src_addr || (umask && umask->hdr.src_addr))
# # ]
363 : 0 : CXGBE_FILL_FS_MEMCPY(val->hdr.src_addr, mask->hdr.src_addr,
364 : : fip);
365 : :
366 [ # # # # : 0 : if (val->hdr.type_of_service || (umask && umask->hdr.type_of_service))
# # ]
367 [ # # # # ]: 0 : CXGBE_FILL_FS(val->hdr.type_of_service,
368 : : mask->hdr.type_of_service, tos);
369 : :
370 : : return 0;
371 : : }
372 : :
373 : : static int
374 : 0 : ch_rte_parsetype_ipv6(const void *dmask, const struct rte_flow_item *item,
375 : : struct ch_filter_specification *fs,
376 : : struct rte_flow_error *e)
377 : : {
378 : 0 : const struct rte_flow_item_ipv6 *val = item->spec;
379 : 0 : const struct rte_flow_item_ipv6 *umask = item->mask;
380 : : const struct rte_flow_item_ipv6 *mask;
381 : : u32 vtc_flow, vtc_flow_mask;
382 : 0 : u8 z[16] = { 0 };
383 : :
384 [ # # ]: 0 : mask = umask ? umask : (const struct rte_flow_item_ipv6 *)dmask;
385 : :
386 [ # # ]: 0 : vtc_flow_mask = be32_to_cpu(mask->hdr.vtc_flow);
387 : :
388 [ # # ]: 0 : if (vtc_flow_mask & RTE_IPV6_HDR_FL_MASK ||
389 [ # # ]: 0 : mask->hdr.payload_len || mask->hdr.hop_limits)
390 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
391 : : item,
392 : : "flow/hop are not supported");
393 : :
394 [ # # ]: 0 : if (fs->mask.ethtype &&
395 [ # # ]: 0 : (fs->val.ethtype != RTE_ETHER_TYPE_IPV6))
396 : 0 : return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
397 : : item,
398 : : "Couldn't find IPv6 ethertype");
399 : 0 : fs->type = FILTER_TYPE_IPV6;
400 [ # # ]: 0 : if (!val)
401 : : return 0; /* ipv6 wild card */
402 : :
403 [ # # # # : 0 : if (val->hdr.proto || (umask && umask->hdr.proto))
# # ]
404 [ # # # # ]: 0 : CXGBE_FILL_FS(val->hdr.proto, mask->hdr.proto, proto);
405 : :
406 [ # # ]: 0 : vtc_flow = be32_to_cpu(val->hdr.vtc_flow);
407 [ # # # # : 0 : if (val->hdr.vtc_flow || (umask && umask->hdr.vtc_flow))
# # ]
408 [ # # # # ]: 0 : CXGBE_FILL_FS((vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
409 : : RTE_IPV6_HDR_TC_SHIFT,
410 : : (vtc_flow_mask & RTE_IPV6_HDR_TC_MASK) >>
411 : : RTE_IPV6_HDR_TC_SHIFT,
412 : : tos);
413 : :
414 [ # # # # ]: 0 : if (memcmp(&val->hdr.dst_addr, z, sizeof(val->hdr.dst_addr)) ||
415 : 0 : (umask &&
416 [ # # ]: 0 : memcmp(&umask->hdr.dst_addr, z, sizeof(umask->hdr.dst_addr))))
417 : 0 : CXGBE_FILL_FS_MEMCPY(val->hdr.dst_addr, mask->hdr.dst_addr,
418 : : lip);
419 : :
420 [ # # # # ]: 0 : if (memcmp(&val->hdr.src_addr, z, sizeof(val->hdr.src_addr)) ||
421 : 0 : (umask &&
422 [ # # ]: 0 : memcmp(&umask->hdr.src_addr, z, sizeof(umask->hdr.src_addr))))
423 : 0 : CXGBE_FILL_FS_MEMCPY(val->hdr.src_addr, mask->hdr.src_addr,
424 : : fip);
425 : :
426 : : return 0;
427 : : }
428 : :
429 : : static int
430 : 0 : cxgbe_rtef_parse_attr(struct rte_flow *flow, const struct rte_flow_attr *attr,
431 : : struct rte_flow_error *e)
432 : : {
433 [ # # ]: 0 : if (attr->egress)
434 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR,
435 : : attr, "attribute:<egress> is"
436 : : " not supported !");
437 [ # # ]: 0 : if (attr->group > 0)
438 : 0 : return rte_flow_error_set(e, ENOTSUP, RTE_FLOW_ERROR_TYPE_ATTR,
439 : : attr, "group parameter is"
440 : : " not supported.");
441 : :
442 [ # # ]: 0 : flow->fidx = attr->priority ? attr->priority - 1 : FILTER_ID_MAX;
443 : :
444 : 0 : return 0;
445 : : }
446 : :
447 : : static inline int check_rxq(struct rte_eth_dev *dev, uint16_t rxq)
448 : : {
449 : : struct port_info *pi = ethdev2pinfo(dev);
450 : :
451 [ # # ]: 0 : if (rxq > pi->n_rx_qsets)
452 : : return -EINVAL;
453 : : return 0;
454 : : }
455 : :
456 : 0 : static int cxgbe_validate_fidxondel(struct filter_entry *f, unsigned int fidx)
457 : : {
458 [ # # ]: 0 : struct adapter *adap = ethdev2adap(f->dev);
459 : 0 : struct ch_filter_specification fs = f->fs;
460 : : u8 nentries;
461 : :
462 [ # # ]: 0 : if (fidx >= adap->tids.nftids) {
463 : 0 : dev_err(adap, "invalid flow index %d.\n", fidx);
464 : 0 : return -EINVAL;
465 : : }
466 : :
467 : 0 : nentries = cxgbe_filter_slots(adap, fs.type);
468 [ # # ]: 0 : if (!cxgbe_is_filter_set(&adap->tids, fidx, nentries)) {
469 : 0 : dev_err(adap, "Already free fidx:%d f:%p\n", fidx, f);
470 : 0 : return -EINVAL;
471 : : }
472 : :
473 : : return 0;
474 : : }
475 : :
476 : : static int
477 : 0 : cxgbe_validate_fidxonadd(struct ch_filter_specification *fs,
478 : : struct adapter *adap, unsigned int fidx)
479 : : {
480 : : u8 nentries;
481 : :
482 : 0 : nentries = cxgbe_filter_slots(adap, fs->type);
483 [ # # ]: 0 : if (cxgbe_is_filter_set(&adap->tids, fidx, nentries)) {
484 : 0 : dev_err(adap, "filter index: %d is busy.\n", fidx);
485 : 0 : return -EBUSY;
486 : : }
487 : :
488 [ # # ]: 0 : if (fidx >= adap->tids.nftids) {
489 : 0 : dev_err(adap, "filter index (%u) >= max(%u)\n",
490 : : fidx, adap->tids.nftids);
491 : 0 : return -ERANGE;
492 : : }
493 : :
494 : : return 0;
495 : : }
496 : :
497 : : static int
498 : 0 : cxgbe_verify_fidx(struct rte_flow *flow, unsigned int fidx, uint8_t del)
499 : : {
500 [ # # ]: 0 : if (flow->fs.cap)
501 : : return 0; /* Hash filters */
502 [ # # ]: 0 : return del ? cxgbe_validate_fidxondel(flow->f, fidx) :
503 : 0 : cxgbe_validate_fidxonadd(&flow->fs,
504 : 0 : ethdev2adap(flow->dev), fidx);
505 : : }
506 : :
507 : 0 : static int cxgbe_get_fidx(struct rte_flow *flow, unsigned int *fidx)
508 : : {
509 : : struct ch_filter_specification *fs = &flow->fs;
510 [ # # ]: 0 : struct adapter *adap = ethdev2adap(flow->dev);
511 : :
512 : : /* For tcam get the next available slot, if default value specified */
513 [ # # ]: 0 : if (flow->fidx == FILTER_ID_MAX) {
514 : : u8 nentries;
515 : : int idx;
516 : :
517 : 0 : nentries = cxgbe_filter_slots(adap, fs->type);
518 : 0 : idx = cxgbe_alloc_ftid(adap, nentries);
519 [ # # ]: 0 : if (idx < 0) {
520 : 0 : dev_err(adap, "unable to get a filter index in tcam\n");
521 : 0 : return -ENOMEM;
522 : : }
523 : 0 : *fidx = (unsigned int)idx;
524 : : } else {
525 : 0 : *fidx = flow->fidx;
526 : : }
527 : :
528 : : return 0;
529 : : }
530 : :
531 : : static int
532 : : cxgbe_get_flow_item_index(const struct rte_flow_item items[], u32 type)
533 : : {
534 : : const struct rte_flow_item *i;
535 : : int j, index = -ENOENT;
536 : :
537 [ # # # # : 0 : for (i = items, j = 0; i->type != RTE_FLOW_ITEM_TYPE_END; i++, j++) {
# # # # #
# # # # #
# # # # #
# # # ]
538 [ # # # # : 0 : if (i->type == type) {
# # # # #
# # # # #
# # # # #
# # # ]
539 : : index = j;
540 : : break;
541 : : }
542 : : }
543 : :
544 : : return index;
545 : : }
546 : :
547 : : static int
548 : 0 : ch_rte_parse_nat(uint8_t nmode, struct ch_filter_specification *fs)
549 : : {
550 : : /* nmode:
551 : : * BIT_0 = [src_ip], BIT_1 = [dst_ip]
552 : : * BIT_2 = [src_port], BIT_3 = [dst_port]
553 : : *
554 : : * Only below cases are supported as per our spec.
555 : : */
556 [ # # # # : 0 : switch (nmode) {
# # # #
# ]
557 : 0 : case 0: /* 0000b */
558 : 0 : fs->nat_mode = NAT_MODE_NONE;
559 : 0 : break;
560 : 0 : case 2: /* 0010b */
561 : 0 : fs->nat_mode = NAT_MODE_DIP;
562 : 0 : break;
563 : 0 : case 5: /* 0101b */
564 : 0 : fs->nat_mode = NAT_MODE_SIP_SP;
565 : 0 : break;
566 : 0 : case 7: /* 0111b */
567 : 0 : fs->nat_mode = NAT_MODE_DIP_SIP_SP;
568 : 0 : break;
569 : 0 : case 10: /* 1010b */
570 : 0 : fs->nat_mode = NAT_MODE_DIP_DP;
571 : 0 : break;
572 : 0 : case 11: /* 1011b */
573 : 0 : fs->nat_mode = NAT_MODE_DIP_DP_SIP;
574 : 0 : break;
575 : 0 : case 14: /* 1110b */
576 : 0 : fs->nat_mode = NAT_MODE_DIP_DP_SP;
577 : 0 : break;
578 : 0 : case 15: /* 1111b */
579 : 0 : fs->nat_mode = NAT_MODE_ALL;
580 : 0 : break;
581 : : default:
582 : : return -EINVAL;
583 : : }
584 : :
585 : : return 0;
586 : : }
587 : :
588 : : static int
589 : 0 : ch_rte_parse_atype_switch(const struct rte_flow_action *a,
590 : : const struct rte_flow_item items[],
591 : : uint8_t *nmode,
592 : : struct ch_filter_specification *fs,
593 : : struct rte_flow_error *e)
594 : : {
595 : : const struct rte_flow_action_of_set_vlan_vid *vlanid;
596 : : const struct rte_flow_action_of_set_vlan_pcp *vlanpcp;
597 : : const struct rte_flow_action_of_push_vlan *pushvlan;
598 : : const struct rte_flow_action_set_ipv4 *ipv4;
599 : : const struct rte_flow_action_set_ipv6 *ipv6;
600 : : const struct rte_flow_action_set_tp *tp_port;
601 : : const struct rte_flow_action_set_mac *mac;
602 : : int item_index;
603 : : u16 tmp_vlan;
604 : :
605 [ # # # # : 0 : switch (a->type) {
# # # # #
# # # #
# ]
606 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
607 : 0 : vlanid = (const struct rte_flow_action_of_set_vlan_vid *)
608 : : a->conf;
609 : : /* If explicitly asked to push a new VLAN header,
610 : : * then don't set rewrite mode. Otherwise, the
611 : : * incoming VLAN packets will get their VLAN fields
612 : : * rewritten, instead of adding an additional outer
613 : : * VLAN header.
614 : : */
615 [ # # ]: 0 : if (fs->newvlan != VLAN_INSERT)
616 : 0 : fs->newvlan = VLAN_REWRITE;
617 : 0 : tmp_vlan = fs->vlan & 0xe000;
618 [ # # ]: 0 : fs->vlan = (be16_to_cpu(vlanid->vlan_vid) & 0xfff) | tmp_vlan;
619 : 0 : break;
620 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
621 : 0 : vlanpcp = (const struct rte_flow_action_of_set_vlan_pcp *)
622 : : a->conf;
623 : : /* If explicitly asked to push a new VLAN header,
624 : : * then don't set rewrite mode. Otherwise, the
625 : : * incoming VLAN packets will get their VLAN fields
626 : : * rewritten, instead of adding an additional outer
627 : : * VLAN header.
628 : : */
629 [ # # ]: 0 : if (fs->newvlan != VLAN_INSERT)
630 : 0 : fs->newvlan = VLAN_REWRITE;
631 : 0 : tmp_vlan = fs->vlan & 0xfff;
632 : 0 : fs->vlan = (vlanpcp->vlan_pcp << 13) | tmp_vlan;
633 : 0 : break;
634 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
635 : 0 : pushvlan = (const struct rte_flow_action_of_push_vlan *)
636 : : a->conf;
637 [ # # # # ]: 0 : if (be16_to_cpu(pushvlan->ethertype) != RTE_ETHER_TYPE_VLAN)
638 : 0 : return rte_flow_error_set(e, EINVAL,
639 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
640 : : "only ethertype 0x8100 "
641 : : "supported for push vlan.");
642 : 0 : fs->newvlan = VLAN_INSERT;
643 : 0 : break;
644 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
645 : 0 : fs->newvlan = VLAN_REMOVE;
646 : 0 : break;
647 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
648 : : item_index = cxgbe_get_flow_item_index(items,
649 : : RTE_FLOW_ITEM_TYPE_IPV4);
650 [ # # ]: 0 : if (item_index < 0)
651 : 0 : return rte_flow_error_set(e, EINVAL,
652 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
653 : : "No RTE_FLOW_ITEM_TYPE_IPV4 "
654 : : "found.");
655 : :
656 : 0 : ipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;
657 : 0 : memcpy(fs->nat_fip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
658 : 0 : *nmode |= 1 << 0;
659 : 0 : break;
660 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
661 : : item_index = cxgbe_get_flow_item_index(items,
662 : : RTE_FLOW_ITEM_TYPE_IPV4);
663 [ # # ]: 0 : if (item_index < 0)
664 : 0 : return rte_flow_error_set(e, EINVAL,
665 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
666 : : "No RTE_FLOW_ITEM_TYPE_IPV4 "
667 : : "found.");
668 : :
669 : 0 : ipv4 = (const struct rte_flow_action_set_ipv4 *)a->conf;
670 : 0 : memcpy(fs->nat_lip, &ipv4->ipv4_addr, sizeof(ipv4->ipv4_addr));
671 : 0 : *nmode |= 1 << 1;
672 : 0 : break;
673 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
674 : : item_index = cxgbe_get_flow_item_index(items,
675 : : RTE_FLOW_ITEM_TYPE_IPV6);
676 [ # # ]: 0 : if (item_index < 0)
677 : 0 : return rte_flow_error_set(e, EINVAL,
678 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
679 : : "No RTE_FLOW_ITEM_TYPE_IPV6 "
680 : : "found.");
681 : :
682 : 0 : ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
683 : 0 : memcpy(fs->nat_fip, &ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
684 : 0 : *nmode |= 1 << 0;
685 : 0 : break;
686 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
687 : : item_index = cxgbe_get_flow_item_index(items,
688 : : RTE_FLOW_ITEM_TYPE_IPV6);
689 [ # # ]: 0 : if (item_index < 0)
690 : 0 : return rte_flow_error_set(e, EINVAL,
691 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
692 : : "No RTE_FLOW_ITEM_TYPE_IPV6 "
693 : : "found.");
694 : :
695 : 0 : ipv6 = (const struct rte_flow_action_set_ipv6 *)a->conf;
696 : 0 : memcpy(fs->nat_lip, &ipv6->ipv6_addr, sizeof(ipv6->ipv6_addr));
697 : 0 : *nmode |= 1 << 1;
698 : 0 : break;
699 : : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
700 : : item_index = cxgbe_get_flow_item_index(items,
701 : : RTE_FLOW_ITEM_TYPE_TCP);
702 [ # # ]: 0 : if (item_index < 0) {
703 : : item_index =
704 : : cxgbe_get_flow_item_index(items,
705 : : RTE_FLOW_ITEM_TYPE_UDP);
706 [ # # ]: 0 : if (item_index < 0)
707 : 0 : return rte_flow_error_set(e, EINVAL,
708 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
709 : : "No RTE_FLOW_ITEM_TYPE_TCP or "
710 : : "RTE_FLOW_ITEM_TYPE_UDP found");
711 : : }
712 : :
713 : 0 : tp_port = (const struct rte_flow_action_set_tp *)a->conf;
714 [ # # ]: 0 : fs->nat_fport = be16_to_cpu(tp_port->port);
715 : 0 : *nmode |= 1 << 2;
716 : 0 : break;
717 : : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
718 : : item_index = cxgbe_get_flow_item_index(items,
719 : : RTE_FLOW_ITEM_TYPE_TCP);
720 [ # # ]: 0 : if (item_index < 0) {
721 : : item_index =
722 : : cxgbe_get_flow_item_index(items,
723 : : RTE_FLOW_ITEM_TYPE_UDP);
724 [ # # ]: 0 : if (item_index < 0)
725 : 0 : return rte_flow_error_set(e, EINVAL,
726 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
727 : : "No RTE_FLOW_ITEM_TYPE_TCP or "
728 : : "RTE_FLOW_ITEM_TYPE_UDP found");
729 : : }
730 : :
731 : 0 : tp_port = (const struct rte_flow_action_set_tp *)a->conf;
732 [ # # ]: 0 : fs->nat_lport = be16_to_cpu(tp_port->port);
733 : 0 : *nmode |= 1 << 3;
734 : 0 : break;
735 : : case RTE_FLOW_ACTION_TYPE_MAC_SWAP:
736 : : item_index = cxgbe_get_flow_item_index(items,
737 : : RTE_FLOW_ITEM_TYPE_ETH);
738 [ # # ]: 0 : if (item_index < 0)
739 : 0 : return rte_flow_error_set(e, EINVAL,
740 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
741 : : "No RTE_FLOW_ITEM_TYPE_ETH "
742 : : "found");
743 : 0 : fs->swapmac = 1;
744 : 0 : break;
745 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
746 : : item_index = cxgbe_get_flow_item_index(items,
747 : : RTE_FLOW_ITEM_TYPE_ETH);
748 [ # # ]: 0 : if (item_index < 0)
749 : 0 : return rte_flow_error_set(e, EINVAL,
750 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
751 : : "No RTE_FLOW_ITEM_TYPE_ETH "
752 : : "found");
753 : 0 : mac = (const struct rte_flow_action_set_mac *)a->conf;
754 : :
755 : 0 : fs->newsmac = 1;
756 : 0 : memcpy(fs->smac, mac->mac_addr, sizeof(fs->smac));
757 : : break;
758 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
759 : : item_index = cxgbe_get_flow_item_index(items,
760 : : RTE_FLOW_ITEM_TYPE_ETH);
761 [ # # ]: 0 : if (item_index < 0)
762 : 0 : return rte_flow_error_set(e, EINVAL,
763 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
764 : : "No RTE_FLOW_ITEM_TYPE_ETH found");
765 : 0 : mac = (const struct rte_flow_action_set_mac *)a->conf;
766 : :
767 : 0 : fs->newdmac = 1;
768 : 0 : memcpy(fs->dmac, mac->mac_addr, sizeof(fs->dmac));
769 : : break;
770 : 0 : default:
771 : : /* We are not supposed to come here */
772 : 0 : return rte_flow_error_set(e, EINVAL,
773 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
774 : : "Action not supported");
775 : : }
776 : :
777 : : return 0;
778 : : }
779 : :
780 : : static int
781 : 0 : cxgbe_rtef_parse_actions(struct rte_flow *flow,
782 : : const struct rte_flow_item items[],
783 : : const struct rte_flow_action action[],
784 : : struct rte_flow_error *e)
785 : : {
786 : 0 : struct ch_filter_specification *fs = &flow->fs;
787 : 0 : uint8_t nmode = 0, nat_ipv4 = 0, nat_ipv6 = 0;
788 : : uint8_t vlan_set_vid = 0, vlan_set_pcp = 0;
789 : : const struct rte_flow_action_queue *q;
790 : : const struct rte_flow_action *a;
791 : : char abit = 0;
792 : : int ret;
793 : :
794 [ # # ]: 0 : for (a = action; a->type != RTE_FLOW_ACTION_TYPE_END; a++) {
795 [ # # # # : 0 : switch (a->type) {
# # # # #
# ]
796 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
797 : 0 : continue;
798 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
799 [ # # ]: 0 : if (abit++)
800 : 0 : return rte_flow_error_set(e, EINVAL,
801 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
802 : : "specify only 1 pass/drop");
803 : 0 : fs->action = FILTER_DROP;
804 : 0 : break;
805 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
806 : 0 : q = (const struct rte_flow_action_queue *)a->conf;
807 [ # # ]: 0 : if (!q)
808 : 0 : return rte_flow_error_set(e, EINVAL,
809 : : RTE_FLOW_ERROR_TYPE_ACTION, q,
810 : : "specify rx queue index");
811 [ # # ]: 0 : if (check_rxq(flow->dev, q->index))
812 : 0 : return rte_flow_error_set(e, EINVAL,
813 : : RTE_FLOW_ERROR_TYPE_ACTION, q,
814 : : "Invalid rx queue");
815 [ # # ]: 0 : if (abit++)
816 : 0 : return rte_flow_error_set(e, EINVAL,
817 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
818 : : "specify only 1 pass/drop");
819 : 0 : fs->action = FILTER_PASS;
820 : 0 : fs->dirsteer = 1;
821 : 0 : fs->iq = q->index;
822 : 0 : break;
823 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
824 : 0 : fs->hitcnts = 1;
825 : 0 : break;
826 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
827 : 0 : vlan_set_vid++;
828 : 0 : goto action_switch;
829 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
830 : 0 : vlan_set_pcp++;
831 : 0 : goto action_switch;
832 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
833 : : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
834 : : case RTE_FLOW_ACTION_TYPE_MAC_SWAP:
835 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
836 : : case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
837 : 0 : nat_ipv4++;
838 : 0 : goto action_switch;
839 : 0 : case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
840 : : case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
841 : 0 : nat_ipv6++;
842 : 0 : goto action_switch;
843 : : case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
844 : : case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
845 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
846 : : case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
847 : 0 : action_switch:
848 : : /* We allow multiple switch actions, but switch is
849 : : * not compatible with either queue or drop
850 : : */
851 [ # # # # ]: 0 : if (abit++ && fs->action != FILTER_SWITCH)
852 : 0 : return rte_flow_error_set(e, EINVAL,
853 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
854 : : "overlapping action specified");
855 [ # # ]: 0 : if (nat_ipv4 && nat_ipv6)
856 : 0 : return rte_flow_error_set(e, EINVAL,
857 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
858 : : "Can't have one address ipv4 and the"
859 : : " other ipv6");
860 : :
861 : 0 : ret = ch_rte_parse_atype_switch(a, items, &nmode, fs,
862 : : e);
863 [ # # ]: 0 : if (ret)
864 : 0 : return ret;
865 : 0 : fs->action = FILTER_SWITCH;
866 : 0 : break;
867 : 0 : default:
868 : : /* Not supported action : return error */
869 : 0 : return rte_flow_error_set(e, ENOTSUP,
870 : : RTE_FLOW_ERROR_TYPE_ACTION,
871 : : a, "Action not supported");
872 : : }
873 : : }
874 : :
875 [ # # # # ]: 0 : if (fs->newvlan == VLAN_REWRITE && (!vlan_set_vid || !vlan_set_pcp))
876 : 0 : return rte_flow_error_set(e, EINVAL,
877 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
878 : : "Both OF_SET_VLAN_VID and "
879 : : "OF_SET_VLAN_PCP must be specified");
880 : :
881 [ # # ]: 0 : if (ch_rte_parse_nat(nmode, fs))
882 : 0 : return rte_flow_error_set(e, EINVAL,
883 : : RTE_FLOW_ERROR_TYPE_ACTION, a,
884 : : "invalid settings for swich action");
885 : : return 0;
886 : : }
887 : :
888 : : static struct chrte_fparse parseitem[] = {
889 : : [RTE_FLOW_ITEM_TYPE_ETH] = {
890 : : .fptr = ch_rte_parsetype_eth,
891 : : .dmask = &(const struct rte_flow_item_eth){
892 : : .hdr.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
893 : : .hdr.src_addr.addr_bytes = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
894 : : .hdr.ether_type = 0xffff,
895 : : }
896 : : },
897 : :
898 : : [RTE_FLOW_ITEM_TYPE_VLAN] = {
899 : : .fptr = ch_rte_parsetype_vlan,
900 : : .dmask = &(const struct rte_flow_item_vlan){
901 : : .hdr.vlan_tci = 0xffff,
902 : : .hdr.eth_proto = 0xffff,
903 : : }
904 : : },
905 : :
906 : : [RTE_FLOW_ITEM_TYPE_IPV4] = {
907 : : .fptr = ch_rte_parsetype_ipv4,
908 : : .dmask = &(const struct rte_flow_item_ipv4) {
909 : : .hdr = {
910 : : .src_addr = RTE_BE32(0xffffffff),
911 : : .dst_addr = RTE_BE32(0xffffffff),
912 : : .type_of_service = 0xff,
913 : : },
914 : : },
915 : : },
916 : :
917 : : [RTE_FLOW_ITEM_TYPE_IPV6] = {
918 : : .fptr = ch_rte_parsetype_ipv6,
919 : : .dmask = &(const struct rte_flow_item_ipv6) {
920 : : .hdr = {
921 : : .src_addr = RTE_IPV6_MASK_FULL,
922 : : .dst_addr = RTE_IPV6_MASK_FULL,
923 : : .vtc_flow = RTE_BE32(0xff000000),
924 : : },
925 : : },
926 : : },
927 : :
928 : : [RTE_FLOW_ITEM_TYPE_UDP] = {
929 : : .fptr = ch_rte_parsetype_udp,
930 : : .dmask = &rte_flow_item_udp_mask,
931 : : },
932 : :
933 : : [RTE_FLOW_ITEM_TYPE_TCP] = {
934 : : .fptr = ch_rte_parsetype_tcp,
935 : : .dmask = &rte_flow_item_tcp_mask,
936 : : },
937 : : };
938 : :
939 : : static int
940 : 0 : cxgbe_rtef_parse_items(struct rte_flow *flow,
941 : : const struct rte_flow_item items[],
942 : : struct rte_flow_error *e)
943 : : {
944 : 0 : struct adapter *adap = ethdev2adap(flow->dev);
945 : : const struct rte_flow_item *i;
946 : 0 : char repeat[ARRAY_SIZE(parseitem)] = {0};
947 : :
948 [ # # ]: 0 : for (i = items; i->type != RTE_FLOW_ITEM_TYPE_END; i++) {
949 : : struct chrte_fparse *idx;
950 : : int ret;
951 : :
952 [ # # ]: 0 : if (i->type >= ARRAY_SIZE(parseitem))
953 : 0 : return rte_flow_error_set(e, ENOTSUP,
954 : : RTE_FLOW_ERROR_TYPE_ITEM,
955 : : i, "Item not supported");
956 : :
957 [ # # ]: 0 : switch (i->type) {
958 : 0 : case RTE_FLOW_ITEM_TYPE_VOID:
959 : 0 : continue;
960 : 0 : default:
961 : : /* check if item is repeated */
962 [ # # # # ]: 0 : if (repeat[i->type] &&
963 : : i->type != RTE_FLOW_ITEM_TYPE_VLAN)
964 : 0 : return rte_flow_error_set(e, ENOTSUP,
965 : : RTE_FLOW_ERROR_TYPE_ITEM, i,
966 : : "parse items cannot be repeated(except void/vlan)");
967 : :
968 : 0 : repeat[i->type] = 1;
969 : :
970 : : /* validate the item */
971 : 0 : ret = cxgbe_validate_item(i, e);
972 [ # # ]: 0 : if (ret)
973 : 0 : return ret;
974 : :
975 : 0 : idx = &flow->item_parser[i->type];
976 [ # # # # ]: 0 : if (!idx || !idx->fptr) {
977 : 0 : return rte_flow_error_set(e, ENOTSUP,
978 : : RTE_FLOW_ERROR_TYPE_ITEM, i,
979 : : "Item not supported");
980 : : } else {
981 : 0 : ret = idx->fptr(idx->dmask, i, &flow->fs, e);
982 [ # # ]: 0 : if (ret)
983 : 0 : return ret;
984 : : }
985 : : }
986 : : }
987 : :
988 : 0 : cxgbe_tweak_filter_spec(adap, &flow->fs);
989 : 0 : cxgbe_fill_filter_region(adap, &flow->fs);
990 : :
991 : 0 : return 0;
992 : : }
993 : :
994 : : static int
995 : 0 : cxgbe_flow_parse(struct rte_flow *flow,
996 : : const struct rte_flow_attr *attr,
997 : : const struct rte_flow_item item[],
998 : : const struct rte_flow_action action[],
999 : : struct rte_flow_error *e)
1000 : : {
1001 : : int ret;
1002 : : /* parse user request into ch_filter_specification */
1003 : 0 : ret = cxgbe_rtef_parse_attr(flow, attr, e);
1004 [ # # ]: 0 : if (ret)
1005 : : return ret;
1006 : 0 : ret = cxgbe_rtef_parse_items(flow, item, e);
1007 [ # # ]: 0 : if (ret)
1008 : : return ret;
1009 : 0 : return cxgbe_rtef_parse_actions(flow, item, action, e);
1010 : : }
1011 : :
1012 : 0 : static int __cxgbe_flow_create(struct rte_eth_dev *dev, struct rte_flow *flow)
1013 : : {
1014 : 0 : struct ch_filter_specification *fs = &flow->fs;
1015 : : struct adapter *adap = ethdev2adap(dev);
1016 : : struct tid_info *t = &adap->tids;
1017 : : struct filter_ctx ctx;
1018 : : unsigned int fidx;
1019 : : int err;
1020 : :
1021 [ # # ]: 0 : if (cxgbe_get_fidx(flow, &fidx))
1022 : : return -ENOMEM;
1023 [ # # ]: 0 : if (cxgbe_verify_fidx(flow, fidx, 0))
1024 : : return -1;
1025 : :
1026 : : t4_init_completion(&ctx.completion);
1027 : : /* go create the filter */
1028 : 0 : err = cxgbe_set_filter(dev, fidx, fs, &ctx);
1029 [ # # ]: 0 : if (err) {
1030 : 0 : dev_err(adap, "Error %d while creating filter.\n", err);
1031 : 0 : return err;
1032 : : }
1033 : :
1034 : : /* Poll the FW for reply */
1035 : 0 : err = cxgbe_poll_for_completion(&adap->sge.fw_evtq,
1036 : : CXGBE_FLOW_POLL_MS,
1037 : : CXGBE_FLOW_POLL_CNT,
1038 : : &ctx.completion);
1039 [ # # ]: 0 : if (err) {
1040 : 0 : dev_err(adap, "Filter set operation timed out (%d)\n", err);
1041 : 0 : return err;
1042 : : }
1043 [ # # ]: 0 : if (ctx.result) {
1044 : 0 : dev_err(adap, "Hardware error %d while creating the filter.\n",
1045 : : ctx.result);
1046 : 0 : return ctx.result;
1047 : : }
1048 : :
1049 [ # # ]: 0 : if (fs->cap) { /* to destroy the filter */
1050 [ # # ]: 0 : flow->fidx = ctx.tid;
1051 : 0 : flow->f = lookup_tid(t, ctx.tid);
1052 : : } else {
1053 : 0 : flow->fidx = fidx;
1054 : 0 : flow->f = &adap->tids.ftid_tab[fidx];
1055 : : }
1056 : :
1057 : : return 0;
1058 : : }
1059 : :
1060 : : static struct rte_flow *
1061 : 0 : cxgbe_flow_create(struct rte_eth_dev *dev,
1062 : : const struct rte_flow_attr *attr,
1063 : : const struct rte_flow_item item[],
1064 : : const struct rte_flow_action action[],
1065 : : struct rte_flow_error *e)
1066 : : {
1067 : : struct adapter *adap = ethdev2adap(dev);
1068 : : struct rte_flow *flow;
1069 : : int ret;
1070 : :
1071 : 0 : flow = t4_os_alloc(sizeof(struct rte_flow));
1072 [ # # ]: 0 : if (!flow) {
1073 : 0 : rte_flow_error_set(e, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1074 : : NULL, "Unable to allocate memory for"
1075 : : " filter_entry");
1076 : 0 : return NULL;
1077 : : }
1078 : :
1079 : 0 : flow->item_parser = parseitem;
1080 : 0 : flow->dev = dev;
1081 : 0 : flow->fs.private = (void *)flow;
1082 : :
1083 [ # # ]: 0 : if (cxgbe_flow_parse(flow, attr, item, action, e)) {
1084 : 0 : t4_os_free(flow);
1085 : 0 : return NULL;
1086 : : }
1087 : :
1088 : 0 : t4_os_lock(&adap->flow_lock);
1089 : : /* go, interact with cxgbe_filter */
1090 : 0 : ret = __cxgbe_flow_create(dev, flow);
1091 : : t4_os_unlock(&adap->flow_lock);
1092 [ # # ]: 0 : if (ret) {
1093 : 0 : rte_flow_error_set(e, ret, RTE_FLOW_ERROR_TYPE_HANDLE,
1094 : : NULL, "Unable to create flow rule");
1095 : 0 : t4_os_free(flow);
1096 : 0 : return NULL;
1097 : : }
1098 : :
1099 : 0 : flow->f->private = flow; /* Will be used during flush */
1100 : :
1101 : 0 : return flow;
1102 : : }
1103 : :
1104 : 0 : static int __cxgbe_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
1105 : : {
1106 : : struct adapter *adap = ethdev2adap(dev);
1107 : 0 : struct filter_entry *f = flow->f;
1108 : : struct ch_filter_specification *fs;
1109 : : struct filter_ctx ctx;
1110 : : int err;
1111 : :
1112 : 0 : fs = &f->fs;
1113 [ # # ]: 0 : if (cxgbe_verify_fidx(flow, flow->fidx, 1))
1114 : : return -1;
1115 : :
1116 : : t4_init_completion(&ctx.completion);
1117 : 0 : err = cxgbe_del_filter(dev, flow->fidx, fs, &ctx);
1118 [ # # ]: 0 : if (err) {
1119 : 0 : dev_err(adap, "Error %d while deleting filter.\n", err);
1120 : 0 : return err;
1121 : : }
1122 : :
1123 : : /* Poll the FW for reply */
1124 : 0 : err = cxgbe_poll_for_completion(&adap->sge.fw_evtq,
1125 : : CXGBE_FLOW_POLL_MS,
1126 : : CXGBE_FLOW_POLL_CNT,
1127 : : &ctx.completion);
1128 [ # # ]: 0 : if (err) {
1129 : 0 : dev_err(adap, "Filter delete operation timed out (%d)\n", err);
1130 : 0 : return err;
1131 : : }
1132 [ # # ]: 0 : if (ctx.result) {
1133 : 0 : dev_err(adap, "Hardware error %d while deleting the filter.\n",
1134 : : ctx.result);
1135 : 0 : return ctx.result;
1136 : : }
1137 : :
1138 : : return 0;
1139 : : }
1140 : :
1141 : : static int
1142 : 0 : cxgbe_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
1143 : : struct rte_flow_error *e)
1144 : : {
1145 : : struct adapter *adap = ethdev2adap(dev);
1146 : : int ret;
1147 : :
1148 : 0 : t4_os_lock(&adap->flow_lock);
1149 : 0 : ret = __cxgbe_flow_destroy(dev, flow);
1150 : : t4_os_unlock(&adap->flow_lock);
1151 [ # # ]: 0 : if (ret)
1152 : 0 : return rte_flow_error_set(e, ret, RTE_FLOW_ERROR_TYPE_HANDLE,
1153 : : flow, "error destroying filter.");
1154 : 0 : t4_os_free(flow);
1155 : 0 : return 0;
1156 : : }
1157 : :
1158 : 0 : static int __cxgbe_flow_query(struct rte_flow *flow, u64 *count,
1159 : : u64 *byte_count)
1160 : : {
1161 : 0 : struct adapter *adap = ethdev2adap(flow->dev);
1162 : 0 : struct ch_filter_specification fs = flow->f->fs;
1163 : 0 : unsigned int fidx = flow->fidx;
1164 : : int ret = 0;
1165 : :
1166 : 0 : ret = cxgbe_get_filter_count(adap, fidx, count, fs.cap, 0);
1167 [ # # ]: 0 : if (ret)
1168 : : return ret;
1169 : 0 : return cxgbe_get_filter_count(adap, fidx, byte_count, fs.cap, 1);
1170 : : }
1171 : :
1172 : : static int
1173 : 0 : cxgbe_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
1174 : : const struct rte_flow_action *action, void *data,
1175 : : struct rte_flow_error *e)
1176 : : {
1177 [ # # ]: 0 : struct adapter *adap = ethdev2adap(flow->dev);
1178 : : struct ch_filter_specification fs;
1179 : : struct rte_flow_query_count *c;
1180 : : struct filter_entry *f;
1181 : : int ret;
1182 : :
1183 : : RTE_SET_USED(dev);
1184 : :
1185 : 0 : f = flow->f;
1186 : 0 : fs = f->fs;
1187 : :
1188 [ # # ]: 0 : if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
1189 : 0 : return rte_flow_error_set(e, ENOTSUP,
1190 : : RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1191 : : "only count supported for query");
1192 : :
1193 : : /*
1194 : : * This is a valid operation, Since we are allowed to do chelsio
1195 : : * specific operations in rte side of our code but not vise-versa
1196 : : *
1197 : : * So, fs can be queried/modified here BUT rte_flow_query_count
1198 : : * cannot be worked on by the lower layer since we want to maintain
1199 : : * it as rte_flow agnostic.
1200 : : */
1201 [ # # ]: 0 : if (!fs.hitcnts)
1202 : 0 : return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
1203 : : &fs, "filter hit counters were not"
1204 : : " enabled during filter creation");
1205 : :
1206 : : c = (struct rte_flow_query_count *)data;
1207 : :
1208 : 0 : t4_os_lock(&adap->flow_lock);
1209 : 0 : ret = __cxgbe_flow_query(flow, &c->hits, &c->bytes);
1210 [ # # ]: 0 : if (ret) {
1211 : 0 : rte_flow_error_set(e, -ret, RTE_FLOW_ERROR_TYPE_ACTION,
1212 : : f, "cxgbe pmd failed to perform query");
1213 : 0 : goto out;
1214 : : }
1215 : :
1216 : : /* Query was successful */
1217 : 0 : c->bytes_set = 1;
1218 : 0 : c->hits_set = 1;
1219 [ # # ]: 0 : if (c->reset)
1220 : 0 : cxgbe_clear_filter_count(adap, flow->fidx, f->fs.cap, true);
1221 : :
1222 : 0 : out:
1223 : : t4_os_unlock(&adap->flow_lock);
1224 : 0 : return ret;
1225 : : }
1226 : :
1227 : : static int
1228 : 0 : cxgbe_flow_validate(struct rte_eth_dev *dev,
1229 : : const struct rte_flow_attr *attr,
1230 : : const struct rte_flow_item item[],
1231 : : const struct rte_flow_action action[],
1232 : : struct rte_flow_error *e)
1233 : : {
1234 : : struct adapter *adap = ethdev2adap(dev);
1235 : : struct rte_flow *flow;
1236 : : unsigned int fidx;
1237 : : int ret = 0;
1238 : :
1239 : 0 : flow = t4_os_alloc(sizeof(struct rte_flow));
1240 [ # # ]: 0 : if (!flow)
1241 : 0 : return rte_flow_error_set(e, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1242 : : NULL,
1243 : : "Unable to allocate memory for filter_entry");
1244 : :
1245 : 0 : flow->item_parser = parseitem;
1246 : 0 : flow->dev = dev;
1247 : 0 : flow->fs.private = (void *)flow;
1248 : :
1249 : 0 : ret = cxgbe_flow_parse(flow, attr, item, action, e);
1250 [ # # ]: 0 : if (ret) {
1251 : 0 : t4_os_free(flow);
1252 : 0 : return ret;
1253 : : }
1254 : :
1255 [ # # ]: 0 : if (cxgbe_validate_filter(adap, &flow->fs)) {
1256 : 0 : t4_os_free(flow);
1257 : 0 : return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
1258 : : NULL,
1259 : : "validation failed. Check f/w config file.");
1260 : : }
1261 : :
1262 : 0 : t4_os_lock(&adap->flow_lock);
1263 [ # # ]: 0 : if (cxgbe_get_fidx(flow, &fidx)) {
1264 : 0 : ret = rte_flow_error_set(e, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1265 : : NULL, "no memory in tcam.");
1266 : 0 : goto out;
1267 : : }
1268 : :
1269 [ # # ]: 0 : if (cxgbe_verify_fidx(flow, fidx, 0)) {
1270 : 0 : ret = rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE,
1271 : : NULL, "validation failed");
1272 : 0 : goto out;
1273 : : }
1274 : :
1275 : 0 : out:
1276 : : t4_os_unlock(&adap->flow_lock);
1277 : 0 : t4_os_free(flow);
1278 : 0 : return ret;
1279 : : }
1280 : :
1281 : : /*
1282 : : * @ret : > 0 filter destroyed successfully
1283 : : * < 0 error destroying filter
1284 : : * == 1 filter not active / not found
1285 : : */
1286 : : static int
1287 : 0 : cxgbe_check_n_destroy(struct filter_entry *f, struct rte_eth_dev *dev)
1288 : : {
1289 [ # # # # ]: 0 : if (f && (f->valid || f->pending) &&
1290 [ # # ]: 0 : f->dev == dev && /* Only if user has asked for this port */
1291 [ # # ]: 0 : f->private) /* We (rte_flow) created this filter */
1292 : 0 : return __cxgbe_flow_destroy(dev, (struct rte_flow *)f->private);
1293 : : return 1;
1294 : : }
1295 : :
1296 : 0 : static int cxgbe_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *e)
1297 : : {
1298 : : struct adapter *adap = ethdev2adap(dev);
1299 : : unsigned int i;
1300 : : int ret = 0;
1301 : :
1302 : 0 : t4_os_lock(&adap->flow_lock);
1303 [ # # ]: 0 : if (adap->tids.ftid_tab) {
1304 : : struct filter_entry *f = &adap->tids.ftid_tab[0];
1305 : :
1306 [ # # ]: 0 : for (i = 0; i < adap->tids.nftids; i++, f++) {
1307 : 0 : ret = cxgbe_check_n_destroy(f, dev);
1308 [ # # ]: 0 : if (ret < 0) {
1309 : 0 : rte_flow_error_set(e, ret,
1310 : : RTE_FLOW_ERROR_TYPE_HANDLE,
1311 : 0 : f->private,
1312 : : "error destroying TCAM "
1313 : : "filter.");
1314 : 0 : goto out;
1315 : : }
1316 : : }
1317 : : }
1318 : :
1319 [ # # # # ]: 0 : if (is_hashfilter(adap) && adap->tids.tid_tab) {
1320 : : struct filter_entry *f;
1321 : :
1322 [ # # ]: 0 : for (i = adap->tids.hash_base; i <= adap->tids.ntids; i++) {
1323 : 0 : f = (struct filter_entry *)adap->tids.tid_tab[i];
1324 : :
1325 : 0 : ret = cxgbe_check_n_destroy(f, dev);
1326 [ # # ]: 0 : if (ret < 0) {
1327 : 0 : rte_flow_error_set(e, ret,
1328 : : RTE_FLOW_ERROR_TYPE_HANDLE,
1329 : 0 : f->private,
1330 : : "error destroying HASH "
1331 : : "filter.");
1332 : 0 : goto out;
1333 : : }
1334 : : }
1335 : : }
1336 : :
1337 : 0 : out:
1338 : : t4_os_unlock(&adap->flow_lock);
1339 : 0 : return ret >= 0 ? 0 : ret;
1340 : : }
1341 : :
1342 : : static const struct rte_flow_ops cxgbe_flow_ops = {
1343 : : .validate = cxgbe_flow_validate,
1344 : : .create = cxgbe_flow_create,
1345 : : .destroy = cxgbe_flow_destroy,
1346 : : .flush = cxgbe_flow_flush,
1347 : : .query = cxgbe_flow_query,
1348 : : .isolate = NULL,
1349 : : };
1350 : :
1351 : : int
1352 : 0 : cxgbe_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
1353 : : const struct rte_flow_ops **ops)
1354 : : {
1355 : 0 : *ops = &cxgbe_flow_ops;
1356 : 0 : return 0;
1357 : : }
|