]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2019 Intel Corporation | |
3 | */ | |
4 | ||
5 | #include <sys/queue.h> | |
6 | #include <stdio.h> | |
7 | #include <errno.h> | |
8 | #include <stdint.h> | |
9 | #include <string.h> | |
10 | #include <unistd.h> | |
11 | #include <stdarg.h> | |
12 | ||
13 | #include <rte_debug.h> | |
14 | #include <rte_ether.h> | |
15 | #include <rte_ethdev_driver.h> | |
16 | #include <rte_log.h> | |
17 | #include <rte_malloc.h> | |
18 | #include <rte_eth_ctrl.h> | |
19 | #include <rte_tailq.h> | |
20 | #include <rte_flow_driver.h> | |
21 | ||
22 | #include "ice_logs.h" | |
23 | #include "base/ice_type.h" | |
24 | #include "base/ice_flow.h" | |
25 | #include "ice_ethdev.h" | |
26 | #include "ice_generic_flow.h" | |
27 | ||
28 | struct rss_type_match_hdr { | |
29 | uint32_t hdr_mask; | |
30 | uint64_t eth_rss_hint; | |
31 | }; | |
32 | ||
33 | struct ice_hash_match_type { | |
34 | uint64_t hash_type; | |
35 | uint64_t hash_flds; | |
36 | }; | |
37 | ||
38 | struct rss_meta { | |
39 | uint32_t pkt_hdr; | |
40 | uint64_t hash_flds; | |
41 | uint8_t hash_function; | |
42 | }; | |
43 | ||
44 | struct ice_hash_flow_cfg { | |
45 | bool simple_xor; | |
46 | struct ice_rss_cfg rss_cfg; | |
47 | }; | |
48 | ||
49 | static int | |
50 | ice_hash_init(struct ice_adapter *ad); | |
51 | ||
52 | static int | |
53 | ice_hash_create(struct ice_adapter *ad, | |
54 | struct rte_flow *flow, | |
55 | void *meta, | |
56 | struct rte_flow_error *error); | |
57 | ||
58 | static int | |
59 | ice_hash_destroy(struct ice_adapter *ad, | |
60 | struct rte_flow *flow, | |
61 | struct rte_flow_error *error); | |
62 | ||
63 | static void | |
64 | ice_hash_uninit(struct ice_adapter *ad); | |
65 | ||
66 | static void | |
67 | ice_hash_free(struct rte_flow *flow); | |
68 | ||
69 | static int | |
70 | ice_hash_parse_pattern_action(struct ice_adapter *ad, | |
71 | struct ice_pattern_match_item *array, | |
72 | uint32_t array_len, | |
73 | const struct rte_flow_item pattern[], | |
74 | const struct rte_flow_action actions[], | |
75 | void **meta, | |
76 | struct rte_flow_error *error); | |
77 | ||
78 | /* The first member is protocol header, the second member is ETH_RSS_*. */ | |
79 | struct rss_type_match_hdr hint_0 = { | |
80 | ICE_FLOW_SEG_HDR_NONE, 0}; | |
81 | struct rss_type_match_hdr hint_1 = { | |
82 | ICE_FLOW_SEG_HDR_IPV4, ETH_RSS_IPV4}; | |
83 | struct rss_type_match_hdr hint_2 = { | |
84 | ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_UDP, ETH_RSS_NONFRAG_IPV4_UDP}; | |
85 | struct rss_type_match_hdr hint_3 = { | |
86 | ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_TCP, ETH_RSS_NONFRAG_IPV4_TCP}; | |
87 | struct rss_type_match_hdr hint_4 = { | |
88 | ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_SCTP, ETH_RSS_NONFRAG_IPV4_SCTP}; | |
89 | struct rss_type_match_hdr hint_5 = { | |
90 | ICE_FLOW_SEG_HDR_IPV6, ETH_RSS_IPV6}; | |
91 | struct rss_type_match_hdr hint_6 = { | |
92 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_UDP, ETH_RSS_NONFRAG_IPV6_UDP}; | |
93 | struct rss_type_match_hdr hint_7 = { | |
94 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_TCP, ETH_RSS_NONFRAG_IPV6_TCP}; | |
95 | struct rss_type_match_hdr hint_8 = { | |
96 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_SCTP, ETH_RSS_NONFRAG_IPV6_SCTP}; | |
97 | struct rss_type_match_hdr hint_9 = { | |
98 | ICE_FLOW_SEG_HDR_GTPU_EH, ETH_RSS_IPV4}; | |
99 | struct rss_type_match_hdr hint_10 = { | |
100 | ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_IPV4}; | |
101 | struct rss_type_match_hdr hint_11 = { | |
102 | ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_NONFRAG_IPV4_UDP}; | |
103 | struct rss_type_match_hdr hint_12 = { | |
104 | ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_NONFRAG_IPV4_TCP}; | |
105 | struct rss_type_match_hdr hint_13 = { | |
106 | ICE_FLOW_SEG_HDR_PPPOE, ETH_RSS_NONFRAG_IPV4_SCTP}; | |
107 | struct rss_type_match_hdr hint_14 = { | |
108 | ICE_FLOW_SEG_HDR_GTPU_EH, ETH_RSS_NONFRAG_IPV4_UDP}; | |
109 | struct rss_type_match_hdr hint_15 = { | |
110 | ICE_FLOW_SEG_HDR_GTPU_EH, ETH_RSS_NONFRAG_IPV4_TCP}; | |
111 | ||
112 | /* Supported pattern for os default package. */ | |
113 | static struct ice_pattern_match_item ice_hash_pattern_list_os[] = { | |
114 | {pattern_eth_ipv4, ICE_INSET_NONE, &hint_1}, | |
115 | {pattern_eth_ipv4_udp, ICE_INSET_NONE, &hint_2}, | |
116 | {pattern_eth_ipv4_tcp, ICE_INSET_NONE, &hint_3}, | |
117 | {pattern_eth_ipv4_sctp, ICE_INSET_NONE, &hint_4}, | |
118 | {pattern_eth_ipv6, ICE_INSET_NONE, &hint_5}, | |
119 | {pattern_eth_ipv6_udp, ICE_INSET_NONE, &hint_6}, | |
120 | {pattern_eth_ipv6_tcp, ICE_INSET_NONE, &hint_7}, | |
121 | {pattern_eth_ipv6_sctp, ICE_INSET_NONE, &hint_8}, | |
122 | {pattern_empty, ICE_INSET_NONE, &hint_0}, | |
123 | }; | |
124 | ||
125 | /* Supported pattern for comms package. */ | |
126 | static struct ice_pattern_match_item ice_hash_pattern_list_comms[] = { | |
127 | {pattern_eth_ipv4, ICE_INSET_NONE, &hint_1}, | |
128 | {pattern_eth_ipv4_udp, ICE_INSET_NONE, &hint_2}, | |
129 | {pattern_eth_ipv4_tcp, ICE_INSET_NONE, &hint_3}, | |
130 | {pattern_eth_ipv4_sctp, ICE_INSET_NONE, &hint_4}, | |
131 | {pattern_eth_ipv6, ICE_INSET_NONE, &hint_5}, | |
132 | {pattern_eth_ipv6_udp, ICE_INSET_NONE, &hint_6}, | |
133 | {pattern_eth_ipv6_tcp, ICE_INSET_NONE, &hint_7}, | |
134 | {pattern_eth_ipv6_sctp, ICE_INSET_NONE, &hint_8}, | |
135 | {pattern_empty, ICE_INSET_NONE, &hint_0}, | |
136 | {pattern_eth_ipv4_gtpu_eh_ipv4, ICE_INSET_NONE, &hint_9}, | |
137 | {pattern_eth_ipv4_gtpu_eh_ipv4_udp, ICE_INSET_NONE, &hint_14}, | |
138 | {pattern_eth_ipv4_gtpu_eh_ipv4_tcp, ICE_INSET_NONE, &hint_15}, | |
139 | {pattern_eth_pppoes_ipv4, ICE_INSET_NONE, &hint_10}, | |
140 | {pattern_eth_pppoes_ipv4_udp, ICE_INSET_NONE, &hint_11}, | |
141 | {pattern_eth_pppoes_ipv4_tcp, ICE_INSET_NONE, &hint_12}, | |
142 | {pattern_eth_pppoes_ipv4_sctp, ICE_INSET_NONE, &hint_13}, | |
143 | }; | |
144 | ||
145 | /** | |
146 | * The first member is input set combination, | |
147 | * the second member is hash fields. | |
148 | */ | |
149 | struct ice_hash_match_type ice_hash_type_list[] = { | |
150 | {ETH_RSS_IPV4 | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)}, | |
151 | {ETH_RSS_IPV4 | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)}, | |
152 | {ETH_RSS_IPV4, ICE_FLOW_HASH_IPV4}, | |
153 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, | |
154 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, | |
155 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)}, | |
156 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, | |
157 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, | |
158 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)}, | |
159 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, | |
160 | {ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, | |
161 | {ETH_RSS_NONFRAG_IPV4_UDP, ICE_HASH_UDP_IPV4}, | |
162 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, | |
163 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, | |
164 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)}, | |
165 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, | |
166 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, | |
167 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)}, | |
168 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, | |
169 | {ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, | |
170 | {ETH_RSS_NONFRAG_IPV4_TCP, ICE_HASH_TCP_IPV4}, | |
171 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, | |
172 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, | |
173 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)}, | |
174 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, | |
175 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, | |
176 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)}, | |
177 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, | |
178 | {ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, | |
179 | {ETH_RSS_NONFRAG_IPV4_SCTP, ICE_HASH_SCTP_IPV4}, | |
180 | {ETH_RSS_IPV6 | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)}, | |
181 | {ETH_RSS_IPV6 | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)}, | |
182 | {ETH_RSS_IPV6, ICE_FLOW_HASH_IPV6}, | |
183 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, | |
184 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, | |
185 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)}, | |
186 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, | |
187 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, | |
188 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)}, | |
189 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)}, | |
190 | {ETH_RSS_NONFRAG_IPV6_UDP | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)}, | |
191 | {ETH_RSS_NONFRAG_IPV6_UDP, ICE_HASH_UDP_IPV6}, | |
192 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, | |
193 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, | |
194 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)}, | |
195 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, | |
196 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, | |
197 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)}, | |
198 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)}, | |
199 | {ETH_RSS_NONFRAG_IPV6_TCP | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)}, | |
200 | {ETH_RSS_NONFRAG_IPV6_TCP, ICE_HASH_TCP_IPV6}, | |
201 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, | |
202 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_SRC_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, | |
203 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)}, | |
204 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, | |
205 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_DST_ONLY | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) | BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, | |
206 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L3_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)}, | |
207 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L4_SRC_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)}, | |
208 | {ETH_RSS_NONFRAG_IPV6_SCTP | ETH_RSS_L4_DST_ONLY, BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)}, | |
209 | {ETH_RSS_NONFRAG_IPV6_SCTP, ICE_HASH_SCTP_IPV6}, | |
210 | }; | |
211 | ||
212 | static struct ice_flow_engine ice_hash_engine = { | |
213 | .init = ice_hash_init, | |
214 | .create = ice_hash_create, | |
215 | .destroy = ice_hash_destroy, | |
216 | .uninit = ice_hash_uninit, | |
217 | .free = ice_hash_free, | |
218 | .type = ICE_FLOW_ENGINE_HASH, | |
219 | }; | |
220 | ||
221 | /* Register parser for os package. */ | |
222 | static struct ice_flow_parser ice_hash_parser_os = { | |
223 | .engine = &ice_hash_engine, | |
224 | .array = ice_hash_pattern_list_os, | |
225 | .array_len = RTE_DIM(ice_hash_pattern_list_os), | |
226 | .parse_pattern_action = ice_hash_parse_pattern_action, | |
227 | .stage = ICE_FLOW_STAGE_RSS, | |
228 | }; | |
229 | ||
230 | /* Register parser for comms package. */ | |
231 | static struct ice_flow_parser ice_hash_parser_comms = { | |
232 | .engine = &ice_hash_engine, | |
233 | .array = ice_hash_pattern_list_comms, | |
234 | .array_len = RTE_DIM(ice_hash_pattern_list_comms), | |
235 | .parse_pattern_action = ice_hash_parse_pattern_action, | |
236 | .stage = ICE_FLOW_STAGE_RSS, | |
237 | }; | |
238 | ||
239 | RTE_INIT(ice_hash_engine_init) | |
240 | { | |
241 | struct ice_flow_engine *engine = &ice_hash_engine; | |
242 | ice_register_flow_engine(engine); | |
243 | } | |
244 | ||
245 | static int | |
246 | ice_hash_init(struct ice_adapter *ad) | |
247 | { | |
248 | struct ice_flow_parser *parser = NULL; | |
249 | ||
250 | if (ad->hw.dcf_enabled) | |
251 | return 0; | |
252 | ||
253 | if (ad->active_pkg_type == ICE_PKG_TYPE_OS_DEFAULT) | |
254 | parser = &ice_hash_parser_os; | |
255 | else if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS) | |
256 | parser = &ice_hash_parser_comms; | |
257 | else | |
258 | return -EINVAL; | |
259 | ||
260 | return ice_register_parser(parser, ad); | |
261 | } | |
262 | ||
263 | static int | |
264 | ice_hash_check_inset(const struct rte_flow_item pattern[], | |
265 | struct rte_flow_error *error) | |
266 | { | |
267 | const struct rte_flow_item *item = pattern; | |
268 | ||
269 | for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { | |
270 | if (item->last) { | |
271 | rte_flow_error_set(error, EINVAL, | |
272 | RTE_FLOW_ERROR_TYPE_ITEM, item, | |
273 | "Not support range"); | |
274 | return -rte_errno; | |
275 | } | |
276 | ||
277 | /* Ignore spec and mask. */ | |
278 | if (item->spec || item->mask) { | |
279 | rte_flow_error_set(error, EINVAL, | |
280 | RTE_FLOW_ERROR_TYPE_ITEM, item, | |
281 | "Invalid spec/mask."); | |
282 | return -rte_errno; | |
283 | } | |
284 | } | |
285 | ||
286 | return 0; | |
287 | } | |
288 | ||
289 | static int | |
290 | ice_hash_parse_action(struct ice_pattern_match_item *pattern_match_item, | |
291 | const struct rte_flow_action actions[], | |
292 | void **meta, | |
293 | struct rte_flow_error *error) | |
294 | { | |
295 | const struct rte_flow_action *action; | |
296 | enum rte_flow_action_type action_type; | |
297 | const struct rte_flow_action_rss *rss; | |
298 | struct rss_type_match_hdr *m = (struct rss_type_match_hdr *) | |
299 | (pattern_match_item->meta); | |
300 | uint32_t type_list_len = RTE_DIM(ice_hash_type_list); | |
301 | struct ice_hash_match_type *type_match_item; | |
302 | uint64_t rss_hf; | |
303 | uint16_t i; | |
304 | ||
305 | /* Supported action is RSS. */ | |
306 | for (action = actions; action->type != | |
307 | RTE_FLOW_ACTION_TYPE_END; action++) { | |
308 | action_type = action->type; | |
309 | switch (action_type) { | |
310 | case RTE_FLOW_ACTION_TYPE_RSS: | |
311 | rss = action->conf; | |
312 | rss_hf = rss->types; | |
313 | ||
314 | /** | |
315 | * Check simultaneous use of SRC_ONLY and DST_ONLY | |
316 | * of the same level. | |
317 | */ | |
318 | rss_hf = rte_eth_rss_hf_refine(rss_hf); | |
319 | ||
320 | /* Check if pattern is empty. */ | |
321 | if (pattern_match_item->pattern_list != | |
322 | pattern_empty && rss->func == | |
323 | RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) | |
324 | return rte_flow_error_set(error, ENOTSUP, | |
325 | RTE_FLOW_ERROR_TYPE_ACTION, action, | |
326 | "Not supported flow"); | |
327 | ||
328 | /* Check if rss types match pattern. */ | |
329 | if (rss->func != RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { | |
330 | if (((rss_hf & ETH_RSS_IPV4) != m->eth_rss_hint) && | |
331 | ((rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) != m->eth_rss_hint) && | |
332 | ((rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) != m->eth_rss_hint) && | |
333 | ((rss_hf & ETH_RSS_NONFRAG_IPV4_SCTP) != m->eth_rss_hint) && | |
334 | ((rss_hf & ETH_RSS_IPV6) != m->eth_rss_hint) && | |
335 | ((rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) != m->eth_rss_hint) && | |
336 | ((rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) != m->eth_rss_hint) && | |
337 | ((rss_hf & ETH_RSS_NONFRAG_IPV6_SCTP) != m->eth_rss_hint)) | |
338 | return rte_flow_error_set(error, | |
339 | ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, | |
340 | action, "Not supported RSS types"); | |
341 | } | |
342 | ||
343 | if (rss->level) | |
344 | return rte_flow_error_set(error, ENOTSUP, | |
345 | RTE_FLOW_ERROR_TYPE_ACTION, action, | |
346 | "a nonzero RSS encapsulation level is not supported"); | |
347 | ||
348 | if (rss->key_len) | |
349 | return rte_flow_error_set(error, ENOTSUP, | |
350 | RTE_FLOW_ERROR_TYPE_ACTION, action, | |
351 | "a nonzero RSS key_len is not supported"); | |
352 | ||
353 | if (rss->queue) | |
354 | return rte_flow_error_set(error, ENOTSUP, | |
355 | RTE_FLOW_ERROR_TYPE_ACTION, action, | |
356 | "a non-NULL RSS queue is not supported"); | |
357 | ||
358 | /* Check hash function and save it to rss_meta. */ | |
359 | if (rss->func == | |
360 | RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) | |
361 | ((struct rss_meta *)*meta)->hash_function = | |
362 | RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; | |
363 | ||
364 | if (rss->func == | |
365 | RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) | |
366 | ((struct rss_meta *)*meta)->hash_function = | |
367 | RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ; | |
368 | ||
369 | type_match_item = rte_zmalloc("ice_type_match_item", | |
370 | sizeof(struct ice_hash_match_type), 0); | |
371 | if (!type_match_item) { | |
372 | rte_flow_error_set(error, EINVAL, | |
373 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
374 | "No memory for type_match_item"); | |
375 | return -ENOMEM; | |
376 | } | |
377 | ||
378 | /* Find matched hash fields according to hash type. */ | |
379 | for (i = 0; i < type_list_len; i++) { | |
380 | if (rss_hf == | |
381 | ice_hash_type_list[i].hash_type) { | |
382 | type_match_item->hash_type = | |
383 | ice_hash_type_list[i].hash_type; | |
384 | type_match_item->hash_flds = | |
385 | ice_hash_type_list[i].hash_flds; | |
386 | } | |
387 | } | |
388 | ||
389 | /* Save hash fileds to rss_meta. */ | |
390 | ((struct rss_meta *)*meta)->hash_flds = | |
391 | type_match_item->hash_flds; | |
392 | ||
393 | rte_free(type_match_item); | |
394 | break; | |
395 | ||
396 | case RTE_FLOW_ACTION_TYPE_END: | |
397 | break; | |
398 | ||
399 | default: | |
400 | rte_flow_error_set(error, EINVAL, | |
401 | RTE_FLOW_ERROR_TYPE_ACTION, action, | |
402 | "Invalid action."); | |
403 | return -rte_errno; | |
404 | } | |
405 | } | |
406 | ||
407 | return 0; | |
408 | } | |
409 | ||
410 | static int | |
411 | ice_hash_parse_pattern_action(__rte_unused struct ice_adapter *ad, | |
412 | struct ice_pattern_match_item *array, | |
413 | uint32_t array_len, | |
414 | const struct rte_flow_item pattern[], | |
415 | const struct rte_flow_action actions[], | |
416 | void **meta, | |
417 | struct rte_flow_error *error) | |
418 | { | |
419 | int ret = 0; | |
420 | struct ice_pattern_match_item *pattern_match_item; | |
421 | struct rss_meta *rss_meta_ptr; | |
422 | ||
423 | rss_meta_ptr = rte_zmalloc(NULL, sizeof(*rss_meta_ptr), 0); | |
424 | if (!rss_meta_ptr) { | |
425 | rte_flow_error_set(error, EINVAL, | |
426 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
427 | "No memory for rss_meta_ptr"); | |
428 | return -ENOMEM; | |
429 | } | |
430 | ||
431 | /* Check rss supported pattern and find matched pattern. */ | |
432 | pattern_match_item = ice_search_pattern_match_item(pattern, | |
433 | array, array_len, error); | |
434 | if (!pattern_match_item) { | |
435 | ret = -rte_errno; | |
436 | goto error; | |
437 | } | |
438 | ||
439 | ret = ice_hash_check_inset(pattern, error); | |
440 | if (ret) | |
441 | goto error; | |
442 | ||
443 | /* Save protocol header to rss_meta. */ | |
444 | rss_meta_ptr->pkt_hdr = ((struct rss_type_match_hdr *) | |
445 | (pattern_match_item->meta))->hdr_mask; | |
446 | ||
447 | /* Check rss action. */ | |
448 | ret = ice_hash_parse_action(pattern_match_item, actions, | |
449 | (void **)&rss_meta_ptr, error); | |
450 | ||
451 | error: | |
452 | if (!ret && meta) | |
453 | *meta = rss_meta_ptr; | |
454 | else | |
455 | rte_free(rss_meta_ptr); | |
456 | rte_free(pattern_match_item); | |
457 | ||
458 | return ret; | |
459 | } | |
460 | ||
461 | static int | |
462 | ice_hash_create(struct ice_adapter *ad, | |
463 | struct rte_flow *flow, | |
464 | void *meta, | |
465 | struct rte_flow_error *error) | |
466 | { | |
467 | struct ice_pf *pf = &ad->pf; | |
468 | struct ice_hw *hw = ICE_PF_TO_HW(pf); | |
469 | struct ice_vsi *vsi = pf->main_vsi; | |
470 | int ret; | |
471 | uint32_t reg; | |
472 | struct ice_hash_flow_cfg *filter_ptr; | |
473 | ||
474 | uint32_t headermask = ((struct rss_meta *)meta)->pkt_hdr; | |
475 | uint64_t hash_field = ((struct rss_meta *)meta)->hash_flds; | |
476 | uint8_t hash_function = ((struct rss_meta *)meta)->hash_function; | |
477 | ||
478 | filter_ptr = rte_zmalloc("ice_rss_filter", | |
479 | sizeof(struct ice_hash_flow_cfg), 0); | |
480 | if (!filter_ptr) { | |
481 | rte_flow_error_set(error, EINVAL, | |
482 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
483 | "No memory for filter_ptr"); | |
484 | return -ENOMEM; | |
485 | } | |
486 | ||
487 | if (hash_function == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) { | |
488 | /* Enable registers for simple_xor hash function. */ | |
489 | reg = ICE_READ_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id)); | |
490 | reg = (reg & (~VSIQF_HASH_CTL_HASH_SCHEME_M)) | | |
491 | (2 << VSIQF_HASH_CTL_HASH_SCHEME_S); | |
492 | ICE_WRITE_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id), reg); | |
493 | ||
494 | filter_ptr->simple_xor = 1; | |
495 | ||
496 | goto out; | |
497 | } else { | |
498 | filter_ptr->rss_cfg.packet_hdr = headermask; | |
499 | filter_ptr->rss_cfg.hashed_flds = hash_field; | |
500 | filter_ptr->rss_cfg.symm = | |
501 | (hash_function == | |
502 | RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ); | |
503 | ||
504 | ret = ice_add_rss_cfg(hw, vsi->idx, | |
505 | filter_ptr->rss_cfg.hashed_flds, | |
506 | filter_ptr->rss_cfg.packet_hdr, | |
507 | filter_ptr->rss_cfg.symm); | |
508 | if (ret) { | |
509 | rte_flow_error_set(error, EINVAL, | |
510 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
511 | "rss flow create fail"); | |
512 | goto error; | |
513 | } | |
514 | } | |
515 | ||
516 | out: | |
517 | flow->rule = filter_ptr; | |
518 | rte_free(meta); | |
519 | return 0; | |
520 | ||
521 | error: | |
522 | rte_free(filter_ptr); | |
523 | rte_free(meta); | |
524 | return -rte_errno; | |
525 | } | |
526 | ||
527 | static int | |
528 | ice_hash_destroy(struct ice_adapter *ad, | |
529 | struct rte_flow *flow, | |
530 | struct rte_flow_error *error) | |
531 | { | |
532 | struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(ad); | |
533 | struct ice_hw *hw = ICE_PF_TO_HW(pf); | |
534 | struct ice_vsi *vsi = pf->main_vsi; | |
535 | int ret; | |
536 | uint32_t reg; | |
537 | struct ice_hash_flow_cfg *filter_ptr; | |
538 | ||
539 | filter_ptr = (struct ice_hash_flow_cfg *)flow->rule; | |
540 | ||
541 | if (filter_ptr->simple_xor == 1) { | |
542 | /* Return to symmetric_toeplitz state. */ | |
543 | reg = ICE_READ_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id)); | |
544 | reg = (reg & (~VSIQF_HASH_CTL_HASH_SCHEME_M)) | | |
545 | (1 << VSIQF_HASH_CTL_HASH_SCHEME_S); | |
546 | ICE_WRITE_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id), reg); | |
547 | } else { | |
548 | ret = ice_rem_rss_cfg(hw, vsi->idx, | |
549 | filter_ptr->rss_cfg.hashed_flds, | |
550 | filter_ptr->rss_cfg.packet_hdr); | |
551 | /* Fixme: Ignore the error if a rule does not exist. | |
552 | * Currently a rule for inputset change or symm turn on/off | |
553 | * will overwrite an exist rule, while application still | |
554 | * have 2 rte_flow handles. | |
555 | **/ | |
556 | if (ret && ret != ICE_ERR_DOES_NOT_EXIST) { | |
557 | rte_flow_error_set(error, EINVAL, | |
558 | RTE_FLOW_ERROR_TYPE_HANDLE, NULL, | |
559 | "rss flow destroy fail"); | |
560 | goto error; | |
561 | } | |
562 | } | |
563 | ||
564 | rte_free(filter_ptr); | |
565 | return 0; | |
566 | ||
567 | error: | |
568 | rte_free(filter_ptr); | |
569 | return -rte_errno; | |
570 | } | |
571 | ||
572 | static void | |
573 | ice_hash_uninit(struct ice_adapter *ad) | |
574 | { | |
575 | if (ad->hw.dcf_enabled) | |
576 | return; | |
577 | ||
578 | if (ad->active_pkg_type == ICE_PKG_TYPE_OS_DEFAULT) | |
579 | ice_unregister_parser(&ice_hash_parser_os, ad); | |
580 | else if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS) | |
581 | ice_unregister_parser(&ice_hash_parser_comms, ad); | |
582 | } | |
583 | ||
584 | static void | |
585 | ice_hash_free(struct rte_flow *flow) | |
586 | { | |
587 | rte_free(flow->rule); | |
588 | } |