ethdev: change promiscuous mode controllers to return errors
[dpdk.git] / lib / librte_ethdev / rte_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016 6WIND S.A.
3  * Copyright 2016 Mellanox Technologies, Ltd
4  */
5
6 #include <errno.h>
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 #include <rte_common.h>
12 #include <rte_errno.h>
13 #include <rte_branch_prediction.h>
14 #include <rte_string_fns.h>
15 #include "rte_ethdev.h"
16 #include "rte_flow_driver.h"
17 #include "rte_flow.h"
18
19 /**
20  * Flow elements description tables.
21  */
22 struct rte_flow_desc_data {
23         const char *name;
24         size_t size;
25 };
26
27 /** Generate flow_item[] entry. */
28 #define MK_FLOW_ITEM(t, s) \
29         [RTE_FLOW_ITEM_TYPE_ ## t] = { \
30                 .name = # t, \
31                 .size = s, \
32         }
33
34 /** Information about known flow pattern items. */
35 static const struct rte_flow_desc_data rte_flow_desc_item[] = {
36         MK_FLOW_ITEM(END, 0),
37         MK_FLOW_ITEM(VOID, 0),
38         MK_FLOW_ITEM(INVERT, 0),
39         MK_FLOW_ITEM(ANY, sizeof(struct rte_flow_item_any)),
40         MK_FLOW_ITEM(PF, 0),
41         MK_FLOW_ITEM(VF, sizeof(struct rte_flow_item_vf)),
42         MK_FLOW_ITEM(PHY_PORT, sizeof(struct rte_flow_item_phy_port)),
43         MK_FLOW_ITEM(PORT_ID, sizeof(struct rte_flow_item_port_id)),
44         MK_FLOW_ITEM(RAW, sizeof(struct rte_flow_item_raw)),
45         MK_FLOW_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
46         MK_FLOW_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
47         MK_FLOW_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
48         MK_FLOW_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
49         MK_FLOW_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
50         MK_FLOW_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
51         MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
52         MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
53         MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
54         MK_FLOW_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
55         MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
56         MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
57         MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
58         MK_FLOW_ITEM(FUZZY, sizeof(struct rte_flow_item_fuzzy)),
59         MK_FLOW_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
60         MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
61         MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
62         MK_FLOW_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
63         MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
64         MK_FLOW_ITEM(VXLAN_GPE, sizeof(struct rte_flow_item_vxlan_gpe)),
65         MK_FLOW_ITEM(ARP_ETH_IPV4, sizeof(struct rte_flow_item_arp_eth_ipv4)),
66         MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
67         MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
68         MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
69         MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
70         MK_FLOW_ITEM(ICMP6_ND_OPT, sizeof(struct rte_flow_item_icmp6_nd_opt)),
71         MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
72                      sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
73         MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
74                      sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
75         MK_FLOW_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
76         MK_FLOW_ITEM(META, sizeof(struct rte_flow_item_meta)),
77         MK_FLOW_ITEM(GRE_KEY, sizeof(rte_be32_t)),
78 };
79
80 /** Generate flow_action[] entry. */
81 #define MK_FLOW_ACTION(t, s) \
82         [RTE_FLOW_ACTION_TYPE_ ## t] = { \
83                 .name = # t, \
84                 .size = s, \
85         }
86
87 /** Information about known flow actions. */
88 static const struct rte_flow_desc_data rte_flow_desc_action[] = {
89         MK_FLOW_ACTION(END, 0),
90         MK_FLOW_ACTION(VOID, 0),
91         MK_FLOW_ACTION(PASSTHRU, 0),
92         MK_FLOW_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
93         MK_FLOW_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
94         MK_FLOW_ACTION(FLAG, 0),
95         MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)),
96         MK_FLOW_ACTION(DROP, 0),
97         MK_FLOW_ACTION(COUNT, sizeof(struct rte_flow_action_count)),
98         MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)),
99         MK_FLOW_ACTION(PF, 0),
100         MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)),
101         MK_FLOW_ACTION(PHY_PORT, sizeof(struct rte_flow_action_phy_port)),
102         MK_FLOW_ACTION(PORT_ID, sizeof(struct rte_flow_action_port_id)),
103         MK_FLOW_ACTION(METER, sizeof(struct rte_flow_action_meter)),
104         MK_FLOW_ACTION(SECURITY, sizeof(struct rte_flow_action_security)),
105         MK_FLOW_ACTION(OF_SET_MPLS_TTL,
106                        sizeof(struct rte_flow_action_of_set_mpls_ttl)),
107         MK_FLOW_ACTION(OF_DEC_MPLS_TTL, 0),
108         MK_FLOW_ACTION(OF_SET_NW_TTL,
109                        sizeof(struct rte_flow_action_of_set_nw_ttl)),
110         MK_FLOW_ACTION(OF_DEC_NW_TTL, 0),
111         MK_FLOW_ACTION(OF_COPY_TTL_OUT, 0),
112         MK_FLOW_ACTION(OF_COPY_TTL_IN, 0),
113         MK_FLOW_ACTION(OF_POP_VLAN, 0),
114         MK_FLOW_ACTION(OF_PUSH_VLAN,
115                        sizeof(struct rte_flow_action_of_push_vlan)),
116         MK_FLOW_ACTION(OF_SET_VLAN_VID,
117                        sizeof(struct rte_flow_action_of_set_vlan_vid)),
118         MK_FLOW_ACTION(OF_SET_VLAN_PCP,
119                        sizeof(struct rte_flow_action_of_set_vlan_pcp)),
120         MK_FLOW_ACTION(OF_POP_MPLS,
121                        sizeof(struct rte_flow_action_of_pop_mpls)),
122         MK_FLOW_ACTION(OF_PUSH_MPLS,
123                        sizeof(struct rte_flow_action_of_push_mpls)),
124         MK_FLOW_ACTION(VXLAN_ENCAP, sizeof(struct rte_flow_action_vxlan_encap)),
125         MK_FLOW_ACTION(VXLAN_DECAP, 0),
126         MK_FLOW_ACTION(NVGRE_ENCAP, sizeof(struct rte_flow_action_vxlan_encap)),
127         MK_FLOW_ACTION(NVGRE_DECAP, 0),
128         MK_FLOW_ACTION(RAW_ENCAP, sizeof(struct rte_flow_action_raw_encap)),
129         MK_FLOW_ACTION(RAW_DECAP, sizeof(struct rte_flow_action_raw_decap)),
130         MK_FLOW_ACTION(SET_IPV4_SRC,
131                        sizeof(struct rte_flow_action_set_ipv4)),
132         MK_FLOW_ACTION(SET_IPV4_DST,
133                        sizeof(struct rte_flow_action_set_ipv4)),
134         MK_FLOW_ACTION(SET_IPV6_SRC,
135                        sizeof(struct rte_flow_action_set_ipv6)),
136         MK_FLOW_ACTION(SET_IPV6_DST,
137                        sizeof(struct rte_flow_action_set_ipv6)),
138         MK_FLOW_ACTION(SET_TP_SRC,
139                        sizeof(struct rte_flow_action_set_tp)),
140         MK_FLOW_ACTION(SET_TP_DST,
141                        sizeof(struct rte_flow_action_set_tp)),
142         MK_FLOW_ACTION(MAC_SWAP, 0),
143         MK_FLOW_ACTION(DEC_TTL, 0),
144         MK_FLOW_ACTION(SET_TTL, sizeof(struct rte_flow_action_set_ttl)),
145         MK_FLOW_ACTION(SET_MAC_SRC, sizeof(struct rte_flow_action_set_mac)),
146         MK_FLOW_ACTION(SET_MAC_DST, sizeof(struct rte_flow_action_set_mac)),
147         MK_FLOW_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)),
148         MK_FLOW_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)),
149         MK_FLOW_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)),
150         MK_FLOW_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)),
151 };
152
153 static int
154 flow_err(uint16_t port_id, int ret, struct rte_flow_error *error)
155 {
156         if (ret == 0)
157                 return 0;
158         if (rte_eth_dev_is_removed(port_id))
159                 return rte_flow_error_set(error, EIO,
160                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
161                                           NULL, rte_strerror(EIO));
162         return ret;
163 }
164
165 /* Get generic flow operations structure from a port. */
166 const struct rte_flow_ops *
167 rte_flow_ops_get(uint16_t port_id, struct rte_flow_error *error)
168 {
169         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
170         const struct rte_flow_ops *ops;
171         int code;
172
173         if (unlikely(!rte_eth_dev_is_valid_port(port_id)))
174                 code = ENODEV;
175         else if (unlikely(!dev->dev_ops->filter_ctrl ||
176                           dev->dev_ops->filter_ctrl(dev,
177                                                     RTE_ETH_FILTER_GENERIC,
178                                                     RTE_ETH_FILTER_GET,
179                                                     &ops) ||
180                           !ops))
181                 code = ENOSYS;
182         else
183                 return ops;
184         rte_flow_error_set(error, code, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
185                            NULL, rte_strerror(code));
186         return NULL;
187 }
188
189 /* Check whether a flow rule can be created on a given port. */
190 int
191 rte_flow_validate(uint16_t port_id,
192                   const struct rte_flow_attr *attr,
193                   const struct rte_flow_item pattern[],
194                   const struct rte_flow_action actions[],
195                   struct rte_flow_error *error)
196 {
197         const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
198         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
199
200         if (unlikely(!ops))
201                 return -rte_errno;
202         if (likely(!!ops->validate))
203                 return flow_err(port_id, ops->validate(dev, attr, pattern,
204                                                        actions, error), error);
205         return rte_flow_error_set(error, ENOSYS,
206                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
207                                   NULL, rte_strerror(ENOSYS));
208 }
209
210 /* Create a flow rule on a given port. */
211 struct rte_flow *
212 rte_flow_create(uint16_t port_id,
213                 const struct rte_flow_attr *attr,
214                 const struct rte_flow_item pattern[],
215                 const struct rte_flow_action actions[],
216                 struct rte_flow_error *error)
217 {
218         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
219         struct rte_flow *flow;
220         const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
221
222         if (unlikely(!ops))
223                 return NULL;
224         if (likely(!!ops->create)) {
225                 flow = ops->create(dev, attr, pattern, actions, error);
226                 if (flow == NULL)
227                         flow_err(port_id, -rte_errno, error);
228                 return flow;
229         }
230         rte_flow_error_set(error, ENOSYS, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
231                            NULL, rte_strerror(ENOSYS));
232         return NULL;
233 }
234
235 /* Destroy a flow rule on a given port. */
236 int
237 rte_flow_destroy(uint16_t port_id,
238                  struct rte_flow *flow,
239                  struct rte_flow_error *error)
240 {
241         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
242         const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
243
244         if (unlikely(!ops))
245                 return -rte_errno;
246         if (likely(!!ops->destroy))
247                 return flow_err(port_id, ops->destroy(dev, flow, error),
248                                 error);
249         return rte_flow_error_set(error, ENOSYS,
250                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
251                                   NULL, rte_strerror(ENOSYS));
252 }
253
254 /* Destroy all flow rules associated with a port. */
255 int
256 rte_flow_flush(uint16_t port_id,
257                struct rte_flow_error *error)
258 {
259         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
260         const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
261
262         if (unlikely(!ops))
263                 return -rte_errno;
264         if (likely(!!ops->flush))
265                 return flow_err(port_id, ops->flush(dev, error), error);
266         return rte_flow_error_set(error, ENOSYS,
267                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
268                                   NULL, rte_strerror(ENOSYS));
269 }
270
271 /* Query an existing flow rule. */
272 int
273 rte_flow_query(uint16_t port_id,
274                struct rte_flow *flow,
275                const struct rte_flow_action *action,
276                void *data,
277                struct rte_flow_error *error)
278 {
279         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
280         const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
281
282         if (!ops)
283                 return -rte_errno;
284         if (likely(!!ops->query))
285                 return flow_err(port_id, ops->query(dev, flow, action, data,
286                                                     error), error);
287         return rte_flow_error_set(error, ENOSYS,
288                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
289                                   NULL, rte_strerror(ENOSYS));
290 }
291
292 /* Restrict ingress traffic to the defined flow rules. */
293 int
294 rte_flow_isolate(uint16_t port_id,
295                  int set,
296                  struct rte_flow_error *error)
297 {
298         struct rte_eth_dev *dev = &rte_eth_devices[port_id];
299         const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
300
301         if (!ops)
302                 return -rte_errno;
303         if (likely(!!ops->isolate))
304                 return flow_err(port_id, ops->isolate(dev, set, error), error);
305         return rte_flow_error_set(error, ENOSYS,
306                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
307                                   NULL, rte_strerror(ENOSYS));
308 }
309
310 /* Initialize flow error structure. */
311 int
312 rte_flow_error_set(struct rte_flow_error *error,
313                    int code,
314                    enum rte_flow_error_type type,
315                    const void *cause,
316                    const char *message)
317 {
318         if (error) {
319                 *error = (struct rte_flow_error){
320                         .type = type,
321                         .cause = cause,
322                         .message = message,
323                 };
324         }
325         rte_errno = code;
326         return -code;
327 }
328
329 /** Pattern item specification types. */
330 enum rte_flow_conv_item_spec_type {
331         RTE_FLOW_CONV_ITEM_SPEC,
332         RTE_FLOW_CONV_ITEM_LAST,
333         RTE_FLOW_CONV_ITEM_MASK,
334 };
335
336 /**
337  * Copy pattern item specification.
338  *
339  * @param[out] buf
340  *   Output buffer. Can be NULL if @p size is zero.
341  * @param size
342  *   Size of @p buf in bytes.
343  * @param[in] item
344  *   Pattern item to copy specification from.
345  * @param type
346  *   Specification selector for either @p spec, @p last or @p mask.
347  *
348  * @return
349  *   Number of bytes needed to store pattern item specification regardless
350  *   of @p size. @p buf contents are truncated to @p size if not large
351  *   enough.
352  */
353 static size_t
354 rte_flow_conv_item_spec(void *buf, const size_t size,
355                         const struct rte_flow_item *item,
356                         enum rte_flow_conv_item_spec_type type)
357 {
358         size_t off;
359         const void *data =
360                 type == RTE_FLOW_CONV_ITEM_SPEC ? item->spec :
361                 type == RTE_FLOW_CONV_ITEM_LAST ? item->last :
362                 type == RTE_FLOW_CONV_ITEM_MASK ? item->mask :
363                 NULL;
364
365         switch (item->type) {
366                 union {
367                         const struct rte_flow_item_raw *raw;
368                 } spec;
369                 union {
370                         const struct rte_flow_item_raw *raw;
371                 } last;
372                 union {
373                         const struct rte_flow_item_raw *raw;
374                 } mask;
375                 union {
376                         const struct rte_flow_item_raw *raw;
377                 } src;
378                 union {
379                         struct rte_flow_item_raw *raw;
380                 } dst;
381                 size_t tmp;
382
383         case RTE_FLOW_ITEM_TYPE_RAW:
384                 spec.raw = item->spec;
385                 last.raw = item->last ? item->last : item->spec;
386                 mask.raw = item->mask ? item->mask : &rte_flow_item_raw_mask;
387                 src.raw = data;
388                 dst.raw = buf;
389                 rte_memcpy(dst.raw,
390                            (&(struct rte_flow_item_raw){
391                                 .relative = src.raw->relative,
392                                 .search = src.raw->search,
393                                 .reserved = src.raw->reserved,
394                                 .offset = src.raw->offset,
395                                 .limit = src.raw->limit,
396                                 .length = src.raw->length,
397                            }),
398                            size > sizeof(*dst.raw) ? sizeof(*dst.raw) : size);
399                 off = sizeof(*dst.raw);
400                 if (type == RTE_FLOW_CONV_ITEM_SPEC ||
401                     (type == RTE_FLOW_CONV_ITEM_MASK &&
402                      ((spec.raw->length & mask.raw->length) >=
403                       (last.raw->length & mask.raw->length))))
404                         tmp = spec.raw->length & mask.raw->length;
405                 else
406                         tmp = last.raw->length & mask.raw->length;
407                 if (tmp) {
408                         off = RTE_ALIGN_CEIL(off, sizeof(*dst.raw->pattern));
409                         if (size >= off + tmp)
410                                 dst.raw->pattern = rte_memcpy
411                                         ((void *)((uintptr_t)dst.raw + off),
412                                          src.raw->pattern, tmp);
413                         off += tmp;
414                 }
415                 break;
416         default:
417                 off = rte_flow_desc_item[item->type].size;
418                 rte_memcpy(buf, data, (size > off ? off : size));
419                 break;
420         }
421         return off;
422 }
423
424 /**
425  * Copy action configuration.
426  *
427  * @param[out] buf
428  *   Output buffer. Can be NULL if @p size is zero.
429  * @param size
430  *   Size of @p buf in bytes.
431  * @param[in] action
432  *   Action to copy configuration from.
433  *
434  * @return
435  *   Number of bytes needed to store pattern item specification regardless
436  *   of @p size. @p buf contents are truncated to @p size if not large
437  *   enough.
438  */
439 static size_t
440 rte_flow_conv_action_conf(void *buf, const size_t size,
441                           const struct rte_flow_action *action)
442 {
443         size_t off;
444
445         switch (action->type) {
446                 union {
447                         const struct rte_flow_action_rss *rss;
448                         const struct rte_flow_action_vxlan_encap *vxlan_encap;
449                         const struct rte_flow_action_nvgre_encap *nvgre_encap;
450                 } src;
451                 union {
452                         struct rte_flow_action_rss *rss;
453                         struct rte_flow_action_vxlan_encap *vxlan_encap;
454                         struct rte_flow_action_nvgre_encap *nvgre_encap;
455                 } dst;
456                 size_t tmp;
457                 int ret;
458
459         case RTE_FLOW_ACTION_TYPE_RSS:
460                 src.rss = action->conf;
461                 dst.rss = buf;
462                 rte_memcpy(dst.rss,
463                            (&(struct rte_flow_action_rss){
464                                 .func = src.rss->func,
465                                 .level = src.rss->level,
466                                 .types = src.rss->types,
467                                 .key_len = src.rss->key_len,
468                                 .queue_num = src.rss->queue_num,
469                            }),
470                            size > sizeof(*dst.rss) ? sizeof(*dst.rss) : size);
471                 off = sizeof(*dst.rss);
472                 if (src.rss->key_len) {
473                         off = RTE_ALIGN_CEIL(off, sizeof(*dst.rss->key));
474                         tmp = sizeof(*src.rss->key) * src.rss->key_len;
475                         if (size >= off + tmp)
476                                 dst.rss->key = rte_memcpy
477                                         ((void *)((uintptr_t)dst.rss + off),
478                                          src.rss->key, tmp);
479                         off += tmp;
480                 }
481                 if (src.rss->queue_num) {
482                         off = RTE_ALIGN_CEIL(off, sizeof(*dst.rss->queue));
483                         tmp = sizeof(*src.rss->queue) * src.rss->queue_num;
484                         if (size >= off + tmp)
485                                 dst.rss->queue = rte_memcpy
486                                         ((void *)((uintptr_t)dst.rss + off),
487                                          src.rss->queue, tmp);
488                         off += tmp;
489                 }
490                 break;
491         case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
492         case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
493                 src.vxlan_encap = action->conf;
494                 dst.vxlan_encap = buf;
495                 RTE_BUILD_BUG_ON(sizeof(*src.vxlan_encap) !=
496                                  sizeof(*src.nvgre_encap) ||
497                                  offsetof(struct rte_flow_action_vxlan_encap,
498                                           definition) !=
499                                  offsetof(struct rte_flow_action_nvgre_encap,
500                                           definition));
501                 off = sizeof(*dst.vxlan_encap);
502                 if (src.vxlan_encap->definition) {
503                         off = RTE_ALIGN_CEIL
504                                 (off, sizeof(*dst.vxlan_encap->definition));
505                         ret = rte_flow_conv
506                                 (RTE_FLOW_CONV_OP_PATTERN,
507                                  (void *)((uintptr_t)dst.vxlan_encap + off),
508                                  size > off ? size - off : 0,
509                                  src.vxlan_encap->definition, NULL);
510                         if (ret < 0)
511                                 return 0;
512                         if (size >= off + ret)
513                                 dst.vxlan_encap->definition =
514                                         (void *)((uintptr_t)dst.vxlan_encap +
515                                                  off);
516                         off += ret;
517                 }
518                 break;
519         default:
520                 off = rte_flow_desc_action[action->type].size;
521                 rte_memcpy(buf, action->conf, (size > off ? off : size));
522                 break;
523         }
524         return off;
525 }
526
527 /**
528  * Copy a list of pattern items.
529  *
530  * @param[out] dst
531  *   Destination buffer. Can be NULL if @p size is zero.
532  * @param size
533  *   Size of @p dst in bytes.
534  * @param[in] src
535  *   Source pattern items.
536  * @param num
537  *   Maximum number of pattern items to process from @p src or 0 to process
538  *   the entire list. In both cases, processing stops after
539  *   RTE_FLOW_ITEM_TYPE_END is encountered.
540  * @param[out] error
541  *   Perform verbose error reporting if not NULL.
542  *
543  * @return
544  *   A positive value representing the number of bytes needed to store
545  *   pattern items regardless of @p size on success (@p buf contents are
546  *   truncated to @p size if not large enough), a negative errno value
547  *   otherwise and rte_errno is set.
548  */
549 static int
550 rte_flow_conv_pattern(struct rte_flow_item *dst,
551                       const size_t size,
552                       const struct rte_flow_item *src,
553                       unsigned int num,
554                       struct rte_flow_error *error)
555 {
556         uintptr_t data = (uintptr_t)dst;
557         size_t off;
558         size_t ret;
559         unsigned int i;
560
561         for (i = 0, off = 0; !num || i != num; ++i, ++src, ++dst) {
562                 if ((size_t)src->type >= RTE_DIM(rte_flow_desc_item) ||
563                     !rte_flow_desc_item[src->type].name)
564                         return rte_flow_error_set
565                                 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, src,
566                                  "cannot convert unknown item type");
567                 if (size >= off + sizeof(*dst))
568                         *dst = (struct rte_flow_item){
569                                 .type = src->type,
570                         };
571                 off += sizeof(*dst);
572                 if (!src->type)
573                         num = i + 1;
574         }
575         num = i;
576         src -= num;
577         dst -= num;
578         do {
579                 if (src->spec) {
580                         off = RTE_ALIGN_CEIL(off, sizeof(double));
581                         ret = rte_flow_conv_item_spec
582                                 ((void *)(data + off),
583                                  size > off ? size - off : 0, src,
584                                  RTE_FLOW_CONV_ITEM_SPEC);
585                         if (size && size >= off + ret)
586                                 dst->spec = (void *)(data + off);
587                         off += ret;
588
589                 }
590                 if (src->last) {
591                         off = RTE_ALIGN_CEIL(off, sizeof(double));
592                         ret = rte_flow_conv_item_spec
593                                 ((void *)(data + off),
594                                  size > off ? size - off : 0, src,
595                                  RTE_FLOW_CONV_ITEM_LAST);
596                         if (size && size >= off + ret)
597                                 dst->last = (void *)(data + off);
598                         off += ret;
599                 }
600                 if (src->mask) {
601                         off = RTE_ALIGN_CEIL(off, sizeof(double));
602                         ret = rte_flow_conv_item_spec
603                                 ((void *)(data + off),
604                                  size > off ? size - off : 0, src,
605                                  RTE_FLOW_CONV_ITEM_MASK);
606                         if (size && size >= off + ret)
607                                 dst->mask = (void *)(data + off);
608                         off += ret;
609                 }
610                 ++src;
611                 ++dst;
612         } while (--num);
613         return off;
614 }
615
616 /**
617  * Copy a list of actions.
618  *
619  * @param[out] dst
620  *   Destination buffer. Can be NULL if @p size is zero.
621  * @param size
622  *   Size of @p dst in bytes.
623  * @param[in] src
624  *   Source actions.
625  * @param num
626  *   Maximum number of actions to process from @p src or 0 to process the
627  *   entire list. In both cases, processing stops after
628  *   RTE_FLOW_ACTION_TYPE_END is encountered.
629  * @param[out] error
630  *   Perform verbose error reporting if not NULL.
631  *
632  * @return
633  *   A positive value representing the number of bytes needed to store
634  *   actions regardless of @p size on success (@p buf contents are truncated
635  *   to @p size if not large enough), a negative errno value otherwise and
636  *   rte_errno is set.
637  */
638 static int
639 rte_flow_conv_actions(struct rte_flow_action *dst,
640                       const size_t size,
641                       const struct rte_flow_action *src,
642                       unsigned int num,
643                       struct rte_flow_error *error)
644 {
645         uintptr_t data = (uintptr_t)dst;
646         size_t off;
647         size_t ret;
648         unsigned int i;
649
650         for (i = 0, off = 0; !num || i != num; ++i, ++src, ++dst) {
651                 if ((size_t)src->type >= RTE_DIM(rte_flow_desc_action) ||
652                     !rte_flow_desc_action[src->type].name)
653                         return rte_flow_error_set
654                                 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
655                                  src, "cannot convert unknown action type");
656                 if (size >= off + sizeof(*dst))
657                         *dst = (struct rte_flow_action){
658                                 .type = src->type,
659                         };
660                 off += sizeof(*dst);
661                 if (!src->type)
662                         num = i + 1;
663         }
664         num = i;
665         src -= num;
666         dst -= num;
667         do {
668                 if (src->conf) {
669                         off = RTE_ALIGN_CEIL(off, sizeof(double));
670                         ret = rte_flow_conv_action_conf
671                                 ((void *)(data + off),
672                                  size > off ? size - off : 0, src);
673                         if (size && size >= off + ret)
674                                 dst->conf = (void *)(data + off);
675                         off += ret;
676                 }
677                 ++src;
678                 ++dst;
679         } while (--num);
680         return off;
681 }
682
683 /**
684  * Copy flow rule components.
685  *
686  * This comprises the flow rule descriptor itself, attributes, pattern and
687  * actions list. NULL components in @p src are skipped.
688  *
689  * @param[out] dst
690  *   Destination buffer. Can be NULL if @p size is zero.
691  * @param size
692  *   Size of @p dst in bytes.
693  * @param[in] src
694  *   Source flow rule descriptor.
695  * @param[out] error
696  *   Perform verbose error reporting if not NULL.
697  *
698  * @return
699  *   A positive value representing the number of bytes needed to store all
700  *   components including the descriptor regardless of @p size on success
701  *   (@p buf contents are truncated to @p size if not large enough), a
702  *   negative errno value otherwise and rte_errno is set.
703  */
704 static int
705 rte_flow_conv_rule(struct rte_flow_conv_rule *dst,
706                    const size_t size,
707                    const struct rte_flow_conv_rule *src,
708                    struct rte_flow_error *error)
709 {
710         size_t off;
711         int ret;
712
713         rte_memcpy(dst,
714                    (&(struct rte_flow_conv_rule){
715                         .attr = NULL,
716                         .pattern = NULL,
717                         .actions = NULL,
718                    }),
719                    size > sizeof(*dst) ? sizeof(*dst) : size);
720         off = sizeof(*dst);
721         if (src->attr_ro) {
722                 off = RTE_ALIGN_CEIL(off, sizeof(double));
723                 if (size && size >= off + sizeof(*dst->attr))
724                         dst->attr = rte_memcpy
725                                 ((void *)((uintptr_t)dst + off),
726                                  src->attr_ro, sizeof(*dst->attr));
727                 off += sizeof(*dst->attr);
728         }
729         if (src->pattern_ro) {
730                 off = RTE_ALIGN_CEIL(off, sizeof(double));
731                 ret = rte_flow_conv_pattern((void *)((uintptr_t)dst + off),
732                                             size > off ? size - off : 0,
733                                             src->pattern_ro, 0, error);
734                 if (ret < 0)
735                         return ret;
736                 if (size && size >= off + (size_t)ret)
737                         dst->pattern = (void *)((uintptr_t)dst + off);
738                 off += ret;
739         }
740         if (src->actions_ro) {
741                 off = RTE_ALIGN_CEIL(off, sizeof(double));
742                 ret = rte_flow_conv_actions((void *)((uintptr_t)dst + off),
743                                             size > off ? size - off : 0,
744                                             src->actions_ro, 0, error);
745                 if (ret < 0)
746                         return ret;
747                 if (size >= off + (size_t)ret)
748                         dst->actions = (void *)((uintptr_t)dst + off);
749                 off += ret;
750         }
751         return off;
752 }
753
754 /**
755  * Retrieve the name of a pattern item/action type.
756  *
757  * @param is_action
758  *   Nonzero when @p src represents an action type instead of a pattern item
759  *   type.
760  * @param is_ptr
761  *   Nonzero to write string address instead of contents into @p dst.
762  * @param[out] dst
763  *   Destination buffer. Can be NULL if @p size is zero.
764  * @param size
765  *   Size of @p dst in bytes.
766  * @param[in] src
767  *   Depending on @p is_action, source pattern item or action type cast as a
768  *   pointer.
769  * @param[out] error
770  *   Perform verbose error reporting if not NULL.
771  *
772  * @return
773  *   A positive value representing the number of bytes needed to store the
774  *   name or its address regardless of @p size on success (@p buf contents
775  *   are truncated to @p size if not large enough), a negative errno value
776  *   otherwise and rte_errno is set.
777  */
778 static int
779 rte_flow_conv_name(int is_action,
780                    int is_ptr,
781                    char *dst,
782                    const size_t size,
783                    const void *src,
784                    struct rte_flow_error *error)
785 {
786         struct desc_info {
787                 const struct rte_flow_desc_data *data;
788                 size_t num;
789         };
790         static const struct desc_info info_rep[2] = {
791                 { rte_flow_desc_item, RTE_DIM(rte_flow_desc_item), },
792                 { rte_flow_desc_action, RTE_DIM(rte_flow_desc_action), },
793         };
794         const struct desc_info *const info = &info_rep[!!is_action];
795         unsigned int type = (uintptr_t)src;
796
797         if (type >= info->num)
798                 return rte_flow_error_set
799                         (error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
800                          "unknown object type to retrieve the name of");
801         if (!is_ptr)
802                 return strlcpy(dst, info->data[type].name, size);
803         if (size >= sizeof(const char **))
804                 *((const char **)dst) = info->data[type].name;
805         return sizeof(const char **);
806 }
807
808 /** Helper function to convert flow API objects. */
809 int
810 rte_flow_conv(enum rte_flow_conv_op op,
811               void *dst,
812               size_t size,
813               const void *src,
814               struct rte_flow_error *error)
815 {
816         switch (op) {
817                 const struct rte_flow_attr *attr;
818
819         case RTE_FLOW_CONV_OP_NONE:
820                 return 0;
821         case RTE_FLOW_CONV_OP_ATTR:
822                 attr = src;
823                 if (size > sizeof(*attr))
824                         size = sizeof(*attr);
825                 rte_memcpy(dst, attr, size);
826                 return sizeof(*attr);
827         case RTE_FLOW_CONV_OP_ITEM:
828                 return rte_flow_conv_pattern(dst, size, src, 1, error);
829         case RTE_FLOW_CONV_OP_ACTION:
830                 return rte_flow_conv_actions(dst, size, src, 1, error);
831         case RTE_FLOW_CONV_OP_PATTERN:
832                 return rte_flow_conv_pattern(dst, size, src, 0, error);
833         case RTE_FLOW_CONV_OP_ACTIONS:
834                 return rte_flow_conv_actions(dst, size, src, 0, error);
835         case RTE_FLOW_CONV_OP_RULE:
836                 return rte_flow_conv_rule(dst, size, src, error);
837         case RTE_FLOW_CONV_OP_ITEM_NAME:
838                 return rte_flow_conv_name(0, 0, dst, size, src, error);
839         case RTE_FLOW_CONV_OP_ACTION_NAME:
840                 return rte_flow_conv_name(1, 0, dst, size, src, error);
841         case RTE_FLOW_CONV_OP_ITEM_NAME_PTR:
842                 return rte_flow_conv_name(0, 1, dst, size, src, error);
843         case RTE_FLOW_CONV_OP_ACTION_NAME_PTR:
844                 return rte_flow_conv_name(1, 1, dst, size, src, error);
845         }
846         return rte_flow_error_set
847                 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
848                  "unknown object conversion operation");
849 }
850
851 /** Store a full rte_flow description. */
852 size_t
853 rte_flow_copy(struct rte_flow_desc *desc, size_t len,
854               const struct rte_flow_attr *attr,
855               const struct rte_flow_item *items,
856               const struct rte_flow_action *actions)
857 {
858         /*
859          * Overlap struct rte_flow_conv with struct rte_flow_desc in order
860          * to convert the former to the latter without wasting space.
861          */
862         struct rte_flow_conv_rule *dst =
863                 len ?
864                 (void *)((uintptr_t)desc +
865                          (offsetof(struct rte_flow_desc, actions) -
866                           offsetof(struct rte_flow_conv_rule, actions))) :
867                 NULL;
868         size_t dst_size =
869                 len > sizeof(*desc) - sizeof(*dst) ?
870                 len - (sizeof(*desc) - sizeof(*dst)) :
871                 0;
872         struct rte_flow_conv_rule src = {
873                 .attr_ro = NULL,
874                 .pattern_ro = items,
875                 .actions_ro = actions,
876         };
877         int ret;
878
879         RTE_BUILD_BUG_ON(sizeof(struct rte_flow_desc) <
880                          sizeof(struct rte_flow_conv_rule));
881         if (dst_size &&
882             (&dst->pattern != &desc->items ||
883              &dst->actions != &desc->actions ||
884              (uintptr_t)(dst + 1) != (uintptr_t)(desc + 1))) {
885                 rte_errno = EINVAL;
886                 return 0;
887         }
888         ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, dst, dst_size, &src, NULL);
889         if (ret < 0)
890                 return 0;
891         ret += sizeof(*desc) - sizeof(*dst);
892         rte_memcpy(desc,
893                    (&(struct rte_flow_desc){
894                         .size = ret,
895                         .attr = *attr,
896                         .items = dst_size ? dst->pattern : NULL,
897                         .actions = dst_size ? dst->actions : NULL,
898                    }),
899                    len > sizeof(*desc) ? sizeof(*desc) : len);
900         return ret;
901 }
902
903 /**
904  * Expand RSS flows into several possible flows according to the RSS hash
905  * fields requested and the driver capabilities.
906  */
907 int
908 rte_flow_expand_rss(struct rte_flow_expand_rss *buf, size_t size,
909                     const struct rte_flow_item *pattern, uint64_t types,
910                     const struct rte_flow_expand_node graph[],
911                     int graph_root_index)
912 {
913         const int elt_n = 8;
914         const struct rte_flow_item *item;
915         const struct rte_flow_expand_node *node = &graph[graph_root_index];
916         const int *next_node;
917         const int *stack[elt_n];
918         int stack_pos = 0;
919         struct rte_flow_item flow_items[elt_n];
920         unsigned int i;
921         size_t lsize;
922         size_t user_pattern_size = 0;
923         void *addr = NULL;
924
925         lsize = offsetof(struct rte_flow_expand_rss, entry) +
926                 elt_n * sizeof(buf->entry[0]);
927         if (lsize <= size) {
928                 buf->entry[0].priority = 0;
929                 buf->entry[0].pattern = (void *)&buf->entry[elt_n];
930                 buf->entries = 0;
931                 addr = buf->entry[0].pattern;
932         }
933         for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
934                 const struct rte_flow_expand_node *next = NULL;
935
936                 for (i = 0; node->next && node->next[i]; ++i) {
937                         next = &graph[node->next[i]];
938                         if (next->type == item->type)
939                                 break;
940                 }
941                 if (next)
942                         node = next;
943                 user_pattern_size += sizeof(*item);
944         }
945         user_pattern_size += sizeof(*item); /* Handle END item. */
946         lsize += user_pattern_size;
947         /* Copy the user pattern in the first entry of the buffer. */
948         if (lsize <= size) {
949                 rte_memcpy(addr, pattern, user_pattern_size);
950                 addr = (void *)(((uintptr_t)addr) + user_pattern_size);
951                 buf->entries = 1;
952         }
953         /* Start expanding. */
954         memset(flow_items, 0, sizeof(flow_items));
955         user_pattern_size -= sizeof(*item);
956         next_node = node->next;
957         stack[stack_pos] = next_node;
958         node = next_node ? &graph[*next_node] : NULL;
959         while (node) {
960                 flow_items[stack_pos].type = node->type;
961                 if (node->rss_types & types) {
962                         /*
963                          * compute the number of items to copy from the
964                          * expansion and copy it.
965                          * When the stack_pos is 0, there are 1 element in it,
966                          * plus the addition END item.
967                          */
968                         int elt = stack_pos + 2;
969
970                         flow_items[stack_pos + 1].type = RTE_FLOW_ITEM_TYPE_END;
971                         lsize += elt * sizeof(*item) + user_pattern_size;
972                         if (lsize <= size) {
973                                 size_t n = elt * sizeof(*item);
974
975                                 buf->entry[buf->entries].priority =
976                                         stack_pos + 1;
977                                 buf->entry[buf->entries].pattern = addr;
978                                 buf->entries++;
979                                 rte_memcpy(addr, buf->entry[0].pattern,
980                                            user_pattern_size);
981                                 addr = (void *)(((uintptr_t)addr) +
982                                                 user_pattern_size);
983                                 rte_memcpy(addr, flow_items, n);
984                                 addr = (void *)(((uintptr_t)addr) + n);
985                         }
986                 }
987                 /* Go deeper. */
988                 if (node->next) {
989                         next_node = node->next;
990                         if (stack_pos++ == elt_n) {
991                                 rte_errno = E2BIG;
992                                 return -rte_errno;
993                         }
994                         stack[stack_pos] = next_node;
995                 } else if (*(next_node + 1)) {
996                         /* Follow up with the next possibility. */
997                         ++next_node;
998                 } else {
999                         /* Move to the next path. */
1000                         if (stack_pos)
1001                                 next_node = stack[--stack_pos];
1002                         next_node++;
1003                         stack[stack_pos] = next_node;
1004                 }
1005                 node = *next_node ? &graph[*next_node] : NULL;
1006         };
1007         return lsize;
1008 }