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