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