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