Bug Summary

File:home/bhubbard/working/src/ceph/src/spdk/dpdk/lib/librte_ethdev/rte_flow.c
Warning:line 397, column 10
Access to field 'length' results in a dereference of a null pointer (loaded from field 'raw')

Annotated Source Code

[?] Use j/k keys for keyboard navigation

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