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