Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2026 Google LLC
3 : : */
4 : :
5 : : #include <rte_flow.h>
6 : : #include <rte_flow_driver.h>
7 : : #include "base/gve_adminq.h"
8 : : #include "gve_ethdev.h"
9 : :
10 : : static int
11 : 0 : gve_validate_flow_attr(const struct rte_flow_attr *attr,
12 : : struct rte_flow_error *error)
13 : : {
14 [ # # ]: 0 : if (attr == NULL) {
15 : 0 : rte_flow_error_set(error, EINVAL,
16 : : RTE_FLOW_ERROR_TYPE_ATTR, NULL,
17 : : "Invalid flow attribute");
18 : 0 : return -EINVAL;
19 : : }
20 [ # # ]: 0 : if (attr->egress || attr->transfer) {
21 : 0 : rte_flow_error_set(error, EINVAL,
22 : : RTE_FLOW_ERROR_TYPE_ATTR, attr,
23 : : "Only ingress is supported");
24 : 0 : return -EINVAL;
25 : : }
26 [ # # ]: 0 : if (!attr->ingress) {
27 : 0 : rte_flow_error_set(error, EINVAL,
28 : : RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
29 : : "Ingress attribute must be set");
30 : 0 : return -EINVAL;
31 : : }
32 [ # # ]: 0 : if (attr->priority != 0) {
33 : 0 : rte_flow_error_set(error, EINVAL,
34 : : RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
35 : : "Priority levels are not supported");
36 : 0 : return -EINVAL;
37 : : }
38 : :
39 : : return 0;
40 : : }
41 : :
42 : : static void
43 : : gve_parse_ipv4(const struct rte_flow_item *item,
44 : : struct gve_flow_rule_params *rule)
45 : : {
46 [ # # ]: 0 : if (item->spec) {
47 : : const struct rte_flow_item_ipv4 *spec = item->spec;
48 : : const struct rte_flow_item_ipv4 *mask =
49 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_ipv4_mask;
50 : :
51 : 0 : rule->key.src_ip[0] = spec->hdr.src_addr;
52 : 0 : rule->key.dst_ip[0] = spec->hdr.dst_addr;
53 : 0 : rule->mask.src_ip[0] = mask->hdr.src_addr;
54 : 0 : rule->mask.dst_ip[0] = mask->hdr.dst_addr;
55 : : }
56 : : }
57 : :
58 : : static void
59 : 0 : gve_parse_ipv6(const struct rte_flow_item *item,
60 : : struct gve_flow_rule_params *rule)
61 : : {
62 [ # # ]: 0 : if (item->spec) {
63 : : const struct rte_flow_item_ipv6 *spec = item->spec;
64 : : const struct rte_flow_item_ipv6 *mask =
65 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_ipv6_mask;
66 : 0 : const __be32 *src_ip = (const __be32 *)&spec->hdr.src_addr;
67 : 0 : const __be32 *src_mask = (const __be32 *)&mask->hdr.src_addr;
68 : 0 : const __be32 *dst_ip = (const __be32 *)&spec->hdr.dst_addr;
69 : 0 : const __be32 *dst_mask = (const __be32 *)&mask->hdr.dst_addr;
70 : : int i;
71 : :
72 : : /*
73 : : * The device expects IPv6 addresses as an array of 4 32-bit words
74 : : * in reverse word order (the MSB word at index 3 and the LSB word
75 : : * at index 0). We must reverse the DPDK network byte order array.
76 : : */
77 [ # # ]: 0 : for (i = 0; i < 4; i++) {
78 : 0 : rule->key.src_ip[3 - i] = src_ip[i];
79 : 0 : rule->key.dst_ip[3 - i] = dst_ip[i];
80 : 0 : rule->mask.src_ip[3 - i] = src_mask[i];
81 : 0 : rule->mask.dst_ip[3 - i] = dst_mask[i];
82 : : }
83 : : }
84 : 0 : }
85 : :
86 : : static void
87 : : gve_parse_udp(const struct rte_flow_item *item,
88 : : struct gve_flow_rule_params *rule)
89 : : {
90 [ # # ]: 0 : if (item->spec) {
91 : : const struct rte_flow_item_udp *spec = item->spec;
92 : : const struct rte_flow_item_udp *mask =
93 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_udp_mask;
94 : :
95 : 0 : rule->key.src_port = spec->hdr.src_port;
96 : 0 : rule->key.dst_port = spec->hdr.dst_port;
97 : 0 : rule->mask.src_port = mask->hdr.src_port;
98 : 0 : rule->mask.dst_port = mask->hdr.dst_port;
99 : : }
100 : : }
101 : :
102 : : static void
103 : : gve_parse_tcp(const struct rte_flow_item *item,
104 : : struct gve_flow_rule_params *rule)
105 : : {
106 [ # # ]: 0 : if (item->spec) {
107 : : const struct rte_flow_item_tcp *spec = item->spec;
108 : : const struct rte_flow_item_tcp *mask =
109 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_tcp_mask;
110 : :
111 : 0 : rule->key.src_port = spec->hdr.src_port;
112 : 0 : rule->key.dst_port = spec->hdr.dst_port;
113 : 0 : rule->mask.src_port = mask->hdr.src_port;
114 : 0 : rule->mask.dst_port = mask->hdr.dst_port;
115 : : }
116 : : }
117 : :
118 : : static void
119 : : gve_parse_sctp(const struct rte_flow_item *item,
120 : : struct gve_flow_rule_params *rule)
121 : : {
122 [ # # ]: 0 : if (item->spec) {
123 : : const struct rte_flow_item_sctp *spec = item->spec;
124 : : const struct rte_flow_item_sctp *mask =
125 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_sctp_mask;
126 : :
127 : 0 : rule->key.src_port = spec->hdr.src_port;
128 : 0 : rule->key.dst_port = spec->hdr.dst_port;
129 : 0 : rule->mask.src_port = mask->hdr.src_port;
130 : 0 : rule->mask.dst_port = mask->hdr.dst_port;
131 : : }
132 : : }
133 : :
134 : : static void
135 : : gve_parse_esp(const struct rte_flow_item *item,
136 : : struct gve_flow_rule_params *rule)
137 : : {
138 [ # # ]: 0 : if (item->spec) {
139 : : const struct rte_flow_item_esp *spec = item->spec;
140 : : const struct rte_flow_item_esp *mask =
141 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_esp_mask;
142 : :
143 : 0 : rule->key.spi = spec->hdr.spi;
144 : 0 : rule->mask.spi = mask->hdr.spi;
145 : : }
146 : : }
147 : :
148 : : static void
149 : : gve_parse_ah(const struct rte_flow_item *item, struct gve_flow_rule_params *rule)
150 : : {
151 [ # # ]: 0 : if (item->spec) {
152 : : const struct rte_flow_item_ah *spec = item->spec;
153 : : const struct rte_flow_item_ah *mask =
154 [ # # ]: 0 : item->mask ? item->mask : &rte_flow_item_ah_mask;
155 : :
156 : 0 : rule->key.spi = spec->spi;
157 : 0 : rule->mask.spi = mask->spi;
158 : : }
159 : : }
160 : :
161 : : static int
162 : 0 : gve_validate_and_parse_flow_pattern(const struct rte_flow_item pattern[],
163 : : struct rte_flow_error *error,
164 : : struct gve_flow_rule_params *rule)
165 : : {
166 : : const struct rte_flow_item *item = pattern;
167 : : enum rte_flow_item_type l3_type = RTE_FLOW_ITEM_TYPE_VOID;
168 : : enum rte_flow_item_type l4_type = RTE_FLOW_ITEM_TYPE_VOID;
169 : :
170 [ # # ]: 0 : if (pattern == NULL) {
171 : 0 : rte_flow_error_set(error, EINVAL,
172 : : RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
173 : : "Invalid flow pattern");
174 : 0 : return -EINVAL;
175 : : }
176 : :
177 [ # # ]: 0 : for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
178 [ # # ]: 0 : if (item->last) {
179 : : /* Last and range are not supported as match criteria. */
180 : 0 : rte_flow_error_set(error, EINVAL,
181 : : RTE_FLOW_ERROR_TYPE_ITEM,
182 : : item,
183 : : "No support for range");
184 : 0 : return -EINVAL;
185 : : }
186 [ # # # # : 0 : switch (item->type) {
# # # #
# ]
187 : : case RTE_FLOW_ITEM_TYPE_VOID:
188 : : break;
189 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
190 [ # # ]: 0 : if (l3_type != RTE_FLOW_ITEM_TYPE_VOID) {
191 : 0 : rte_flow_error_set(error, EINVAL,
192 : : RTE_FLOW_ERROR_TYPE_ITEM,
193 : : item,
194 : : "Multiple L3 items not supported");
195 : 0 : return -EINVAL;
196 : : }
197 : : gve_parse_ipv4(item, rule);
198 : : l3_type = item->type;
199 : : break;
200 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
201 [ # # ]: 0 : if (l3_type != RTE_FLOW_ITEM_TYPE_VOID) {
202 : 0 : rte_flow_error_set(error, EINVAL,
203 : : RTE_FLOW_ERROR_TYPE_ITEM,
204 : : item,
205 : : "Multiple L3 items not supported");
206 : 0 : return -EINVAL;
207 : : }
208 : 0 : gve_parse_ipv6(item, rule);
209 : : l3_type = item->type;
210 : 0 : break;
211 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
212 [ # # ]: 0 : if (l4_type != RTE_FLOW_ITEM_TYPE_VOID) {
213 : 0 : rte_flow_error_set(error, EINVAL,
214 : : RTE_FLOW_ERROR_TYPE_ITEM,
215 : : item,
216 : : "Multiple L4 items not supported");
217 : 0 : return -EINVAL;
218 : : }
219 : : gve_parse_udp(item, rule);
220 : : l4_type = item->type;
221 : : break;
222 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
223 [ # # ]: 0 : if (l4_type != RTE_FLOW_ITEM_TYPE_VOID) {
224 : 0 : rte_flow_error_set(error, EINVAL,
225 : : RTE_FLOW_ERROR_TYPE_ITEM,
226 : : item,
227 : : "Multiple L4 items not supported");
228 : 0 : return -EINVAL;
229 : : }
230 : : gve_parse_tcp(item, rule);
231 : : l4_type = item->type;
232 : : break;
233 : 0 : case RTE_FLOW_ITEM_TYPE_SCTP:
234 [ # # ]: 0 : if (l4_type != RTE_FLOW_ITEM_TYPE_VOID) {
235 : 0 : rte_flow_error_set(error, EINVAL,
236 : : RTE_FLOW_ERROR_TYPE_ITEM,
237 : : item,
238 : : "Multiple L4 items not supported");
239 : 0 : return -EINVAL;
240 : : }
241 : : gve_parse_sctp(item, rule);
242 : : l4_type = item->type;
243 : : break;
244 : 0 : case RTE_FLOW_ITEM_TYPE_ESP:
245 [ # # ]: 0 : if (l4_type != RTE_FLOW_ITEM_TYPE_VOID) {
246 : 0 : rte_flow_error_set(error, EINVAL,
247 : : RTE_FLOW_ERROR_TYPE_ITEM,
248 : : item,
249 : : "Multiple L4 items not supported");
250 : 0 : return -EINVAL;
251 : : }
252 : : gve_parse_esp(item, rule);
253 : : l4_type = item->type;
254 : : break;
255 : 0 : case RTE_FLOW_ITEM_TYPE_AH:
256 [ # # ]: 0 : if (l4_type != RTE_FLOW_ITEM_TYPE_VOID) {
257 : 0 : rte_flow_error_set(error, EINVAL,
258 : : RTE_FLOW_ERROR_TYPE_ITEM,
259 : : item,
260 : : "Multiple L4 items not supported");
261 : 0 : return -EINVAL;
262 : : }
263 : : gve_parse_ah(item, rule);
264 : : l4_type = item->type;
265 : : break;
266 : 0 : default:
267 : 0 : rte_flow_error_set(error, EINVAL,
268 : : RTE_FLOW_ERROR_TYPE_ITEM, item,
269 : : "Unsupported flow pattern item type");
270 : 0 : return -EINVAL;
271 : : }
272 : : }
273 : :
274 [ # # # ]: 0 : switch (l3_type) {
275 [ # # # # : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
# # ]
276 : : switch (l4_type) {
277 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
278 : 0 : rule->flow_type = GVE_FLOW_TYPE_TCPV4;
279 : 0 : break;
280 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
281 : 0 : rule->flow_type = GVE_FLOW_TYPE_UDPV4;
282 : 0 : break;
283 : 0 : case RTE_FLOW_ITEM_TYPE_SCTP:
284 : 0 : rule->flow_type = GVE_FLOW_TYPE_SCTPV4;
285 : 0 : break;
286 : 0 : case RTE_FLOW_ITEM_TYPE_AH:
287 : 0 : rule->flow_type = GVE_FLOW_TYPE_AHV4;
288 : 0 : break;
289 : 0 : case RTE_FLOW_ITEM_TYPE_ESP:
290 : 0 : rule->flow_type = GVE_FLOW_TYPE_ESPV4;
291 : 0 : break;
292 : 0 : default:
293 : 0 : goto unsupported_flow;
294 : : }
295 : : break;
296 [ # # # # : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
# # ]
297 : : switch (l4_type) {
298 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
299 : 0 : rule->flow_type = GVE_FLOW_TYPE_TCPV6;
300 : 0 : break;
301 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
302 : 0 : rule->flow_type = GVE_FLOW_TYPE_UDPV6;
303 : 0 : break;
304 : 0 : case RTE_FLOW_ITEM_TYPE_SCTP:
305 : 0 : rule->flow_type = GVE_FLOW_TYPE_SCTPV6;
306 : 0 : break;
307 : 0 : case RTE_FLOW_ITEM_TYPE_AH:
308 : 0 : rule->flow_type = GVE_FLOW_TYPE_AHV6;
309 : 0 : break;
310 : 0 : case RTE_FLOW_ITEM_TYPE_ESP:
311 : 0 : rule->flow_type = GVE_FLOW_TYPE_ESPV6;
312 : 0 : break;
313 : 0 : default:
314 : 0 : goto unsupported_flow;
315 : : }
316 : : break;
317 : 0 : default:
318 : 0 : goto unsupported_flow;
319 : : }
320 : :
321 : : return 0;
322 : :
323 : 0 : unsupported_flow:
324 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
325 : : NULL, "Unsupported L3/L4 combination");
326 : 0 : return -EINVAL;
327 : : }
328 : :
329 : : static int
330 : 0 : gve_validate_and_parse_flow_actions(struct rte_eth_dev *dev,
331 : : const struct rte_flow_action actions[],
332 : : struct rte_flow_error *error,
333 : : struct gve_flow_rule_params *rule)
334 : : {
335 : : const struct rte_flow_action_queue *action_queue;
336 : : const struct rte_flow_action *action = actions;
337 : : int num_queue_actions = 0;
338 : :
339 [ # # ]: 0 : if (actions == NULL) {
340 : 0 : rte_flow_error_set(error, EINVAL,
341 : : RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
342 : : "Invalid flow actions");
343 : 0 : return -EINVAL;
344 : : }
345 : :
346 [ # # ]: 0 : while (action->type != RTE_FLOW_ACTION_TYPE_END) {
347 [ # # # ]: 0 : switch (action->type) {
348 : : case RTE_FLOW_ACTION_TYPE_VOID:
349 : : break;
350 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
351 [ # # ]: 0 : if (action->conf == NULL) {
352 : 0 : rte_flow_error_set(error, EINVAL,
353 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
354 : : action,
355 : : "QUEUE action config cannot be NULL.");
356 : 0 : return -EINVAL;
357 : : }
358 : :
359 : : action_queue = action->conf;
360 [ # # ]: 0 : if (action_queue->index >= dev->data->nb_rx_queues) {
361 : 0 : rte_flow_error_set(error, EINVAL,
362 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
363 : : action, "Invalid Queue ID");
364 : 0 : return -EINVAL;
365 : : }
366 : :
367 : 0 : rule->action = action_queue->index;
368 : 0 : num_queue_actions++;
369 : 0 : break;
370 : 0 : default:
371 : 0 : rte_flow_error_set(error, ENOTSUP,
372 : : RTE_FLOW_ERROR_TYPE_ACTION,
373 : : action,
374 : : "Unsupported action. Only QUEUE is permitted.");
375 : 0 : return -ENOTSUP;
376 : : }
377 : 0 : action++;
378 : : }
379 : :
380 [ # # ]: 0 : if (num_queue_actions == 0) {
381 : 0 : rte_flow_error_set(error, EINVAL,
382 : : RTE_FLOW_ERROR_TYPE_ACTION_NUM,
383 : : NULL, "A QUEUE action is required.");
384 : 0 : return -EINVAL;
385 : : }
386 : :
387 [ # # ]: 0 : if (num_queue_actions > 1) {
388 : 0 : rte_flow_error_set(error, EINVAL,
389 : : RTE_FLOW_ERROR_TYPE_ACTION_NUM,
390 : : NULL, "Only a single QUEUE action is allowed.");
391 : 0 : return -EINVAL;
392 : : }
393 : :
394 : : return 0;
395 : : }
396 : :
397 : : static int
398 : 0 : gve_validate_and_parse_flow(struct rte_eth_dev *dev,
399 : : const struct rte_flow_attr *attr,
400 : : const struct rte_flow_item pattern[],
401 : : const struct rte_flow_action actions[],
402 : : struct rte_flow_error *error,
403 : : struct gve_flow_rule_params *rule)
404 : : {
405 : : int err;
406 : :
407 : 0 : err = gve_validate_flow_attr(attr, error);
408 [ # # ]: 0 : if (err)
409 : : return err;
410 : :
411 : 0 : err = gve_validate_and_parse_flow_pattern(pattern, error, rule);
412 [ # # ]: 0 : if (err)
413 : : return err;
414 : :
415 : 0 : err = gve_validate_and_parse_flow_actions(dev, actions, error, rule);
416 [ # # ]: 0 : if (err)
417 : 0 : return err;
418 : :
419 : : return 0;
420 : : }
421 : :
422 : : int
423 : 0 : gve_flow_init_bmp(struct gve_priv *priv)
424 : : {
425 : 0 : priv->avail_flow_rule_bmp = rte_bitmap_init_with_all_set(priv->max_flow_rules,
426 : 0 : priv->avail_flow_rule_bmp_mem, priv->flow_rule_bmp_size);
427 [ # # ]: 0 : if (priv->avail_flow_rule_bmp == NULL) {
428 : 0 : PMD_DRV_LOG(ERR, "Flow subsystem failed: cannot init bitmap.");
429 : 0 : return -ENOMEM;
430 : : }
431 : :
432 : : return 0;
433 : : }
434 : :
435 : : void
436 : 0 : gve_flow_free_bmp(struct gve_priv *priv)
437 : : {
438 : 0 : rte_free(priv->avail_flow_rule_bmp_mem);
439 : 0 : priv->avail_flow_rule_bmp_mem = NULL;
440 : 0 : priv->avail_flow_rule_bmp = NULL;
441 : 0 : }
442 : :
443 : : /*
444 : : * The caller must acquire the flow rule lock before calling this function.
445 : : */
446 : : int
447 : 0 : gve_free_flow_rules(struct gve_priv *priv)
448 : : {
449 : : struct gve_flow *flow;
450 : : int err = 0;
451 : :
452 [ # # ]: 0 : if (!TAILQ_EMPTY(&priv->active_flows)) {
453 : 0 : err = gve_adminq_reset_flow_rules(priv);
454 [ # # ]: 0 : if (err) {
455 : 0 : PMD_DRV_LOG(ERR,
456 : : "Failed to reset flow rules, internal device err=%d",
457 : : err);
458 : : }
459 : :
460 : : /* Free flows even if AQ fails to avoid leaking memory. */
461 [ # # ]: 0 : while (!TAILQ_EMPTY(&priv->active_flows)) {
462 : : flow = TAILQ_FIRST(&priv->active_flows);
463 [ # # ]: 0 : TAILQ_REMOVE(&priv->active_flows, flow, list_handle);
464 : 0 : free(flow);
465 : : }
466 : : }
467 : :
468 : 0 : return err;
469 : : }
470 : :
471 : : static struct rte_flow *
472 : 0 : gve_create_flow_rule(struct rte_eth_dev *dev,
473 : : const struct rte_flow_attr *attr,
474 : : const struct rte_flow_item pattern[],
475 : : const struct rte_flow_action actions[],
476 : : struct rte_flow_error *error)
477 : : {
478 : 0 : struct gve_priv *priv = dev->data->dev_private;
479 : 0 : struct gve_flow_rule_params rule = {0};
480 : 0 : uint64_t slab_bits = 0;
481 : 0 : uint32_t slab_idx = 0;
482 : : struct gve_flow *flow;
483 : : int err;
484 : :
485 : 0 : err = gve_validate_and_parse_flow(dev, attr, pattern, actions, error,
486 : : &rule);
487 [ # # ]: 0 : if (err)
488 : : return NULL;
489 : :
490 : 0 : flow = calloc(1, sizeof(struct gve_flow));
491 [ # # ]: 0 : if (flow == NULL) {
492 : 0 : rte_flow_error_set(error, ENOMEM,
493 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
494 : : "Failed to allocate memory for flow rule.");
495 : 0 : return NULL;
496 : : }
497 : :
498 : 0 : pthread_mutex_lock(&priv->flow_rule_lock);
499 : :
500 [ # # ]: 0 : if (!gve_get_flow_subsystem_ok(priv)) {
501 : 0 : rte_flow_error_set(error, ENOTSUP,
502 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
503 : : "Failed to create flow, flow subsystem not initialized.");
504 : 0 : goto free_flow_and_unlock;
505 : : }
506 : :
507 : : /* Try to allocate a new rule ID from the bitmap. */
508 [ # # ]: 0 : if (rte_bitmap_scan(priv->avail_flow_rule_bmp, &slab_idx,
509 : : &slab_bits) == 1) {
510 : 0 : flow->rule_id = slab_idx + rte_ctz64(slab_bits);
511 : 0 : rte_bitmap_clear(priv->avail_flow_rule_bmp, flow->rule_id);
512 : : } else {
513 : 0 : rte_flow_error_set(error, ENOMEM,
514 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
515 : : "Failed to create flow, could not allocate a new rule ID.");
516 : 0 : goto free_flow_and_unlock;
517 : : }
518 : :
519 : 0 : err = gve_adminq_add_flow_rule(priv, &rule, flow->rule_id);
520 [ # # ]: 0 : if (err) {
521 : 0 : rte_bitmap_set(priv->avail_flow_rule_bmp, flow->rule_id);
522 : 0 : rte_flow_error_set(error, -err,
523 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
524 : : "Failed to create flow rule, internal device error.");
525 : 0 : goto free_flow_and_unlock;
526 : : }
527 : :
528 : 0 : TAILQ_INSERT_TAIL(&priv->active_flows, flow, list_handle);
529 : :
530 : 0 : pthread_mutex_unlock(&priv->flow_rule_lock);
531 : :
532 : 0 : return (struct rte_flow *)flow;
533 : :
534 : 0 : free_flow_and_unlock:
535 : 0 : free(flow);
536 : 0 : pthread_mutex_unlock(&priv->flow_rule_lock);
537 : 0 : return NULL;
538 : : }
539 : :
540 : : static int
541 : 0 : gve_destroy_flow_rule(struct rte_eth_dev *dev, struct rte_flow *flow_handle,
542 : : struct rte_flow_error *error)
543 : : {
544 : 0 : struct gve_priv *priv = dev->data->dev_private;
545 : : struct gve_flow *flow;
546 : : bool flow_rule_active;
547 : : int err;
548 : :
549 : 0 : pthread_mutex_lock(&priv->flow_rule_lock);
550 : :
551 [ # # ]: 0 : if (!gve_get_flow_subsystem_ok(priv)) {
552 : 0 : rte_flow_error_set(error, ENOTSUP,
553 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
554 : : "Failed to destroy flow, flow subsystem not initialized.");
555 : : err = -ENOTSUP;
556 : 0 : goto unlock;
557 : : }
558 : :
559 : : flow = (struct gve_flow *)flow_handle;
560 : :
561 [ # # ]: 0 : if (flow == NULL) {
562 : 0 : rte_flow_error_set(error, EINVAL,
563 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
564 : : "Failed to destroy flow, invalid flow provided.");
565 : : err = -EINVAL;
566 : 0 : goto unlock;
567 : : }
568 : :
569 [ # # ]: 0 : if (flow->rule_id >= priv->max_flow_rules) {
570 : 0 : PMD_DRV_LOG(ERR,
571 : : "Cannot destroy flow rule with invalid ID %d.",
572 : : flow->rule_id);
573 : 0 : rte_flow_error_set(error, EINVAL,
574 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
575 : : "Failed to destroy flow, rule ID is invalid.");
576 : : err = -EINVAL;
577 : 0 : goto unlock;
578 : : }
579 : :
580 [ # # ]: 0 : flow_rule_active = !rte_bitmap_get(priv->avail_flow_rule_bmp,
581 : : flow->rule_id);
582 : :
583 [ # # ]: 0 : if (!flow_rule_active) {
584 : 0 : rte_flow_error_set(error, EINVAL,
585 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
586 : : "Failed to destroy flow, handle not found in active list.");
587 : : err = -EINVAL;
588 : 0 : goto unlock;
589 : : }
590 : :
591 : 0 : err = gve_adminq_del_flow_rule(priv, flow->rule_id);
592 [ # # ]: 0 : if (err) {
593 : 0 : rte_flow_error_set(error, -err,
594 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
595 : : "Failed to destroy flow, internal device error.");
596 : 0 : goto unlock;
597 : : }
598 : :
599 : 0 : rte_bitmap_set(priv->avail_flow_rule_bmp, flow->rule_id);
600 [ # # ]: 0 : TAILQ_REMOVE(&priv->active_flows, flow, list_handle);
601 : 0 : free(flow);
602 : :
603 : : err = 0;
604 : :
605 : 0 : unlock:
606 : 0 : pthread_mutex_unlock(&priv->flow_rule_lock);
607 : 0 : return err;
608 : : }
609 : :
610 : : static int
611 : 0 : gve_flush_flow_rules(struct rte_eth_dev *dev, struct rte_flow_error *error)
612 : : {
613 : 0 : struct gve_priv *priv = dev->data->dev_private;
614 : : int err;
615 : :
616 : 0 : pthread_mutex_lock(&priv->flow_rule_lock);
617 : :
618 [ # # ]: 0 : if (!gve_get_flow_subsystem_ok(priv)) {
619 : 0 : rte_flow_error_set(error, ENOTSUP,
620 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
621 : : "Failed to flush rules, flow subsystem not initialized.");
622 : : err = -ENOTSUP;
623 : 0 : goto unlock;
624 : : }
625 : :
626 : 0 : err = gve_free_flow_rules(priv);
627 [ # # ]: 0 : if (err) {
628 : 0 : rte_flow_error_set(error, -err,
629 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
630 : : "Failed to flush rules due to internal device error, disabling flow subsystem.");
631 : 0 : goto disable_and_free;
632 : : }
633 : :
634 : 0 : err = gve_flow_init_bmp(priv);
635 [ # # ]: 0 : if (err) {
636 : 0 : rte_flow_error_set(error, -err,
637 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
638 : : "Failed to re-initialize rule ID bitmap, disabling flow subsystem.");
639 : 0 : goto disable_and_free;
640 : : }
641 : :
642 : 0 : pthread_mutex_unlock(&priv->flow_rule_lock);
643 : :
644 : 0 : return 0;
645 : :
646 : 0 : disable_and_free:
647 : : gve_clear_flow_subsystem_ok(priv);
648 : 0 : gve_flow_free_bmp(priv);
649 : 0 : unlock:
650 : 0 : pthread_mutex_unlock(&priv->flow_rule_lock);
651 : 0 : return err;
652 : : }
653 : :
654 : : const struct rte_flow_ops gve_flow_ops = {
655 : : .create = gve_create_flow_rule,
656 : : .destroy = gve_destroy_flow_rule,
657 : : .flush = gve_flush_flow_rules,
658 : : };
|