LCOV - code coverage report
Current view: top level - drivers/net/gve - gve_flow_rule.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 276 0.0 %
Date: 2026-04-01 20:02:27 Functions: 0 11 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 143 0.0 %

           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                 :            : };

Generated by: LCOV version 1.14