net/mlx5: add Direct Verbs validation function
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_dv.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018 Mellanox Technologies, Ltd
3  */
4
5 #include <sys/queue.h>
6 #include <stdalign.h>
7 #include <stdint.h>
8 #include <string.h>
9
10 /* Verbs header. */
11 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
12 #ifdef PEDANTIC
13 #pragma GCC diagnostic ignored "-Wpedantic"
14 #endif
15 #include <infiniband/verbs.h>
16 #ifdef PEDANTIC
17 #pragma GCC diagnostic error "-Wpedantic"
18 #endif
19
20 #include <rte_common.h>
21 #include <rte_ether.h>
22 #include <rte_eth_ctrl.h>
23 #include <rte_ethdev_driver.h>
24 #include <rte_flow.h>
25 #include <rte_flow_driver.h>
26 #include <rte_malloc.h>
27 #include <rte_ip.h>
28
29 #include "mlx5.h"
30 #include "mlx5_defs.h"
31 #include "mlx5_prm.h"
32 #include "mlx5_glue.h"
33 #include "mlx5_flow.h"
34
35 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
36
37 /**
38  * Verify the @p attributes will be correctly understood by the NIC and store
39  * them in the @p flow if everything is correct.
40  *
41  * @param[in] dev
42  *   Pointer to dev struct.
43  * @param[in] attributes
44  *   Pointer to flow attributes
45  * @param[out] error
46  *   Pointer to error structure.
47  *
48  * @return
49  *   0 on success, a negative errno value otherwise and rte_errno is set.
50  */
51 static int
52 flow_dv_validate_attributes(struct rte_eth_dev *dev,
53                             const struct rte_flow_attr *attributes,
54                             struct rte_flow_error *error)
55 {
56         struct priv *priv = dev->data->dev_private;
57         uint32_t priority_max = priv->config.flow_prio - 1;
58
59         if (attributes->group)
60                 return rte_flow_error_set(error, ENOTSUP,
61                                           RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
62                                           NULL,
63                                           "groups is not supported");
64         if (attributes->priority != MLX5_FLOW_PRIO_RSVD &&
65             attributes->priority >= priority_max)
66                 return rte_flow_error_set(error, ENOTSUP,
67                                           RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
68                                           NULL,
69                                           "priority out of range");
70         if (attributes->egress)
71                 return rte_flow_error_set(error, ENOTSUP,
72                                           RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
73                                           NULL,
74                                           "egress is not supported");
75         if (attributes->transfer)
76                 return rte_flow_error_set(error, ENOTSUP,
77                                           RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
78                                           NULL,
79                                           "transfer is not supported");
80         if (!attributes->ingress)
81                 return rte_flow_error_set(error, EINVAL,
82                                           RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
83                                           NULL,
84                                           "ingress attribute is mandatory");
85         return 0;
86 }
87
88 /**
89  * Internal validation function. For validating both actions and items.
90  *
91  * @param[in] dev
92  *   Pointer to the rte_eth_dev structure.
93  * @param[in] attr
94  *   Pointer to the flow attributes.
95  * @param[in] items
96  *   Pointer to the list of items.
97  * @param[in] actions
98  *   Pointer to the list of actions.
99  * @param[out] error
100  *   Pointer to the error structure.
101  *
102  * @return
103  *   0 on success, a negative errno value otherwise and rte_ernno is set.
104  */
105 static int
106 flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
107                  const struct rte_flow_item items[],
108                  const struct rte_flow_action actions[],
109                  struct rte_flow_error *error)
110 {
111         int ret;
112         uint32_t action_flags = 0;
113         uint32_t item_flags = 0;
114         int tunnel = 0;
115         uint8_t next_protocol = 0xff;
116         int actions_n = 0;
117
118         if (items == NULL)
119                 return -1;
120         ret = flow_dv_validate_attributes(dev, attr, error);
121         if (ret < 0)
122                 return ret;
123         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
124                 switch (items->type) {
125                 case RTE_FLOW_ITEM_TYPE_VOID:
126                         break;
127                 case RTE_FLOW_ITEM_TYPE_ETH:
128                         ret = mlx5_flow_validate_item_eth(items, item_flags,
129                                                           error);
130                         if (ret < 0)
131                                 return ret;
132                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
133                                                MLX5_FLOW_LAYER_OUTER_L2;
134                         break;
135                 case RTE_FLOW_ITEM_TYPE_VLAN:
136                         ret = mlx5_flow_validate_item_vlan(items, item_flags,
137                                                            error);
138                         if (ret < 0)
139                                 return ret;
140                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
141                                                MLX5_FLOW_LAYER_OUTER_VLAN;
142                         break;
143                 case RTE_FLOW_ITEM_TYPE_IPV4:
144                         ret = mlx5_flow_validate_item_ipv4(items, item_flags,
145                                                            error);
146                         if (ret < 0)
147                                 return ret;
148                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
149                                                MLX5_FLOW_LAYER_OUTER_L3_IPV4;
150                         if (items->mask != NULL &&
151                             ((const struct rte_flow_item_ipv4 *)
152                              items->mask)->hdr.next_proto_id)
153                                 next_protocol =
154                                         ((const struct rte_flow_item_ipv4 *)
155                                          (items->spec))->hdr.next_proto_id;
156                         break;
157                 case RTE_FLOW_ITEM_TYPE_IPV6:
158                         ret = mlx5_flow_validate_item_ipv6(items, item_flags,
159                                                            error);
160                         if (ret < 0)
161                                 return ret;
162                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
163                                                MLX5_FLOW_LAYER_OUTER_L3_IPV6;
164                         if (items->mask != NULL &&
165                             ((const struct rte_flow_item_ipv6 *)
166                              items->mask)->hdr.proto)
167                                 next_protocol =
168                                         ((const struct rte_flow_item_ipv6 *)
169                                          items->spec)->hdr.proto;
170                         break;
171                 case RTE_FLOW_ITEM_TYPE_UDP:
172                         ret = mlx5_flow_validate_item_udp(items, item_flags,
173                                                           next_protocol,
174                                                           error);
175                         if (ret < 0)
176                                 return ret;
177                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
178                                                MLX5_FLOW_LAYER_OUTER_L4_UDP;
179                         break;
180                 case RTE_FLOW_ITEM_TYPE_TCP:
181                         ret = mlx5_flow_validate_item_tcp(items, item_flags,
182                                                           next_protocol, error);
183                         if (ret < 0)
184                                 return ret;
185                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
186                                                MLX5_FLOW_LAYER_OUTER_L4_TCP;
187                         break;
188                 case RTE_FLOW_ITEM_TYPE_VXLAN:
189                         ret = mlx5_flow_validate_item_vxlan(items, item_flags,
190                                                             error);
191                         if (ret < 0)
192                                 return ret;
193                         item_flags |= MLX5_FLOW_LAYER_VXLAN;
194                         break;
195                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
196                         ret = mlx5_flow_validate_item_vxlan_gpe(items,
197                                                                 item_flags, dev,
198                                                                 error);
199                         if (ret < 0)
200                                 return ret;
201                         item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
202                         break;
203                 case RTE_FLOW_ITEM_TYPE_GRE:
204                         ret = mlx5_flow_validate_item_gre(items, item_flags,
205                                                           next_protocol, error);
206                         if (ret < 0)
207                                 return ret;
208                         item_flags |= MLX5_FLOW_LAYER_GRE;
209                         break;
210                 case RTE_FLOW_ITEM_TYPE_MPLS:
211                         ret = mlx5_flow_validate_item_mpls(items, item_flags,
212                                                            next_protocol,
213                                                            error);
214                         if (ret < 0)
215                                 return ret;
216                         item_flags |= MLX5_FLOW_LAYER_MPLS;
217                         break;
218                 default:
219                         return rte_flow_error_set(error, ENOTSUP,
220                                                   RTE_FLOW_ERROR_TYPE_ITEM,
221                                                   NULL, "item not supported");
222                 }
223         }
224         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
225                 if (actions_n == MLX5_DV_MAX_NUMBER_OF_ACTIONS)
226                         return rte_flow_error_set(error, ENOTSUP,
227                                                   RTE_FLOW_ERROR_TYPE_ACTION,
228                                                   actions, "too many actions");
229                 tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
230                 switch (actions->type) {
231                 case RTE_FLOW_ACTION_TYPE_VOID:
232                         break;
233                 case RTE_FLOW_ACTION_TYPE_FLAG:
234                         ret = mlx5_flow_validate_action_flag(action_flags,
235                                                              error);
236                         if (ret < 0)
237                                 return ret;
238                         action_flags |= MLX5_FLOW_ACTION_FLAG;
239                         ++actions_n;
240                         break;
241                 case RTE_FLOW_ACTION_TYPE_MARK:
242                         ret = mlx5_flow_validate_action_mark(actions,
243                                                              action_flags,
244                                                              error);
245                         if (ret < 0)
246                                 return ret;
247                         action_flags |= MLX5_FLOW_ACTION_MARK;
248                         ++actions_n;
249                         break;
250                 case RTE_FLOW_ACTION_TYPE_DROP:
251                         ret = mlx5_flow_validate_action_drop(action_flags,
252                                                              error);
253                         if (ret < 0)
254                                 return ret;
255                         action_flags |= MLX5_FLOW_ACTION_DROP;
256                         ++actions_n;
257                         break;
258                 case RTE_FLOW_ACTION_TYPE_QUEUE:
259                         ret = mlx5_flow_validate_action_queue(actions,
260                                                               action_flags, dev,
261                                                               error);
262                         if (ret < 0)
263                                 return ret;
264                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
265                         ++actions_n;
266                         break;
267                 case RTE_FLOW_ACTION_TYPE_RSS:
268                         ret = mlx5_flow_validate_action_rss(actions,
269                                                             action_flags, dev,
270                                                             error);
271                         if (ret < 0)
272                                 return ret;
273                         action_flags |= MLX5_FLOW_ACTION_RSS;
274                         ++actions_n;
275                         break;
276                 case RTE_FLOW_ACTION_TYPE_COUNT:
277                         ret = mlx5_flow_validate_action_count(dev, error);
278                         if (ret < 0)
279                                 return ret;
280                         action_flags |= MLX5_FLOW_ACTION_COUNT;
281                         ++actions_n;
282                         break;
283                 default:
284                         return rte_flow_error_set(error, ENOTSUP,
285                                                   RTE_FLOW_ERROR_TYPE_ACTION,
286                                                   actions,
287                                                   "action not supported");
288                 }
289         }
290         if (!(action_flags & MLX5_FLOW_FATE_ACTIONS))
291                 return rte_flow_error_set(error, EINVAL,
292                                           RTE_FLOW_ERROR_TYPE_ACTION, actions,
293                                           "no fate action is found");
294         return 0;
295 }
296
297 /**
298  * Fills the flow_ops with the function pointers.
299  *
300  * @param[out] flow_ops
301  *   Pointer to driver_ops structure.
302  */
303 void
304 mlx5_flow_dv_get_driver_ops(struct mlx5_flow_driver_ops *flow_ops)
305 {
306         *flow_ops = (struct mlx5_flow_driver_ops) {
307                 .validate = flow_dv_validate,
308                 .prepare = NULL,
309                 .translate = NULL,
310                 .apply = NULL,
311                 .remove = NULL,
312                 .destroy = NULL,
313         };
314 }
315
316 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */