Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2025 ZTE 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 : : #include <stdlib.h>
13 : :
14 : : #include <rte_debug.h>
15 : : #include <rte_ether.h>
16 : : #include <ethdev_driver.h>
17 : : #include <rte_log.h>
18 : : #include <rte_malloc.h>
19 : : #include <rte_tailq.h>
20 : : #include <rte_flow.h>
21 : : #include <rte_bitmap.h>
22 : :
23 : : #include "zxdh_ethdev.h"
24 : : #include "zxdh_logs.h"
25 : : #include "zxdh_flow.h"
26 : : #include "zxdh_tables.h"
27 : : #include "zxdh_ethdev_ops.h"
28 : : #include "zxdh_np.h"
29 : : #include "zxdh_msg.h"
30 : :
31 : : #define ZXDH_IPV6_FRAG_HEADER 44
32 : : #define ZXDH_TENANT_ARRAY_NUM 3
33 : : #define ZXDH_VLAN_TCI_MASK 0xFFFF
34 : : #define ZXDH_VLAN_PRI_MASK 0xE000
35 : : #define ZXDH_VLAN_CFI_MASK 0x1000
36 : : #define ZXDH_VLAN_VID_MASK 0x0FFF
37 : : #define MAX_STRING_LEN 8192
38 : : #define FLOW_INGRESS 0
39 : : #define FLOW_EGRESS 1
40 : : #define MAX_ENCAP1_NUM (256)
41 : : #define INVALID_HANDLEIDX 0xffff
42 : : #define ACTION_VXLAN_ENCAP_ITEMS_NUM (6)
43 : : static struct dh_engine_list flow_engine_list = TAILQ_HEAD_INITIALIZER(flow_engine_list);
44 : : static struct count_res flow_count_ref[MAX_FLOW_COUNT_NUM];
45 : : static rte_spinlock_t fd_hw_res_lock = RTE_SPINLOCK_INITIALIZER;
46 : : static uint8_t fd_hwres_bitmap[ZXDH_MAX_FLOW_NUM] = {0};
47 : :
48 : : #define MKDUMPSTR(buf, buf_size, cur_len, ...) \
49 : : do { \
50 : : if ((cur_len) >= (buf_size)) \
51 : : break; \
52 : : (cur_len) += snprintf((buf) + (cur_len), (buf_size) - (cur_len), __VA_ARGS__); \
53 : : } while (0)
54 : :
55 : : static inline void
56 : 0 : print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr,
57 : : char print_buf[], uint32_t buf_size, uint32_t *cur_len)
58 : : {
59 : : char buf[RTE_ETHER_ADDR_FMT_SIZE];
60 : :
61 : 0 : rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
62 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, "%s%s", what, buf);
63 : 0 : }
64 : :
65 : : static inline void
66 : : zxdh_fd_flow_free_dtbentry(ZXDH_DTB_USER_ENTRY_T *dtb_entry)
67 : : {
68 : 0 : rte_free(dtb_entry->p_entry_data);
69 : 0 : dtb_entry->p_entry_data = NULL;
70 : 0 : dtb_entry->sdt_no = 0;
71 : : }
72 : :
73 : : static void
74 : : data_bitwise(void *data, int bytecnt)
75 : : {
76 : : int i;
77 : : uint32_t *temp = (uint32_t *)data;
78 : : int remain = bytecnt % 4;
79 [ # # ]: 0 : for (i = 0; i < (bytecnt >> 2); i++) {
80 : 0 : *(temp) = ~*(temp);
81 : 0 : temp++;
82 : : }
83 : :
84 : : if (remain) {
85 : : for (i = 0; i < remain; i++) {
86 : : uint8_t *tmp = (uint8_t *)temp;
87 : : *(uint8_t *)tmp = ~*(uint8_t *)tmp;
88 : : tmp++;
89 : : }
90 : : }
91 : : }
92 : :
93 : : static void
94 [ # # ]: 0 : zxdh_adjust_flow_op_rsp_memory_layout(void *old_data,
95 : : size_t old_size, void *new_data)
96 : : {
97 : : rte_memcpy(new_data, old_data, sizeof(struct zxdh_flow));
98 [ # # ]: 0 : memset((char *)new_data + sizeof(struct zxdh_flow), 0, 4);
99 [ # # ]: 0 : rte_memcpy((char *)new_data + sizeof(struct zxdh_flow) + 4,
100 : : (char *)old_data + sizeof(struct zxdh_flow),
101 : : old_size - sizeof(struct zxdh_flow));
102 : 0 : }
103 : :
104 : 0 : void zxdh_flow_global_init(void)
105 : : {
106 : : int i;
107 [ # # ]: 0 : for (i = 0; i < MAX_FLOW_COUNT_NUM; i++) {
108 : : rte_spinlock_init(&flow_count_ref[i].count_lock);
109 : 0 : flow_count_ref[i].count_ref = 0;
110 : : }
111 : 0 : }
112 : :
113 : : static void
114 : 0 : __entry_dump(char *print_buf, uint32_t buf_size,
115 : : uint32_t *cur_len, struct fd_flow_key *key)
116 : : {
117 : 0 : print_ether_addr("\nL2\t dst=", &key->mac_dst, print_buf, buf_size, cur_len);
118 : 0 : print_ether_addr(" - src=", &key->mac_src, print_buf, buf_size, cur_len);
119 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, " -eth type=0x%04x", key->ether_type);
120 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len,
121 : : " -vlan_pri=0x%02x -vlan_vlanid=0x%04x -vlan_tci=0x%04x ",
122 : : key->cvlan_pri, key->cvlan_vlanid, key->vlan_tci);
123 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len,
124 : : " -vni=0x%02x 0x%02x 0x%02x\n", key->vni[0], key->vni[1], key->vni[2]);
125 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len,
126 : : "L3\t dstip=0x%08x 0x%08x 0x%08x 0x%08x("IPv6_BYTES_FMT")\n",
127 : : *(uint32_t *)key->dst_ip, *((uint32_t *)key->dst_ip + 1),
128 : : *((uint32_t *)key->dst_ip + 2),
129 : : *((uint32_t *)key->dst_ip + 3),
130 : : IPv6_BYTES(key->dst_ip));
131 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len,
132 : : "\t srcip=0x%08x 0x%08x 0x%08x 0x%08x("IPv6_BYTES_FMT")\n",
133 : : *((uint32_t *)key->src_ip), *((uint32_t *)key->src_ip + 1),
134 : : *((uint32_t *)key->src_ip + 2),
135 : : *((uint32_t *)key->src_ip + 3),
136 : : IPv6_BYTES(key->src_ip));
137 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len,
138 : : " \t tos=0x%02x -nw-proto=0x%02x -frag-flag %u\n",
139 : : key->tos, key->nw_proto, key->frag_flag);
140 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len,
141 : : "L4\t dstport=0x%04x -srcport=0x%04x", key->tp_dst, key->tp_src);
142 : 0 : }
143 : :
144 : : static void
145 : 0 : __result_dump(char *print_buf, uint32_t buf_size,
146 : : uint32_t *cur_len, struct fd_flow_result *res)
147 : : {
148 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, " -hit_flag = 0x%04x", res->hit_flag);
149 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, " -action_idx = 0x%02x", res->action_idx);
150 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, " -qid = 0x%04x", res->qid);
151 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, " -mark_id = 0x%08x", res->mark_fd_id);
152 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, *cur_len, " -count_id = 0x%02x", res->countid);
153 : 0 : }
154 : :
155 : 0 : static void offlow_key_dump(struct fd_flow_key *key, struct fd_flow_key *key_mask, FILE *file)
156 : : {
157 : : char print_buf[MAX_STRING_LEN];
158 : : uint32_t buf_size = MAX_STRING_LEN;
159 : : uint32_t cur_len = 0;
160 : :
161 : 0 : MKDUMPSTR(print_buf, buf_size, cur_len, "offload key:\n\t");
162 : 0 : __entry_dump(print_buf, buf_size, &cur_len, key);
163 : :
164 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, cur_len, "\noffload key_mask:\n\t");
165 : 0 : __entry_dump(print_buf, buf_size, &cur_len, key_mask);
166 : :
167 : 0 : PMD_DRV_LOG(INFO, "%s", print_buf);
168 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, cur_len, "\n");
169 [ # # ]: 0 : if (file)
170 : 0 : fputs(print_buf, file);
171 : 0 : }
172 : :
173 : 0 : static void offlow_result_dump(struct fd_flow_result *res, FILE *file)
174 : : {
175 : : char print_buf[MAX_STRING_LEN];
176 : : uint32_t buf_size = MAX_STRING_LEN;
177 : : uint32_t cur_len = 0;
178 : :
179 : 0 : MKDUMPSTR(print_buf, buf_size, cur_len, "offload result:\n");
180 : 0 : __result_dump(print_buf, buf_size, &cur_len, res);
181 : 0 : PMD_DRV_LOG(INFO, "%s", print_buf);
182 : 0 : PMD_DRV_LOG(INFO, "memdump : ===result ===");
183 [ # # ]: 0 : MKDUMPSTR(print_buf, buf_size, cur_len, "\n");
184 [ # # ]: 0 : if (file)
185 : 0 : fputs(print_buf, file);
186 : 0 : }
187 : :
188 : : static int
189 : 0 : set_flow_enable(struct rte_eth_dev *dev, uint8_t dir,
190 : : bool enable, struct rte_flow_error *error)
191 : : {
192 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
193 : 0 : struct zxdh_port_attr_table port_attr = {0};
194 : : int ret = 0;
195 : :
196 [ # # ]: 0 : if (priv->is_pf) {
197 : 0 : ret = zxdh_get_port_attr(priv, priv->vport.vport, &port_attr);
198 [ # # ]: 0 : if (ret)
199 : 0 : return -rte_flow_error_set(error, EINVAL,
200 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
201 : : "get port attr failed.");
202 : 0 : port_attr.fd_enable = enable;
203 : :
204 : 0 : ret = zxdh_set_port_attr(priv, priv->vport.vport, &port_attr);
205 [ # # ]: 0 : if (ret)
206 : 0 : return -rte_flow_error_set(error, EINVAL,
207 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
208 : : "set port attr fd_enable failed.");
209 : : } else {
210 : 0 : struct zxdh_msg_info msg_info = {0};
211 : : struct zxdh_port_attr_set_msg *attr_msg = &msg_info.data.port_attr_msg;
212 : :
213 : 0 : attr_msg->mode = ZXDH_PORT_FD_EN_OFF_FLAG;
214 : 0 : attr_msg->value = enable;
215 : 0 : zxdh_msg_head_build(priv, ZXDH_PORT_ATTRS_SET, &msg_info);
216 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(msg_info), NULL, 0);
217 [ # # ]: 0 : if (ret) {
218 : 0 : PMD_DRV_LOG(ERR, "port %d flow enable failed", priv->port_id);
219 : 0 : return -rte_flow_error_set(error, EINVAL,
220 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
221 : : "flow enable failed.");
222 : : }
223 : : }
224 [ # # ]: 0 : if (dir == FLOW_INGRESS)
225 : 0 : priv->i_flow_en = !!enable;
226 : : else
227 : 0 : priv->e_flow_en = !!enable;
228 : :
229 : : return ret;
230 : : }
231 : :
232 : : static int
233 : 0 : set_vxlan_enable(struct rte_eth_dev *dev, bool enable, struct rte_flow_error *error)
234 : : {
235 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
236 : 0 : struct zxdh_port_attr_table port_attr = {0};
237 : : int ret = 0;
238 : :
239 [ # # ]: 0 : if (priv->vxlan_flow_en == !!enable)
240 : : return 0;
241 [ # # ]: 0 : if (priv->is_pf) {
242 : 0 : ret = zxdh_get_port_attr(priv, priv->vport.vport, &port_attr);
243 [ # # ]: 0 : if (ret)
244 : 0 : return -rte_flow_error_set(error, EINVAL,
245 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
246 : : "get port attr failed.");
247 : 0 : port_attr.fd_vxlan_offload_en = enable;
248 : :
249 : 0 : ret = zxdh_set_port_attr(priv, priv->vport.vport, &port_attr);
250 [ # # ]: 0 : if (ret)
251 : 0 : return -rte_flow_error_set(error, EINVAL,
252 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
253 : : "set port attr fd_enable failed.");
254 : : } else {
255 : 0 : struct zxdh_msg_info msg_info = {0};
256 : : struct zxdh_port_attr_set_msg *attr_msg = &msg_info.data.port_attr_msg;
257 : :
258 : 0 : attr_msg->mode = ZXDH_PORT_VXLAN_OFFLOAD_EN_OFF;
259 : 0 : attr_msg->value = enable;
260 : :
261 : 0 : zxdh_msg_head_build(priv, ZXDH_PORT_ATTRS_SET, &msg_info);
262 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(msg_info), NULL, 0);
263 [ # # ]: 0 : if (ret) {
264 : 0 : PMD_DRV_LOG(ERR, "port %d vxlan flow enable failed", priv->port_id);
265 : 0 : return -rte_flow_error_set(error, EINVAL,
266 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
267 : : "vxlan offload enable failed.");
268 : : }
269 : : }
270 : :
271 : 0 : priv->vxlan_flow_en = !!enable;
272 : 0 : return ret;
273 : : }
274 : :
275 : 0 : void zxdh_register_flow_engine(struct dh_flow_engine *engine)
276 : : {
277 : 0 : TAILQ_INSERT_TAIL(&flow_engine_list, engine, node);
278 : 0 : }
279 : :
280 : 0 : static void zxdh_flow_free(struct zxdh_flow *dh_flow)
281 : : {
282 [ # # ]: 0 : if (dh_flow)
283 [ # # ]: 0 : rte_mempool_put(zxdh_shared_data->flow_mp, dh_flow);
284 : 0 : }
285 : :
286 : : static struct dh_flow_engine *zxdh_get_flow_engine(struct rte_eth_dev *dev __rte_unused)
287 : : {
288 : : struct dh_flow_engine *engine = NULL;
289 : : void *temp;
290 : :
291 [ # # # # : 0 : RTE_TAILQ_FOREACH_SAFE(engine, &flow_engine_list, node, temp) {
# # # # #
# ]
292 [ # # # # : 0 : if (engine->type == FLOW_TYPE_FD_TCAM)
# # # # #
# ]
293 : : break;
294 : : }
295 : : return engine;
296 : : }
297 : :
298 : : static int
299 : 0 : zxdh_flow_validate(struct rte_eth_dev *dev,
300 : : const struct rte_flow_attr *attr,
301 : : const struct rte_flow_item *pattern,
302 : : const struct rte_flow_action *actions,
303 : : struct rte_flow_error *error)
304 : : {
305 : : struct dh_flow_engine *flow_engine = NULL;
306 : :
307 [ # # ]: 0 : if (!pattern) {
308 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
309 : : NULL, "NULL pattern.");
310 : 0 : return -rte_errno;
311 : : }
312 : :
313 [ # # ]: 0 : if (!actions) {
314 : 0 : rte_flow_error_set(error, EINVAL,
315 : : RTE_FLOW_ERROR_TYPE_ACTION_NUM,
316 : : NULL, "NULL action.");
317 : 0 : return -rte_errno;
318 : : }
319 : :
320 [ # # ]: 0 : if (!attr) {
321 : 0 : rte_flow_error_set(error, EINVAL,
322 : : RTE_FLOW_ERROR_TYPE_ATTR,
323 : : NULL, "NULL attribute.");
324 : 0 : return -rte_errno;
325 : : }
326 : : flow_engine = zxdh_get_flow_engine(dev);
327 [ # # # # ]: 0 : if (flow_engine == NULL || flow_engine->parse_pattern_action == NULL) {
328 : 0 : rte_flow_error_set(error, EINVAL,
329 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
330 : : NULL, "cannot find valid flow engine.");
331 : 0 : return -rte_errno;
332 : : }
333 [ # # ]: 0 : if (flow_engine->parse_pattern_action(dev, attr, pattern, actions, error, NULL) != 0)
334 : 0 : return -rte_errno;
335 : : return 0;
336 : : }
337 : :
338 : 0 : static struct zxdh_flow *flow_exist_check(struct rte_eth_dev *dev, struct zxdh_flow *dh_flow)
339 : : {
340 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
341 : : struct rte_flow *entry;
342 : : struct zxdh_flow *entry_flow;
343 : :
344 [ # # ]: 0 : TAILQ_FOREACH(entry, &hw->dh_flow_list, next) {
345 : 0 : entry_flow = (struct zxdh_flow *)entry->driver_flow;
346 [ # # ]: 0 : if ((memcmp(&entry_flow->flowentry.fd_flow.key, &dh_flow->flowentry.fd_flow.key,
347 : 0 : sizeof(struct fd_flow_key)) == 0) &&
348 : 0 : (memcmp(&entry_flow->flowentry.fd_flow.key_mask,
349 [ # # ]: 0 : &dh_flow->flowentry.fd_flow.key_mask,
350 : : sizeof(struct fd_flow_key)) == 0)) {
351 : 0 : return entry_flow;
352 : : }
353 : : }
354 : : return NULL;
355 : : }
356 : :
357 : : static struct rte_flow *
358 : 0 : zxdh_flow_create(struct rte_eth_dev *dev,
359 : : const struct rte_flow_attr *attr,
360 : : const struct rte_flow_item pattern[],
361 : : const struct rte_flow_action actions[],
362 : : struct rte_flow_error *error)
363 : : {
364 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
365 : : struct rte_flow *flow = NULL;
366 : 0 : struct zxdh_flow *dh_flow = NULL;
367 : : int ret = 0;
368 : : struct dh_flow_engine *flow_engine = NULL;
369 : :
370 : : flow_engine = zxdh_get_flow_engine(dev);
371 : :
372 [ # # ]: 0 : if (flow_engine == NULL ||
373 [ # # ]: 0 : flow_engine->parse_pattern_action == NULL ||
374 [ # # ]: 0 : flow_engine->apply == NULL) {
375 : 0 : rte_flow_error_set(error, EINVAL,
376 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
377 : : NULL, "cannot find valid flow engine.");
378 : 0 : return NULL;
379 : : }
380 : :
381 : 0 : flow = rte_zmalloc("rte_flow", sizeof(struct rte_flow), 0);
382 [ # # ]: 0 : if (!flow) {
383 : 0 : rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "flow malloc failed");
384 : 0 : return NULL;
385 : : }
386 [ # # ]: 0 : ret = rte_mempool_get(zxdh_shared_data->flow_mp, (void **)&dh_flow);
387 [ # # ]: 0 : if (ret) {
388 : 0 : rte_flow_error_set(error, ENOMEM,
389 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
390 : : "Failed to allocate memory from flowmp");
391 : 0 : goto free_flow;
392 : : }
393 : 0 : memset(dh_flow, 0, sizeof(struct zxdh_flow));
394 [ # # ]: 0 : if (flow_engine->parse_pattern_action(dev, attr, pattern, actions, error, dh_flow) != 0) {
395 : 0 : PMD_DRV_LOG(ERR, "parse_pattern_action failed zxdh_created failed");
396 : 0 : goto free_flow;
397 : : }
398 : :
399 [ # # ]: 0 : if (flow_exist_check(dev, dh_flow) != NULL) {
400 : 0 : rte_flow_error_set(error, EINVAL,
401 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
402 : : "duplicate entry: will not add");
403 : 0 : goto free_flow;
404 : : }
405 : :
406 : 0 : ret = flow_engine->apply(dev, dh_flow, error, hw->vport.vport, hw->pcie_id);
407 [ # # ]: 0 : if (ret) {
408 : 0 : PMD_DRV_LOG(ERR, "flow creation failed: failed to apply");
409 : 0 : goto free_flow;
410 : : }
411 : :
412 [ # # ]: 0 : if (hw->i_flow_en == 0) {
413 : 0 : ret = set_flow_enable(dev, FLOW_INGRESS, 1, error);
414 [ # # ]: 0 : if (ret < 0) {
415 : 0 : PMD_DRV_LOG(ERR, "set flow enable failed");
416 : 0 : goto free_flow;
417 : : }
418 : : }
419 : :
420 : 0 : flow->driver_flow = dh_flow;
421 : 0 : flow->port_id = dev->data->port_id;
422 : 0 : flow->type = ZXDH_FLOW_GROUP_TCAM;
423 : 0 : TAILQ_INSERT_TAIL(&hw->dh_flow_list, flow, next);
424 : :
425 : 0 : return flow;
426 : 0 : free_flow:
427 : 0 : zxdh_flow_free(dh_flow);
428 : 0 : rte_free(flow);
429 : 0 : return NULL;
430 : : }
431 : :
432 : : static int
433 : 0 : zxdh_flow_destroy(struct rte_eth_dev *dev,
434 : : struct rte_flow *flow,
435 : : struct rte_flow_error *error)
436 : : {
437 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
438 : : struct zxdh_flow *dh_flow = NULL;
439 : : int ret = 0;
440 : : struct dh_flow_engine *flow_engine = NULL;
441 : :
442 : : flow_engine = zxdh_get_flow_engine(dev);
443 [ # # ]: 0 : if (flow_engine == NULL ||
444 [ # # ]: 0 : flow_engine->destroy == NULL) {
445 : 0 : rte_flow_error_set(error, EINVAL,
446 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
447 : : NULL, "cannot find valid flow engine.");
448 : 0 : return -rte_errno;
449 : : }
450 [ # # ]: 0 : if (flow->driver_flow)
451 : : dh_flow = (struct zxdh_flow *)flow->driver_flow;
452 : :
453 : : if (dh_flow == NULL) {
454 : 0 : PMD_DRV_LOG(ERR, "invalid flow");
455 : 0 : rte_flow_error_set(error, EINVAL,
456 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
457 : : NULL, "invalid flow");
458 : 0 : return -1;
459 : : }
460 : 0 : ret = flow_engine->destroy(dev, dh_flow, error, priv->vport.vport, priv->pcie_id);
461 [ # # ]: 0 : if (ret) {
462 : 0 : rte_flow_error_set(error, -ret,
463 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
464 : : "Failed to destroy flow.");
465 : 0 : return -rte_errno;
466 : : }
467 [ # # ]: 0 : TAILQ_REMOVE(&priv->dh_flow_list, flow, next);
468 : 0 : zxdh_flow_free(dh_flow);
469 : 0 : rte_free(flow);
470 : :
471 [ # # ]: 0 : if (TAILQ_EMPTY(&priv->dh_flow_list)) {
472 : 0 : ret = set_flow_enable(dev, FLOW_INGRESS, 0, error);
473 [ # # ]: 0 : if (ret) {
474 : 0 : PMD_DRV_LOG(ERR, "clear flow enable failed");
475 : 0 : return -rte_errno;
476 : : }
477 : : }
478 : : return ret;
479 : : }
480 : :
481 : :
482 : : static int
483 : 0 : zxdh_flow_query(struct rte_eth_dev *dev,
484 : : struct rte_flow *flow,
485 : : const struct rte_flow_action *actions,
486 : : void *data, struct rte_flow_error *error)
487 : : {
488 : : struct zxdh_flow *dh_flow = NULL;
489 : : struct dh_flow_engine *flow_engine = NULL;
490 : : int ret = 0;
491 : :
492 : : flow_engine = zxdh_get_flow_engine(dev);
493 : :
494 [ # # ]: 0 : if (flow_engine == NULL ||
495 [ # # ]: 0 : flow_engine->query_count == NULL) {
496 : 0 : rte_flow_error_set(error, EINVAL,
497 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
498 : : NULL, "cannot find valid flow engine.");
499 : 0 : return -rte_errno;
500 : : }
501 : :
502 [ # # ]: 0 : if (flow->driver_flow) {
503 : : dh_flow = (struct zxdh_flow *)flow->driver_flow;
504 : : if (dh_flow == NULL) {
505 : : PMD_DRV_LOG(ERR, "flow does not exist");
506 : : return -1;
507 : : }
508 : : }
509 : :
510 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
511 [ # # # ]: 0 : switch (actions->type) {
512 : : case RTE_FLOW_ACTION_TYPE_VOID:
513 : : break;
514 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
515 : 0 : ret = flow_engine->query_count(dev, dh_flow,
516 : : (struct rte_flow_query_count *)data, error);
517 : 0 : break;
518 : 0 : default:
519 : 0 : ret = rte_flow_error_set(error, ENOTSUP,
520 : : RTE_FLOW_ERROR_TYPE_ACTION,
521 : : actions,
522 : : "action does not support QUERY");
523 : 0 : goto out;
524 : : }
525 : : }
526 : 0 : out:
527 [ # # ]: 0 : if (ret)
528 : 0 : PMD_DRV_LOG(ERR, "flow query failed");
529 : : return ret;
530 : : }
531 : :
532 : 0 : static int zxdh_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
533 : : {
534 : : struct rte_flow *flow;
535 : : struct zxdh_flow *dh_flow = NULL;
536 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
537 : 0 : struct zxdh_dtb_shared_data *dtb_data = &hw->dev_sd->dtb_sd;
538 : : struct dh_flow_engine *flow_engine = NULL;
539 : 0 : struct zxdh_msg_info msg_info = {0};
540 : 0 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0};
541 : : int ret = 0;
542 : :
543 : : flow_engine = zxdh_get_flow_engine(dev);
544 [ # # ]: 0 : if (flow_engine == NULL) {
545 : 0 : PMD_DRV_LOG(ERR, "get flow engine failed");
546 : 0 : return -1;
547 : : }
548 : 0 : ret = set_flow_enable(dev, FLOW_INGRESS, 0, error);
549 [ # # ]: 0 : if (ret) {
550 : 0 : PMD_DRV_LOG(ERR, "clear flow enable failed");
551 : 0 : return ret;
552 : : }
553 : :
554 : 0 : ret = set_vxlan_enable(dev, 0, error);
555 [ # # ]: 0 : if (ret)
556 : 0 : PMD_DRV_LOG(ERR, "clear vxlan enable failed");
557 : 0 : hw->vxlan_fd_num = 0;
558 : :
559 [ # # ]: 0 : if (hw->is_pf) {
560 : 0 : ret = zxdh_np_dtb_acl_offline_delete(hw->dev_id, dtb_data->queueid,
561 : 0 : ZXDH_SDT_FD_TABLE, hw->vport.vport,
562 : : ZXDH_FLOW_STATS_INGRESS_BASE, 1);
563 [ # # ]: 0 : if (ret)
564 : 0 : PMD_DRV_LOG(ERR, "%s flush failed. code:%d", dev->data->name, ret);
565 : : } else {
566 : 0 : zxdh_msg_head_build(hw, ZXDH_FLOW_HW_FLUSH, &msg_info);
567 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(struct zxdh_msg_info),
568 : : (void *)zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(msg_reply_info));
569 [ # # ]: 0 : if (ret) {
570 : 0 : PMD_DRV_LOG(ERR, "port %d flow op %d flush failed ret %d",
571 : : hw->port_id, ZXDH_FLOW_HW_FLUSH, ret);
572 : 0 : return -1;
573 : : }
574 : : }
575 : :
576 : : /* Remove all flows */
577 [ # # ]: 0 : while ((flow = TAILQ_FIRST(&hw->dh_flow_list))) {
578 [ # # ]: 0 : TAILQ_REMOVE(&hw->dh_flow_list, flow, next);
579 [ # # ]: 0 : if (flow->driver_flow)
580 : : dh_flow = (struct zxdh_flow *)flow->driver_flow;
581 [ # # ]: 0 : if (dh_flow == NULL) {
582 : 0 : PMD_DRV_LOG(ERR, "Invalid flow Failed to destroy flow.");
583 : 0 : ret = rte_flow_error_set(error, ENOTSUP,
584 : : RTE_FLOW_ERROR_TYPE_HANDLE,
585 : : NULL,
586 : : "Invalid flow, flush failed");
587 : 0 : return ret;
588 : : }
589 : :
590 : 0 : zxdh_flow_free(dh_flow);
591 : 0 : rte_free(flow);
592 : : }
593 : : return ret;
594 : : }
595 : :
596 : : static void
597 : 0 : handle_res_dump(struct rte_eth_dev *dev)
598 : : {
599 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
600 : 0 : uint16_t hwres_base = priv->vport.pfid << 10;
601 : : uint16_t hwres_cnt = ZXDH_MAX_FLOW_NUM >> 1;
602 : : uint16_t i;
603 : :
604 : 0 : PMD_DRV_LOG(DEBUG, "hwres_base %d", hwres_base);
605 : : rte_spinlock_lock(&fd_hw_res_lock);
606 [ # # ]: 0 : for (i = 0; i < hwres_cnt; i++) {
607 [ # # ]: 0 : if (fd_hwres_bitmap[hwres_base + i] == 1)
608 : 0 : PMD_DRV_LOG(DEBUG, "used idx %d", i + hwres_base);
609 : : }
610 : : rte_spinlock_unlock(&fd_hw_res_lock);
611 : 0 : }
612 : :
613 : : static int
614 : 0 : zxdh_flow_dev_dump(struct rte_eth_dev *dev,
615 : : struct rte_flow *flow,
616 : : FILE *file,
617 : : struct rte_flow_error *error __rte_unused)
618 : : {
619 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
620 : : struct rte_flow *entry;
621 : : struct zxdh_flow *entry_flow;
622 : : uint32_t dtb_qid = 0;
623 : 0 : uint32_t entry_num = 0;
624 : : uint16_t ret = 0;
625 : : ZXDH_DTB_ACL_ENTRY_INFO_T *fd_entry = NULL;
626 : : uint8_t *key = NULL;
627 : : uint8_t *key_mask = NULL;
628 : : uint8_t *result = NULL;
629 : :
630 [ # # ]: 0 : if (flow) {
631 : 0 : entry_flow = flow_exist_check(dev, (struct zxdh_flow *)flow->driver_flow);
632 [ # # ]: 0 : if (entry_flow) {
633 : 0 : PMD_DRV_LOG(DEBUG, "handle idx %d:", entry_flow->flowentry.hw_idx);
634 : 0 : offlow_key_dump(&entry_flow->flowentry.fd_flow.key,
635 : : &entry_flow->flowentry.fd_flow.key_mask, file);
636 : 0 : offlow_result_dump(&entry_flow->flowentry.fd_flow.result, file);
637 : : }
638 : : } else {
639 [ # # ]: 0 : if (hw->is_pf) {
640 : 0 : dtb_qid = hw->dev_sd->dtb_sd.queueid;
641 : 0 : fd_entry = calloc(1, sizeof(ZXDH_DTB_ACL_ENTRY_INFO_T) * ZXDH_MAX_FLOW_NUM);
642 : 0 : key = calloc(1, sizeof(struct fd_flow_key) * ZXDH_MAX_FLOW_NUM);
643 : 0 : key_mask = calloc(1, sizeof(struct fd_flow_key) * ZXDH_MAX_FLOW_NUM);
644 : 0 : result = calloc(1, sizeof(struct fd_flow_result) * ZXDH_MAX_FLOW_NUM);
645 [ # # # # ]: 0 : if (!fd_entry || !key || !key_mask || !result) {
646 : 0 : PMD_DRV_LOG(ERR, "fd_entry malloc failed!");
647 : 0 : goto end;
648 : : }
649 : :
650 [ # # ]: 0 : for (int i = 0; i < ZXDH_MAX_FLOW_NUM; i++) {
651 : 0 : fd_entry[i].key_data = key + i * sizeof(struct fd_flow_key);
652 : 0 : fd_entry[i].key_mask = key_mask + i * sizeof(struct fd_flow_key);
653 : 0 : fd_entry[i].p_as_rslt = result + i * sizeof(struct fd_flow_result);
654 : : }
655 : 0 : ret = zxdh_np_dtb_acl_table_dump_by_vport(hw->dev_id, dtb_qid,
656 : 0 : ZXDH_SDT_FD_TABLE, hw->vport.vport, &entry_num,
657 : : (uint8_t *)fd_entry);
658 [ # # ]: 0 : if (ret) {
659 : 0 : PMD_DRV_LOG(ERR, "dpp_dtb_acl_table_dump_by_vport failed!");
660 : 0 : goto end;
661 : : }
662 [ # # ]: 0 : for (uint32_t i = 0; i < entry_num; i++) {
663 : 0 : offlow_key_dump((struct fd_flow_key *)fd_entry[i].key_data,
664 : 0 : (struct fd_flow_key *)fd_entry[i].key_mask, file);
665 : 0 : offlow_result_dump((struct fd_flow_result *)fd_entry[i].p_as_rslt,
666 : : file);
667 : : }
668 : 0 : free(result);
669 : 0 : free(key_mask);
670 : 0 : free(key);
671 : 0 : free(fd_entry);
672 : : } else {
673 : : entry = calloc(1, sizeof(struct rte_flow));
674 : 0 : entry_flow = calloc(1, sizeof(struct zxdh_flow));
675 [ # # ]: 0 : TAILQ_FOREACH(entry, &hw->dh_flow_list, next) {
676 : 0 : entry_flow = (struct zxdh_flow *)entry->driver_flow;
677 : 0 : offlow_key_dump(&entry_flow->flowentry.fd_flow.key,
678 : : &entry_flow->flowentry.fd_flow.key_mask, file);
679 : 0 : offlow_result_dump(&entry_flow->flowentry.fd_flow.result, file);
680 : : }
681 : 0 : free(entry_flow);
682 : : free(entry);
683 : : }
684 : : }
685 : 0 : handle_res_dump(dev);
686 : :
687 : 0 : return 0;
688 : 0 : end:
689 : 0 : free(result);
690 : 0 : free(key_mask);
691 : 0 : free(key);
692 : 0 : free(fd_entry);
693 : 0 : return -1;
694 : : }
695 : :
696 : : static int32_t
697 : 0 : get_available_handle(struct zxdh_hw *hw, uint16_t vport)
698 : : {
699 : : int ret = 0;
700 : 0 : uint32_t handle_idx = 0;
701 : :
702 : 0 : ret = zxdh_np_dtb_acl_index_request(hw->dev_id, ZXDH_SDT_FD_TABLE, vport, &handle_idx);
703 [ # # ]: 0 : if (ret) {
704 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for hw!");
705 : 0 : return INVALID_HANDLEIDX;
706 : : }
707 : 0 : return handle_idx;
708 : : }
709 : :
710 : 0 : static int free_handle(struct zxdh_hw *hw, uint16_t handle_idx, uint16_t vport)
711 : : {
712 : 0 : int ret = zxdh_np_dtb_acl_index_release(hw->dev_id, ZXDH_SDT_FD_TABLE, vport, handle_idx);
713 : :
714 [ # # ]: 0 : if (ret) {
715 : 0 : PMD_DRV_LOG(ERR, "Failed to free handle_idx %d for hw!", handle_idx);
716 : 0 : return -1;
717 : : }
718 : : return 0;
719 : : }
720 : :
721 : : static uint16_t
722 : 0 : zxdh_encap0_to_dtbentry(struct zxdh_hw *hw __rte_unused,
723 : : struct zxdh_flow *dh_flow,
724 : : ZXDH_DTB_USER_ENTRY_T *dtb_entry)
725 : : {
726 : : ZXDH_DTB_ERAM_ENTRY_INFO_T *dtb_eram_entry;
727 : 0 : dtb_eram_entry = rte_zmalloc(NULL, sizeof(ZXDH_DTB_ERAM_ENTRY_INFO_T), 0);
728 : :
729 [ # # ]: 0 : if (dtb_eram_entry == NULL)
730 : : return INVALID_HANDLEIDX;
731 : :
732 : 0 : dtb_eram_entry->index = dh_flow->flowentry.fd_flow.result.encap0_index * 2;
733 : 0 : dtb_eram_entry->p_data = (uint32_t *)&dh_flow->encap0;
734 : :
735 : 0 : dtb_entry->sdt_no = ZXDH_SDT_TUNNEL_ENCAP0_TABLE;
736 : 0 : dtb_entry->p_entry_data = dtb_eram_entry;
737 : 0 : return 0;
738 : : }
739 : :
740 : : static uint16_t
741 : 0 : zxdh_encap0_ip_to_dtbentry(struct zxdh_hw *hw __rte_unused,
742 : : struct zxdh_flow *dh_flow,
743 : : ZXDH_DTB_USER_ENTRY_T *dtb_entry)
744 : : {
745 : : ZXDH_DTB_ERAM_ENTRY_INFO_T *dtb_eram_entry;
746 : 0 : dtb_eram_entry = rte_zmalloc(NULL, sizeof(ZXDH_DTB_ERAM_ENTRY_INFO_T), 0);
747 : :
748 [ # # ]: 0 : if (dtb_eram_entry == NULL)
749 : : return INVALID_HANDLEIDX;
750 : :
751 : 0 : dtb_eram_entry->index = dh_flow->flowentry.fd_flow.result.encap0_index * 2 + 1;
752 : 0 : dtb_eram_entry->p_data = (uint32_t *)&dh_flow->encap0.dip;
753 : 0 : dtb_entry->sdt_no = ZXDH_SDT_TUNNEL_ENCAP0_TABLE;
754 : 0 : dtb_entry->p_entry_data = dtb_eram_entry;
755 : 0 : return 0;
756 : : }
757 : :
758 : 0 : static uint16_t zxdh_encap1_to_dtbentry(struct zxdh_hw *hw __rte_unused,
759 : : struct zxdh_flow *dh_flow,
760 : : ZXDH_DTB_USER_ENTRY_T *dtb_entry)
761 : : {
762 : : ZXDH_DTB_ERAM_ENTRY_INFO_T *dtb_eram_entry;
763 : 0 : dtb_eram_entry = rte_zmalloc(NULL, sizeof(ZXDH_DTB_ERAM_ENTRY_INFO_T), 0);
764 : :
765 [ # # ]: 0 : if (dtb_eram_entry == NULL)
766 : : return INVALID_HANDLEIDX;
767 : :
768 [ # # ]: 0 : if (dh_flow->encap0.ethtype == 0)
769 : 0 : dtb_eram_entry->index = dh_flow->flowentry.fd_flow.result.encap1_index * 4;
770 : : else
771 : 0 : dtb_eram_entry->index = dh_flow->flowentry.fd_flow.result.encap1_index * 4 + 1;
772 : :
773 : 0 : dtb_eram_entry->p_data = (uint32_t *)&dh_flow->encap1;
774 : :
775 : 0 : dtb_entry->sdt_no = ZXDH_SDT_TUNNEL_ENCAP1_TABLE;
776 : 0 : dtb_entry->p_entry_data = dtb_eram_entry;
777 : 0 : return 0;
778 : : }
779 : :
780 : : static uint16_t
781 : 0 : zxdh_encap1_ip_to_dtbentry(struct zxdh_hw *hw __rte_unused,
782 : : struct zxdh_flow *dh_flow,
783 : : ZXDH_DTB_USER_ENTRY_T *dtb_entry)
784 : : {
785 : : ZXDH_DTB_ERAM_ENTRY_INFO_T *dtb_eram_entry;
786 : 0 : dtb_eram_entry = rte_zmalloc(NULL, sizeof(ZXDH_DTB_ERAM_ENTRY_INFO_T), 0);
787 : :
788 [ # # ]: 0 : if (dtb_eram_entry == NULL)
789 : : return INVALID_HANDLEIDX;
790 [ # # ]: 0 : if (dh_flow->encap0.ethtype == 0)
791 : 0 : dtb_eram_entry->index = dh_flow->flowentry.fd_flow.result.encap1_index * 4 + 2;
792 : : else
793 : 0 : dtb_eram_entry->index = dh_flow->flowentry.fd_flow.result.encap1_index * 4 + 3;
794 : 0 : dtb_eram_entry->p_data = (uint32_t *)&dh_flow->encap1.sip;
795 : 0 : dtb_entry->sdt_no = ZXDH_SDT_TUNNEL_ENCAP1_TABLE;
796 : 0 : dtb_entry->p_entry_data = dtb_eram_entry;
797 : 0 : return 0;
798 : : }
799 : :
800 : 0 : static int zxdh_hw_encap_insert(struct rte_eth_dev *dev,
801 : : struct zxdh_flow *dh_flow,
802 : : struct rte_flow_error *error)
803 : : {
804 : : uint32_t ret;
805 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
806 : 0 : uint32_t dtb_qid = hw->dev_sd->dtb_sd.queueid;
807 : 0 : ZXDH_DTB_USER_ENTRY_T dtb_entry = {0};
808 : :
809 : 0 : zxdh_encap0_to_dtbentry(hw, dh_flow, &dtb_entry);
810 : 0 : ret = zxdh_np_dtb_table_entry_write(hw->dev_id, dtb_qid, 1, &dtb_entry);
811 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
812 [ # # ]: 0 : if (ret) {
813 : 0 : rte_flow_error_set(error, EINVAL,
814 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
815 : : "write to hw failed");
816 : 0 : return -1;
817 : : }
818 : :
819 : 0 : zxdh_encap0_ip_to_dtbentry(hw, dh_flow, &dtb_entry);
820 : 0 : ret = zxdh_np_dtb_table_entry_write(hw->dev_id, dtb_qid, 1, &dtb_entry);
821 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
822 [ # # ]: 0 : if (ret) {
823 : 0 : rte_flow_error_set(error, EINVAL,
824 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
825 : : "write to hw failed");
826 : 0 : return -1;
827 : : }
828 : :
829 : 0 : zxdh_encap1_to_dtbentry(hw, dh_flow, &dtb_entry);
830 : 0 : ret = zxdh_np_dtb_table_entry_write(hw->dev_id, dtb_qid, 1, &dtb_entry);
831 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
832 [ # # ]: 0 : if (ret) {
833 : 0 : rte_flow_error_set(error, EINVAL,
834 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
835 : : "write to hw failed");
836 : 0 : return -1;
837 : : }
838 : :
839 : 0 : zxdh_encap1_ip_to_dtbentry(hw, dh_flow, &dtb_entry);
840 : 0 : ret = zxdh_np_dtb_table_entry_write(hw->dev_id, dtb_qid, 1, &dtb_entry);
841 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
842 [ # # ]: 0 : if (ret) {
843 : 0 : rte_flow_error_set(error, EINVAL,
844 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
845 : : "write to hw failed");
846 : 0 : return -1;
847 : : }
848 : : return 0;
849 : : }
850 : :
851 : : static uint16_t
852 : 0 : zxdh_fd_flow_to_dtbentry(struct zxdh_hw *hw __rte_unused,
853 : : struct zxdh_flow_info *fdflow,
854 : : ZXDH_DTB_USER_ENTRY_T *dtb_entry)
855 : : {
856 : : ZXDH_DTB_ACL_ENTRY_INFO_T *dtb_acl_entry;
857 : : uint16_t handle_idx = 0;
858 : 0 : dtb_acl_entry = rte_zmalloc("fdflow_dtbentry", sizeof(ZXDH_DTB_ACL_ENTRY_INFO_T), 0);
859 : :
860 [ # # ]: 0 : if (dtb_acl_entry == NULL)
861 : : return INVALID_HANDLEIDX;
862 : :
863 : 0 : dtb_acl_entry->key_data = (uint8_t *)&fdflow->fd_flow.key;
864 : 0 : dtb_acl_entry->key_mask = (uint8_t *)&fdflow->fd_flow.key_mask;
865 : 0 : dtb_acl_entry->p_as_rslt = (uint8_t *)&fdflow->fd_flow.result;
866 : :
867 : 0 : handle_idx = fdflow->hw_idx;
868 : :
869 [ # # ]: 0 : if (handle_idx >= ZXDH_MAX_FLOW_NUM) {
870 : 0 : rte_free(dtb_acl_entry);
871 : 0 : return INVALID_HANDLEIDX;
872 : : }
873 : 0 : dtb_acl_entry->handle = handle_idx;
874 : 0 : dtb_entry->sdt_no = ZXDH_SDT_FD_TABLE;
875 : 0 : dtb_entry->p_entry_data = dtb_acl_entry;
876 : 0 : return handle_idx;
877 : : }
878 : :
879 : 0 : static int zxdh_hw_flow_insert(struct rte_eth_dev *dev,
880 : : struct zxdh_flow *dh_flow,
881 : : struct rte_flow_error *error,
882 : : uint16_t vport)
883 : : {
884 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
885 : 0 : uint32_t dtb_qid = hw->dev_sd->dtb_sd.queueid;
886 : 0 : ZXDH_DTB_USER_ENTRY_T dtb_entry = {0};
887 : : uint32_t ret;
888 : : uint16_t handle_idx;
889 : :
890 : 0 : struct zxdh_flow_info *flow = &dh_flow->flowentry;
891 : 0 : handle_idx = zxdh_fd_flow_to_dtbentry(hw, flow, &dtb_entry);
892 [ # # ]: 0 : if (handle_idx == INVALID_HANDLEIDX) {
893 : 0 : rte_flow_error_set(error, EINVAL,
894 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
895 : : "Failed to allocate memory for hw");
896 : 0 : return -1;
897 : : }
898 : 0 : ret = zxdh_np_dtb_table_entry_write(hw->dev_id, dtb_qid, 1, &dtb_entry);
899 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
900 [ # # ]: 0 : if (ret) {
901 : 0 : ret = free_handle(hw, handle_idx, vport);
902 [ # # ]: 0 : if (ret) {
903 : 0 : rte_flow_error_set(error, EINVAL,
904 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
905 : : "release handle_idx to hw failed");
906 : 0 : return -1;
907 : : }
908 : 0 : rte_flow_error_set(error, EINVAL,
909 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
910 : : "write to hw failed");
911 : 0 : return -1;
912 : : }
913 : 0 : dh_flow->flowentry.hw_idx = handle_idx;
914 : 0 : return 0;
915 : : }
916 : :
917 : : static int
918 : 0 : hw_count_query(struct zxdh_hw *hw, uint32_t countid, bool clear,
919 : : struct flow_stats *fstats, struct rte_flow_error *error)
920 : : {
921 : : uint32_t stats_id = 0;
922 : : int ret = 0;
923 : : stats_id = countid;
924 [ # # ]: 0 : if (stats_id >= ZXDH_MAX_FLOW_NUM) {
925 : 0 : PMD_DRV_LOG(DEBUG, "query count id %d invalid", stats_id);
926 : 0 : ret = rte_flow_error_set(error, ENODEV,
927 : : RTE_FLOW_ERROR_TYPE_HANDLE,
928 : : NULL,
929 : : "query count id invalid");
930 : 0 : return -rte_errno;
931 : : }
932 : 0 : PMD_DRV_LOG(DEBUG, "query count id %d,clear %d ", stats_id, clear);
933 [ # # ]: 0 : if (!clear)
934 : 0 : ret = zxdh_np_dtb_stats_get(hw->dev_id, hw->dev_sd->dtb_sd.queueid, 1,
935 : : stats_id + ZXDH_FLOW_STATS_INGRESS_BASE,
936 : : (uint32_t *)fstats);
937 : : else
938 : 0 : ret = zxdh_np_stat_ppu_cnt_get_ex(hw->dev_id, 1,
939 : : stats_id + ZXDH_FLOW_STATS_INGRESS_BASE,
940 : : 1, (uint32_t *)fstats);
941 [ # # ]: 0 : if (ret)
942 : 0 : rte_flow_error_set(error, EINVAL,
943 : : RTE_FLOW_ERROR_TYPE_ACTION, NULL,
944 : : "fail to get flow stats");
945 : : return ret;
946 : : }
947 : :
948 : : static int
949 : 0 : count_deref(struct zxdh_hw *hw, uint32_t countid,
950 : : struct rte_flow_error *error)
951 : : {
952 : : int ret = 0;
953 : : struct count_res *count_res = &flow_count_ref[countid];
954 : 0 : struct flow_stats fstats = {0};
955 : :
956 : 0 : rte_spinlock_lock(&count_res->count_lock);
957 : :
958 [ # # ]: 0 : if (count_res->count_ref >= 1) {
959 : 0 : count_res->count_ref--;
960 : : } else {
961 : : rte_spinlock_unlock(&count_res->count_lock);
962 : 0 : return rte_flow_error_set(error, ENOTSUP,
963 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
964 : : NULL,
965 : : "count deref underflow");
966 : : }
967 [ # # ]: 0 : if (count_res->count_ref == 0)
968 : 0 : ret = hw_count_query(hw, countid, 1, &fstats, error);
969 : :
970 : : rte_spinlock_unlock(&count_res->count_lock);
971 : 0 : return ret;
972 : : }
973 : :
974 : : static int
975 : 0 : count_ref(struct zxdh_hw *hw, uint32_t countid, struct rte_flow_error *error)
976 : : {
977 : : int ret = 0;
978 : : struct count_res *count_res = &flow_count_ref[countid];
979 : 0 : struct flow_stats fstats = {0};
980 : :
981 : 0 : rte_spinlock_lock(&count_res->count_lock);
982 [ # # ]: 0 : if (count_res->count_ref < 255) {
983 : 0 : count_res->count_ref++;
984 : : } else {
985 : : rte_spinlock_unlock(&count_res->count_lock);
986 : 0 : return rte_flow_error_set(error, ENOTSUP,
987 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
988 : : NULL,
989 : : "count ref overflow");
990 : : }
991 : :
992 [ # # ]: 0 : if (count_res->count_ref == 1)
993 : 0 : ret = hw_count_query(hw, countid, 1, &fstats, error);
994 : :
995 : : rte_spinlock_unlock(&count_res->count_lock);
996 : 0 : return ret;
997 : : }
998 : :
999 : : int
1000 : 0 : pf_fd_hw_apply(struct rte_eth_dev *dev, struct zxdh_flow *dh_flow,
1001 : : struct rte_flow_error *error, uint16_t vport, uint16_t pcieid)
1002 : : {
1003 : : int ret = 0;
1004 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1005 : : uint8_t vf_index = 0;
1006 : 0 : uint8_t action_bits = dh_flow->flowentry.fd_flow.result.action_idx;
1007 : : uint32_t countid = MAX_FLOW_COUNT_NUM;
1008 : : uint32_t handle_idx = 0;
1009 : : union zxdh_virport_num port = {0};
1010 : :
1011 : : port.vport = vport;
1012 : 0 : handle_idx = get_available_handle(hw, vport);
1013 [ # # ]: 0 : if (handle_idx >= ZXDH_MAX_FLOW_NUM) {
1014 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_HANDLE, NULL, "Failed to allocate memory for hw");
1015 : 0 : return -1;
1016 : : }
1017 : 0 : dh_flow->flowentry.hw_idx = handle_idx;
1018 [ # # ]: 0 : if ((action_bits & (1 << FD_ACTION_COUNT_BIT)) != 0) {
1019 : : countid = handle_idx;
1020 : 0 : dh_flow->flowentry.fd_flow.result.countid = countid;
1021 : : }
1022 : :
1023 [ # # ]: 0 : if ((action_bits & (1 << FD_ACTION_VXLAN_ENCAP)) != 0) {
1024 : 0 : dh_flow->flowentry.fd_flow.result.encap0_index = handle_idx;
1025 [ # # ]: 0 : if (!port.vf_flag) {
1026 : 0 : dh_flow->flowentry.fd_flow.result.encap1_index =
1027 : 0 : hw->hash_search_index * MAX_ENCAP1_NUM;
1028 : : } else {
1029 : 0 : vf_index = VF_IDX(pcieid);
1030 [ # # ]: 0 : if (vf_index < (ZXDH_MAX_VF - 1)) {
1031 : 0 : dh_flow->flowentry.fd_flow.result.encap1_index =
1032 : 0 : hw->hash_search_index * MAX_ENCAP1_NUM + vf_index + 1;
1033 : : } else {
1034 : 0 : rte_flow_error_set(error, EINVAL,
1035 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1036 : : "encap1 vf_index is too big");
1037 : 0 : return -1;
1038 : : }
1039 : : }
1040 : 0 : PMD_DRV_LOG(DEBUG, "encap_index (%d)(%d)",
1041 : : dh_flow->flowentry.fd_flow.result.encap0_index,
1042 : : dh_flow->flowentry.fd_flow.result.encap1_index);
1043 [ # # ]: 0 : if (zxdh_hw_encap_insert(dev, dh_flow, error) != 0)
1044 : : return -1;
1045 : : }
1046 : 0 : ret = zxdh_hw_flow_insert(dev, dh_flow, error, vport);
1047 [ # # ]: 0 : if (!ret && countid < MAX_FLOW_COUNT_NUM)
1048 : 0 : ret = count_ref(hw, countid, error);
1049 : :
1050 [ # # ]: 0 : if (!ret) {
1051 [ # # ]: 0 : if (!port.vf_flag) {
1052 [ # # ]: 0 : if (((action_bits & (1 << FD_ACTION_VXLAN_ENCAP)) != 0) ||
1053 : : ((action_bits & (1 << FD_ACTION_VXLAN_DECAP)) != 0)) {
1054 : 0 : hw->vxlan_fd_num++;
1055 [ # # ]: 0 : if (hw->vxlan_fd_num == 1)
1056 : 0 : set_vxlan_enable(dev, 1, error);
1057 : : }
1058 : : }
1059 : : }
1060 : :
1061 : : return ret;
1062 : : }
1063 : :
1064 : : static int
1065 : 0 : zxdh_hw_flow_del(struct rte_eth_dev *dev,
1066 : : struct zxdh_flow *dh_flow,
1067 : : struct rte_flow_error *error,
1068 : : uint16_t vport)
1069 : : {
1070 : 0 : struct zxdh_flow_info *flow = &dh_flow->flowentry;
1071 : 0 : ZXDH_DTB_USER_ENTRY_T dtb_entry = {0};
1072 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1073 : 0 : uint32_t dtb_qid = hw->dev_sd->dtb_sd.queueid;
1074 : : uint32_t ret;
1075 : : uint16_t handle_idx;
1076 : :
1077 : 0 : handle_idx = zxdh_fd_flow_to_dtbentry(hw, flow, &dtb_entry);
1078 [ # # ]: 0 : if (handle_idx >= ZXDH_MAX_FLOW_NUM) {
1079 : 0 : rte_flow_error_set(error, EINVAL,
1080 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1081 : : "Failed to allocate memory for hw");
1082 : 0 : return -1;
1083 : : }
1084 : 0 : ret = zxdh_np_dtb_table_entry_delete(hw->dev_id, dtb_qid, 1, &dtb_entry);
1085 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
1086 [ # # ]: 0 : if (ret) {
1087 : 0 : rte_flow_error_set(error, EINVAL,
1088 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1089 : : "delete to hw failed");
1090 : 0 : return -1;
1091 : : }
1092 : 0 : ret = free_handle(hw, handle_idx, vport);
1093 [ # # ]: 0 : if (ret) {
1094 : 0 : rte_flow_error_set(error, EINVAL,
1095 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1096 : : "release handle_idx to hw failed");
1097 : 0 : return -1;
1098 : : }
1099 : 0 : PMD_DRV_LOG(DEBUG, "release handle_idx to hw success! %d", handle_idx);
1100 : 0 : return ret;
1101 : : }
1102 : :
1103 : : int
1104 : 0 : pf_fd_hw_destroy(struct rte_eth_dev *dev, struct zxdh_flow *dh_flow,
1105 : : struct rte_flow_error *error, uint16_t vport,
1106 : : uint16_t pcieid __rte_unused)
1107 : : {
1108 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1109 : : union zxdh_virport_num port = {0};
1110 : : int ret = 0;
1111 : :
1112 : : port.vport = vport;
1113 : 0 : ret = zxdh_hw_flow_del(dev, dh_flow, error, vport);
1114 : 0 : PMD_DRV_LOG(DEBUG, "destroy handle id %d", dh_flow->flowentry.hw_idx);
1115 [ # # ]: 0 : if (!ret) {
1116 : 0 : uint8_t action_bits = dh_flow->flowentry.fd_flow.result.action_idx;
1117 : : uint32_t countid;
1118 : 0 : countid = dh_flow->flowentry.hw_idx;
1119 [ # # ]: 0 : if ((action_bits & (1 << FD_ACTION_COUNT_BIT)) != 0)
1120 : 0 : ret = count_deref(hw, countid, error);
1121 [ # # ]: 0 : if (!port.vf_flag) {
1122 [ # # ]: 0 : if (((action_bits & (1 << FD_ACTION_VXLAN_ENCAP)) != 0) ||
1123 : : ((action_bits & (1 << FD_ACTION_VXLAN_DECAP)) != 0)) {
1124 : 0 : hw->vxlan_fd_num--;
1125 [ # # ]: 0 : if (hw->vxlan_fd_num == 0)
1126 : 0 : set_vxlan_enable(dev, 0, error);
1127 : : }
1128 : : }
1129 : : }
1130 : 0 : return ret;
1131 : : }
1132 : :
1133 : : static int
1134 : 0 : zxdh_hw_flow_query(struct rte_eth_dev *dev, struct zxdh_flow *dh_flow,
1135 : : struct rte_flow_error *error)
1136 : : {
1137 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1138 : : int ret = 0;
1139 : 0 : struct zxdh_flow_info *flow = &dh_flow->flowentry;
1140 : : ZXDH_DTB_USER_ENTRY_T dtb_entry;
1141 : : uint16_t handle_idx;
1142 : :
1143 : 0 : handle_idx = zxdh_fd_flow_to_dtbentry(hw, flow, &dtb_entry);
1144 [ # # ]: 0 : if (handle_idx >= ZXDH_MAX_FLOW_NUM) {
1145 : 0 : rte_flow_error_set(error, EINVAL,
1146 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1147 : : "Failed to build hw entry for query");
1148 : : ret = -1;
1149 : 0 : goto free_res;
1150 : : }
1151 : 0 : ret = zxdh_np_dtb_table_entry_get(hw->dev_id, hw->dev_sd->dtb_sd.queueid, &dtb_entry, 0);
1152 [ # # ]: 0 : if (ret != 0) {
1153 : 0 : rte_flow_error_set(error, EINVAL,
1154 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1155 : : "Failed query entry from hw ");
1156 : 0 : goto free_res;
1157 : : }
1158 : :
1159 : 0 : free_res:
1160 : : zxdh_fd_flow_free_dtbentry(&dtb_entry);
1161 : 0 : return ret;
1162 : : }
1163 : :
1164 : : int
1165 : 0 : pf_fd_hw_query_count(struct rte_eth_dev *dev,
1166 : : struct zxdh_flow *flow,
1167 : : struct rte_flow_query_count *count,
1168 : : struct rte_flow_error *error)
1169 : : {
1170 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1171 : 0 : struct flow_stats fstats = {0};
1172 : : int ret = 0;
1173 : : uint32_t countid;
1174 : :
1175 : 0 : memset(&flow->flowentry.fd_flow.result, 0, sizeof(struct fd_flow_result));
1176 : 0 : ret = zxdh_hw_flow_query(dev, flow, error);
1177 [ # # ]: 0 : if (ret) {
1178 : 0 : ret = rte_flow_error_set(error, ENODEV,
1179 : : RTE_FLOW_ERROR_TYPE_HANDLE,
1180 : : NULL,
1181 : : "query failed");
1182 : 0 : return -rte_errno;
1183 : : }
1184 : 0 : countid = flow->flowentry.hw_idx;
1185 [ # # ]: 0 : if (countid >= ZXDH_MAX_FLOW_NUM) {
1186 : 0 : ret = rte_flow_error_set(error, ENODEV,
1187 : : RTE_FLOW_ERROR_TYPE_HANDLE,
1188 : : NULL,
1189 : : "query count id invalid");
1190 : 0 : return -rte_errno;
1191 : : }
1192 : 0 : ret = hw_count_query(hw, countid, 0, &fstats, error);
1193 [ # # ]: 0 : if (ret) {
1194 : 0 : rte_flow_error_set(error, EINVAL,
1195 : : RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1196 : : "fail to get flow stats");
1197 : 0 : return ret;
1198 : : }
1199 : 0 : count->bytes = (uint64_t)(rte_le_to_cpu_32(fstats.hit_bytes_hi)) << 32 |
1200 : 0 : rte_le_to_cpu_32(fstats.hit_bytes_lo);
1201 : 0 : count->hits = (uint64_t)(rte_le_to_cpu_32(fstats.hit_pkts_hi)) << 32 |
1202 : 0 : rte_le_to_cpu_32(fstats.hit_pkts_lo);
1203 : 0 : return ret;
1204 : : }
1205 : :
1206 : : static int
1207 : 0 : fd_flow_parse_attr(struct rte_eth_dev *dev __rte_unused,
1208 : : const struct rte_flow_attr *attr,
1209 : : struct rte_flow_error *error,
1210 : : struct zxdh_flow *dh_flow)
1211 : : {
1212 : : /* Not supported */
1213 [ # # ]: 0 : if (attr->priority) {
1214 : 0 : rte_flow_error_set(error, EINVAL,
1215 : : RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1216 : : attr, "Not support priority.");
1217 : 0 : return -rte_errno;
1218 : : }
1219 : :
1220 : : /* Not supported */
1221 [ # # ]: 0 : if (attr->group >= MAX_GROUP) {
1222 : 0 : rte_flow_error_set(error, EINVAL,
1223 : : RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
1224 : : attr, "Not support group.");
1225 : 0 : return -rte_errno;
1226 : : }
1227 : :
1228 [ # # ]: 0 : if (dh_flow) {
1229 : 0 : dh_flow->group = attr->group;
1230 : 0 : dh_flow->direct = (attr->ingress == 1) ? 0 : 1;
1231 : 0 : dh_flow->pri = attr->priority;
1232 : : }
1233 : :
1234 : : return 0;
1235 : : }
1236 : :
1237 : 0 : static int fd_flow_parse_pattern(struct rte_eth_dev *dev, const struct rte_flow_item *items,
1238 : : struct rte_flow_error *error, struct zxdh_flow *dh_flow)
1239 : : {
1240 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
1241 : : struct zxdh_flow_info *flow = NULL;
1242 : : const struct rte_flow_item *item;
1243 : : const struct rte_flow_item_eth *eth_spec, *eth_mask;
1244 : : const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
1245 : : const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
1246 : : const struct rte_flow_item_ipv6 *ipv6_spec = NULL, *ipv6_mask = NULL;
1247 : : const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
1248 : : const struct rte_flow_item_udp *udp_spec, *udp_mask;
1249 : : const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
1250 : : const struct rte_flow_item_vxlan *vxlan_spec, *vxlan_mask;
1251 : : struct fd_flow_key *key, *key_mask;
1252 : :
1253 [ # # ]: 0 : if (dh_flow) {
1254 : 0 : flow = &dh_flow->flowentry;
1255 : : } else {
1256 : 0 : flow = rte_zmalloc("dh_flow", sizeof(*flow), 0);
1257 [ # # ]: 0 : if (flow == NULL) {
1258 : 0 : rte_flow_error_set(error, EINVAL,
1259 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1260 : : "Failed to allocate memory ");
1261 : 0 : return -rte_errno;
1262 : : }
1263 : : }
1264 : :
1265 : : key = &flow->fd_flow.key;
1266 : 0 : key_mask = &flow->fd_flow.key_mask;
1267 [ # # ]: 0 : key->vfid = rte_cpu_to_be_16(priv->vfid);
1268 : 0 : key_mask->vfid = 0xffff;
1269 [ # # ]: 0 : for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
1270 : : item = items;
1271 [ # # ]: 0 : if (items->last) {
1272 : 0 : rte_flow_error_set(error, EINVAL,
1273 : : RTE_FLOW_ERROR_TYPE_ITEM,
1274 : : items,
1275 : : "Not support range");
1276 : 0 : return -rte_errno;
1277 : : }
1278 : :
1279 [ # # # # : 0 : switch (item->type) {
# # # # #
# ]
1280 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
1281 : 0 : eth_spec = item->spec;
1282 : 0 : eth_mask = item->mask;
1283 [ # # ]: 0 : if (eth_spec && eth_mask) {
1284 : 0 : key->mac_dst = eth_spec->dst;
1285 : 0 : key->mac_src = eth_spec->src;
1286 : 0 : key_mask->mac_dst = eth_mask->dst;
1287 : 0 : key_mask->mac_src = eth_mask->src;
1288 : :
1289 [ # # ]: 0 : if (eth_mask->type == 0xffff) {
1290 : 0 : key->ether_type = eth_spec->type;
1291 : 0 : key_mask->ether_type = eth_mask->type;
1292 : : }
1293 : : }
1294 : : break;
1295 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
1296 : 0 : vlan_spec = item->spec;
1297 : 0 : vlan_mask = item->mask;
1298 [ # # ]: 0 : if (vlan_spec && vlan_mask) {
1299 : 0 : key->vlan_tci = vlan_spec->tci;
1300 : 0 : key_mask->vlan_tci = vlan_mask->tci;
1301 : : }
1302 : : break;
1303 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
1304 : 0 : ipv4_spec = item->spec;
1305 : 0 : ipv4_mask = item->mask;
1306 : :
1307 [ # # ]: 0 : if (ipv4_spec && ipv4_mask) {
1308 : : /* Check IPv4 mask and update input set */
1309 [ # # ]: 0 : if (ipv4_mask->hdr.version_ihl ||
1310 [ # # ]: 0 : ipv4_mask->hdr.total_length ||
1311 [ # # ]: 0 : ipv4_mask->hdr.packet_id ||
1312 [ # # ]: 0 : ipv4_mask->hdr.hdr_checksum ||
1313 [ # # ]: 0 : ipv4_mask->hdr.time_to_live) {
1314 : 0 : rte_flow_error_set(error, EINVAL,
1315 : : RTE_FLOW_ERROR_TYPE_ITEM,
1316 : : item,
1317 : : "Invalid IPv4 mask.");
1318 : 0 : return -rte_errno;
1319 : : }
1320 : : /* Get the filter info */
1321 : 0 : key->nw_proto =
1322 : 0 : ipv4_spec->hdr.next_proto_id;
1323 : 0 : key->tos =
1324 : 0 : ipv4_spec->hdr.type_of_service;
1325 : 0 : key_mask->nw_proto =
1326 : 0 : ipv4_mask->hdr.next_proto_id;
1327 : 0 : key_mask->tos =
1328 : 0 : ipv4_mask->hdr.type_of_service;
1329 : 0 : key->frag_flag = (ipv4_spec->hdr.fragment_offset != 0) ? 1 : 0;
1330 : 0 : key_mask->frag_flag = (ipv4_mask->hdr.fragment_offset != 0) ? 1 : 0;
1331 : 0 : rte_memcpy((uint32_t *)key->src_ip + 3,
1332 [ # # ]: 0 : &ipv4_spec->hdr.src_addr, 4);
1333 : 0 : rte_memcpy((uint32_t *)key->dst_ip + 3,
1334 [ # # ]: 0 : &ipv4_spec->hdr.dst_addr, 4);
1335 : 0 : rte_memcpy((uint32_t *)key_mask->src_ip + 3,
1336 [ # # ]: 0 : &ipv4_mask->hdr.src_addr, 4);
1337 : 0 : rte_memcpy((uint32_t *)key_mask->dst_ip + 3,
1338 [ # # ]: 0 : &ipv4_mask->hdr.dst_addr, 4);
1339 : : }
1340 : : break;
1341 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
1342 : 0 : ipv6_spec = item->spec;
1343 : 0 : ipv6_mask = item->mask;
1344 : :
1345 [ # # ]: 0 : if (ipv6_spec && ipv6_mask) {
1346 : : /* Check IPv6 mask and update input set */
1347 [ # # ]: 0 : if (ipv6_mask->hdr.payload_len ||
1348 [ # # ]: 0 : ipv6_mask->hdr.hop_limits == UINT8_MAX) {
1349 : 0 : rte_flow_error_set(error, EINVAL,
1350 : : RTE_FLOW_ERROR_TYPE_ITEM,
1351 : : item,
1352 : : "Invalid IPv6 mask");
1353 : 0 : return -rte_errno;
1354 : : }
1355 : 0 : key->tc =
1356 : 0 : (uint8_t)((ipv6_spec->hdr.vtc_flow &
1357 : 0 : RTE_IPV6_HDR_TC_MASK) >>
1358 : : RTE_IPV6_HDR_TC_SHIFT);
1359 : 0 : key_mask->tc =
1360 : 0 : (uint8_t)((ipv6_mask->hdr.vtc_flow &
1361 : 0 : RTE_IPV6_HDR_TC_MASK) >>
1362 : : RTE_IPV6_HDR_TC_SHIFT);
1363 : :
1364 : 0 : key->nw_proto = ipv6_spec->hdr.proto;
1365 : 0 : key_mask->nw_proto = ipv6_mask->hdr.proto;
1366 : :
1367 : 0 : rte_memcpy(key->src_ip,
1368 [ # # ]: 0 : &ipv6_spec->hdr.src_addr, 16);
1369 : 0 : rte_memcpy(key->dst_ip,
1370 [ # # ]: 0 : &ipv6_spec->hdr.dst_addr, 16);
1371 : 0 : rte_memcpy(key_mask->src_ip,
1372 [ # # ]: 0 : &ipv6_mask->hdr.src_addr, 16);
1373 : 0 : rte_memcpy(key_mask->dst_ip,
1374 [ # # ]: 0 : &ipv6_mask->hdr.dst_addr, 16);
1375 : : }
1376 : : break;
1377 : 0 : case RTE_FLOW_ITEM_TYPE_TCP:
1378 : 0 : tcp_spec = item->spec;
1379 : 0 : tcp_mask = item->mask;
1380 : :
1381 [ # # ]: 0 : if (tcp_spec && tcp_mask) {
1382 : : /* Check TCP mask and update input set */
1383 [ # # ]: 0 : if (tcp_mask->hdr.sent_seq ||
1384 [ # # ]: 0 : tcp_mask->hdr.recv_ack ||
1385 [ # # ]: 0 : tcp_mask->hdr.data_off ||
1386 [ # # ]: 0 : tcp_mask->hdr.tcp_flags ||
1387 [ # # ]: 0 : tcp_mask->hdr.rx_win ||
1388 [ # # ]: 0 : tcp_mask->hdr.cksum ||
1389 [ # # ]: 0 : tcp_mask->hdr.tcp_urp ||
1390 [ # # ]: 0 : (tcp_mask->hdr.src_port &&
1391 : 0 : tcp_mask->hdr.src_port != UINT16_MAX) ||
1392 [ # # ]: 0 : (tcp_mask->hdr.dst_port &&
1393 : : tcp_mask->hdr.dst_port != UINT16_MAX)) {
1394 : 0 : rte_flow_error_set(error, EINVAL,
1395 : : RTE_FLOW_ERROR_TYPE_ITEM,
1396 : : item,
1397 : : "Invalid TCP mask");
1398 : 0 : return -rte_errno;
1399 : : }
1400 : :
1401 : 0 : key->tp_src = tcp_spec->hdr.src_port;
1402 : 0 : key_mask->tp_src = tcp_mask->hdr.src_port;
1403 : :
1404 : 0 : key->tp_dst = tcp_spec->hdr.dst_port;
1405 : 0 : key_mask->tp_dst = tcp_mask->hdr.dst_port;
1406 : : }
1407 : : break;
1408 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
1409 : 0 : udp_spec = item->spec;
1410 : 0 : udp_mask = item->mask;
1411 : :
1412 [ # # ]: 0 : if (udp_spec && udp_mask) {
1413 : : /* Check UDP mask and update input set*/
1414 [ # # ]: 0 : if (udp_mask->hdr.dgram_len ||
1415 [ # # ]: 0 : udp_mask->hdr.dgram_cksum ||
1416 [ # # ]: 0 : (udp_mask->hdr.src_port &&
1417 : 0 : udp_mask->hdr.src_port != UINT16_MAX) ||
1418 [ # # ]: 0 : (udp_mask->hdr.dst_port &&
1419 : : udp_mask->hdr.dst_port != UINT16_MAX)) {
1420 : 0 : rte_flow_error_set(error, EINVAL,
1421 : : RTE_FLOW_ERROR_TYPE_ITEM,
1422 : : item,
1423 : : "Invalid UDP mask");
1424 : 0 : return -rte_errno;
1425 : : }
1426 : :
1427 : 0 : key->tp_src = udp_spec->hdr.src_port;
1428 : 0 : key_mask->tp_src = udp_mask->hdr.src_port;
1429 : :
1430 : 0 : key->tp_dst = udp_spec->hdr.dst_port;
1431 : 0 : key_mask->tp_dst = udp_mask->hdr.dst_port;
1432 : : }
1433 : : break;
1434 : 0 : case RTE_FLOW_ITEM_TYPE_SCTP:
1435 : 0 : sctp_spec = item->spec;
1436 : 0 : sctp_mask = item->mask;
1437 : :
1438 [ # # ]: 0 : if (!(sctp_spec && sctp_mask))
1439 : : break;
1440 : :
1441 : : /* Check SCTP mask and update input set */
1442 [ # # ]: 0 : if (sctp_mask->hdr.cksum) {
1443 : 0 : rte_flow_error_set(error, EINVAL,
1444 : : RTE_FLOW_ERROR_TYPE_ITEM,
1445 : : item,
1446 : : "Invalid sctp mask");
1447 : 0 : return -rte_errno;
1448 : : }
1449 : :
1450 : : /* Mask for SCTP src/dst ports not supported */
1451 [ # # ]: 0 : if (sctp_mask->hdr.src_port &&
1452 : : sctp_mask->hdr.src_port != UINT16_MAX)
1453 : 0 : return -rte_errno;
1454 [ # # ]: 0 : if (sctp_mask->hdr.dst_port &&
1455 : : sctp_mask->hdr.dst_port != UINT16_MAX)
1456 : 0 : return -rte_errno;
1457 : :
1458 : 0 : key->tp_src = sctp_spec->hdr.src_port;
1459 : 0 : key_mask->tp_src = sctp_mask->hdr.src_port;
1460 : 0 : key->tp_dst = sctp_spec->hdr.dst_port;
1461 : 0 : key_mask->tp_dst = sctp_mask->hdr.dst_port;
1462 : 0 : break;
1463 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
1464 : : {
1465 : 0 : vxlan_spec = item->spec;
1466 : 0 : vxlan_mask = item->mask;
1467 : : static const struct rte_flow_item_vxlan flow_item_vxlan_mask = {
1468 : : .vni = {0xff, 0xff, 0xff},
1469 : : };
1470 [ # # ]: 0 : if (!(vxlan_spec && vxlan_mask))
1471 : : break;
1472 [ # # ]: 0 : if (memcmp(vxlan_mask, &flow_item_vxlan_mask,
1473 : : sizeof(struct rte_flow_item_vxlan))) {
1474 : 0 : rte_flow_error_set(error, EINVAL,
1475 : : RTE_FLOW_ERROR_TYPE_ITEM,
1476 : : item,
1477 : : "Invalid vxlan mask");
1478 : 0 : return -rte_errno;
1479 : : }
1480 [ # # ]: 0 : rte_memcpy(key->vni, vxlan_spec->vni, 3);
1481 [ # # ]: 0 : rte_memcpy(key_mask->vni, vxlan_mask->vni, 3);
1482 : : break;
1483 : : }
1484 : : case RTE_FLOW_ACTION_TYPE_VOID:
1485 : : break;
1486 : 0 : default:
1487 : 0 : return rte_flow_error_set(error, ENOTSUP,
1488 : : RTE_FLOW_ERROR_TYPE_ITEM,
1489 : : NULL, "item not supported");
1490 : : }
1491 : : }
1492 : :
1493 : : data_bitwise(key_mask, sizeof(*key_mask));
1494 : : return 0;
1495 : : }
1496 : :
1497 : : static inline int
1498 : 0 : validate_action_rss(struct rte_eth_dev *dev,
1499 : : const struct rte_flow_action *action,
1500 : : struct rte_flow_error *error)
1501 : : {
1502 : 0 : const struct rte_flow_action_rss *rss = action->conf;
1503 : :
1504 [ # # ]: 0 : if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT &&
1505 : : rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ) {
1506 : 0 : rte_flow_error_set(error, ENOTSUP,
1507 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1508 : 0 : &rss->func,
1509 : : "RSS hash function not supported");
1510 : 0 : return -rte_errno;
1511 : : }
1512 : :
1513 [ # # ]: 0 : if (rss->level > 1) {
1514 : 0 : rte_flow_error_set(error, ENOTSUP,
1515 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1516 : 0 : &rss->level,
1517 : : "tunnel RSS is not supported");
1518 : 0 : return -rte_errno;
1519 : : }
1520 : :
1521 : : /* allow RSS key_len 0 in case of NULL (default) RSS key. */
1522 [ # # # # ]: 0 : if (rss->key_len == 0 && rss->key != NULL) {
1523 : 0 : rte_flow_error_set(error, ENOTSUP,
1524 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1525 : 0 : &rss->key_len,
1526 : : "RSS hash key length 0");
1527 : 0 : return -rte_errno;
1528 : : }
1529 : :
1530 [ # # ]: 0 : if (rss->key_len > 0 && rss->key_len < ZXDH_RSS_HASH_KEY_LEN) {
1531 : 0 : rte_flow_error_set(error, ENOTSUP,
1532 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1533 : 0 : &rss->key_len,
1534 : : "RSS hash key too small, value is 40U");
1535 : 0 : return -rte_errno;
1536 : : }
1537 : :
1538 [ # # ]: 0 : if (rss->key_len > ZXDH_RSS_HASH_KEY_LEN) {
1539 : 0 : rte_flow_error_set(error, ENOTSUP,
1540 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1541 : 0 : &rss->key_len,
1542 : : "RSS hash key too large, value is 40U");
1543 : 0 : return -rte_errno;
1544 : : }
1545 : :
1546 [ # # ]: 0 : if (!rss->queue_num) {
1547 : 0 : rte_flow_error_set(error, EINVAL,
1548 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1549 : 0 : &dev->data->nb_rx_queues, "No queues configured");
1550 : 0 : return -rte_errno;
1551 : : }
1552 : :
1553 : : return 0;
1554 : : }
1555 : :
1556 : : static int
1557 : 0 : fd_flow_parse_vxlan_encap(struct rte_eth_dev *dev __rte_unused,
1558 : : const struct rte_flow_item *item,
1559 : : struct zxdh_flow *dh_flow)
1560 : : {
1561 : : const struct rte_flow_item *items;
1562 : : const struct rte_flow_item_eth *item_eth;
1563 : : const struct rte_flow_item_vlan *item_vlan;
1564 : : const struct rte_flow_item_ipv4 *item_ipv4;
1565 : : const struct rte_flow_item_ipv6 *item_ipv6;
1566 : : const struct rte_flow_item_udp *item_udp;
1567 : : const struct rte_flow_item_vxlan *item_vxlan;
1568 : : uint32_t i = 0;
1569 : : rte_be32_t addr;
1570 : :
1571 [ # # ]: 0 : for (i = 0; i < ACTION_VXLAN_ENCAP_ITEMS_NUM; i++) {
1572 : 0 : items = &item[i];
1573 [ # # # # : 0 : switch (items->type) {
# # # ]
1574 : 0 : case RTE_FLOW_ITEM_TYPE_ETH:
1575 : 0 : item_eth = items->spec;
1576 [ # # ]: 0 : rte_memcpy(&dh_flow->encap0.dst_mac1, item_eth->dst.addr_bytes, 2);
1577 [ # # ]: 0 : rte_memcpy(&dh_flow->encap1.src_mac1, item_eth->src.addr_bytes, 2);
1578 [ # # ]: 0 : rte_memcpy(&dh_flow->encap0.dst_mac2, &item_eth->dst.addr_bytes[2], 4);
1579 [ # # ]: 0 : rte_memcpy(&dh_flow->encap1.src_mac2, &item_eth->src.addr_bytes[2], 4);
1580 [ # # ]: 0 : dh_flow->encap0.dst_mac1 = rte_bswap16(dh_flow->encap0.dst_mac1);
1581 [ # # ]: 0 : dh_flow->encap1.src_mac1 = rte_bswap16(dh_flow->encap1.src_mac1);
1582 [ # # ]: 0 : dh_flow->encap0.dst_mac2 = rte_bswap32(dh_flow->encap0.dst_mac2);
1583 [ # # ]: 0 : dh_flow->encap1.src_mac2 = rte_bswap32(dh_flow->encap1.src_mac2);
1584 : 0 : break;
1585 : 0 : case RTE_FLOW_ITEM_TYPE_VLAN:
1586 : 0 : item_vlan = items->spec;
1587 : 0 : dh_flow->encap1.vlan_tci = item_vlan->hdr.vlan_tci;
1588 : 0 : break;
1589 : 0 : case RTE_FLOW_ITEM_TYPE_IPV4:
1590 : 0 : item_ipv4 = items->spec;
1591 : 0 : dh_flow->encap0.ethtype = 0;
1592 : 0 : dh_flow->encap0.tos = item_ipv4->hdr.type_of_service;
1593 : 0 : dh_flow->encap0.ttl = item_ipv4->hdr.time_to_live;
1594 [ # # ]: 0 : addr = rte_bswap32(item_ipv4->hdr.src_addr);
1595 [ # # ]: 0 : rte_memcpy((uint32_t *)dh_flow->encap1.sip.ip_addr + 3, &addr, 4);
1596 [ # # ]: 0 : addr = rte_bswap32(item_ipv4->hdr.dst_addr);
1597 [ # # ]: 0 : rte_memcpy((uint32_t *)dh_flow->encap0.dip.ip_addr + 3, &addr, 4);
1598 : : break;
1599 : 0 : case RTE_FLOW_ITEM_TYPE_IPV6:
1600 : 0 : item_ipv6 = items->spec;
1601 : 0 : dh_flow->encap0.ethtype = 1;
1602 : 0 : dh_flow->encap0.tos =
1603 : 0 : (item_ipv6->hdr.vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
1604 : : RTE_IPV6_HDR_TC_SHIFT;
1605 : 0 : dh_flow->encap0.ttl = item_ipv6->hdr.hop_limits;
1606 [ # # ]: 0 : rte_memcpy(dh_flow->encap1.sip.ip_addr, &item_ipv6->hdr.src_addr, 16);
1607 : 0 : dh_flow->encap1.sip.ip_addr[0] =
1608 [ # # ]: 0 : rte_bswap32(dh_flow->encap1.sip.ip_addr[0]);
1609 : 0 : dh_flow->encap1.sip.ip_addr[1] =
1610 [ # # ]: 0 : rte_bswap32(dh_flow->encap1.sip.ip_addr[1]);
1611 : 0 : dh_flow->encap1.sip.ip_addr[2] =
1612 [ # # ]: 0 : rte_bswap32(dh_flow->encap1.sip.ip_addr[2]);
1613 : 0 : dh_flow->encap1.sip.ip_addr[3] =
1614 [ # # ]: 0 : rte_bswap32(dh_flow->encap1.sip.ip_addr[3]);
1615 [ # # ]: 0 : rte_memcpy(dh_flow->encap0.dip.ip_addr, &item_ipv6->hdr.dst_addr, 16);
1616 : 0 : dh_flow->encap0.dip.ip_addr[0] =
1617 [ # # ]: 0 : rte_bswap32(dh_flow->encap0.dip.ip_addr[0]);
1618 : 0 : dh_flow->encap0.dip.ip_addr[1] =
1619 [ # # ]: 0 : rte_bswap32(dh_flow->encap0.dip.ip_addr[1]);
1620 : 0 : dh_flow->encap0.dip.ip_addr[2] =
1621 [ # # ]: 0 : rte_bswap32(dh_flow->encap0.dip.ip_addr[2]);
1622 : 0 : dh_flow->encap0.dip.ip_addr[3] =
1623 [ # # ]: 0 : rte_bswap32(dh_flow->encap0.dip.ip_addr[3]);
1624 : 0 : break;
1625 : 0 : case RTE_FLOW_ITEM_TYPE_UDP:
1626 : 0 : item_udp = items->spec;
1627 : 0 : dh_flow->encap0.tp_dst = item_udp->hdr.dst_port;
1628 [ # # ]: 0 : dh_flow->encap0.tp_dst = rte_bswap16(dh_flow->encap0.tp_dst);
1629 : 0 : break;
1630 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
1631 : 0 : item_vxlan = items->spec;
1632 : 0 : dh_flow->encap0.vni = item_vxlan->vni[0] * 65536 +
1633 : 0 : item_vxlan->vni[1] * 256 + item_vxlan->vni[2];
1634 : 0 : break;
1635 : : case RTE_FLOW_ITEM_TYPE_VOID:
1636 : : break;
1637 : : default:
1638 : : break;
1639 : : }
1640 : : }
1641 : 0 : dh_flow->encap0.hit_flag = 1;
1642 : 0 : dh_flow->encap1.hit_flag = 1;
1643 : :
1644 : 0 : return 0;
1645 : : }
1646 : :
1647 : : static int
1648 : 0 : fd_flow_parse_action(struct rte_eth_dev *dev, const struct rte_flow_action *actions,
1649 : : struct rte_flow_error *error, struct zxdh_flow *dh_flow)
1650 : : {
1651 : : struct zxdh_flow_info *flow = NULL;
1652 : : struct fd_flow_result *result = NULL;
1653 : : const struct rte_flow_item *enc_item = NULL;
1654 : : uint8_t action_bitmap = 0;
1655 : : uint32_t dest_num = 0;
1656 : : uint32_t mark_num = 0;
1657 : : uint32_t counter_num = 0;
1658 : : int ret;
1659 : :
1660 : 0 : rte_errno = 0;
1661 [ # # ]: 0 : if (dh_flow) {
1662 : 0 : flow = &dh_flow->flowentry;
1663 : : } else {
1664 : 0 : flow = rte_zmalloc("dh_flow", sizeof(*flow), 0);
1665 [ # # ]: 0 : if (flow == NULL) {
1666 : 0 : rte_flow_error_set(error, EINVAL,
1667 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1668 : : "Failed to allocate memory ");
1669 : 0 : return -rte_errno;
1670 : : }
1671 : : }
1672 : : result = &flow->fd_flow.result;
1673 : 0 : action_bitmap = result->action_idx;
1674 : :
1675 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1676 [ # # # # : 0 : switch (actions->type) {
# # # # ]
1677 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
1678 : : {
1679 : 0 : dest_num++;
1680 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_RSS_BIT)) {
1681 : 0 : rte_flow_error_set(error, EINVAL,
1682 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1683 : : "rss action does no support.");
1684 : 0 : goto free_flow;
1685 : : }
1686 : 0 : ret = validate_action_rss(dev, actions, error);
1687 [ # # ]: 0 : if (ret)
1688 : 0 : goto free_flow;
1689 : 0 : action_bitmap |= (1 << FD_ACTION_RSS_BIT);
1690 : 0 : break;
1691 : : }
1692 : 0 : case RTE_FLOW_ACTION_TYPE_MARK:
1693 : : {
1694 : 0 : mark_num++;
1695 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_MARK_BIT)) {
1696 : 0 : rte_flow_error_set(error, EINVAL,
1697 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1698 : : "multi mark action no support.");
1699 : 0 : goto free_flow;
1700 : : }
1701 : 0 : const struct rte_flow_action_mark *act_mark = actions->conf;
1702 : 0 : result->mark_fd_id = rte_cpu_to_le_32(act_mark->id);
1703 : 0 : action_bitmap |= (1 << FD_ACTION_MARK_BIT);
1704 : 0 : break;
1705 : : }
1706 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
1707 : : {
1708 : 0 : counter_num++;
1709 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_COUNT_BIT)) {
1710 : 0 : rte_flow_error_set(error, EINVAL,
1711 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1712 : : "multi count action no support.");
1713 : 0 : goto free_flow;
1714 : : }
1715 : 0 : const struct rte_flow_action_count *act_count = actions->conf;
1716 [ # # ]: 0 : if (act_count->id > MAX_FLOW_COUNT_NUM) {
1717 : 0 : rte_flow_error_set(error, EINVAL,
1718 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1719 : : "count action id no support.");
1720 : 0 : goto free_flow;
1721 : : };
1722 : 0 : result->countid = act_count->id;
1723 : 0 : action_bitmap |= (1 << FD_ACTION_COUNT_BIT);
1724 : 0 : break;
1725 : : }
1726 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
1727 : : {
1728 : 0 : dest_num++;
1729 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_QUEUE_BIT)) {
1730 : 0 : rte_flow_error_set(error, EINVAL,
1731 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1732 : : "multi queue action no support.");
1733 : 0 : goto free_flow;
1734 : : }
1735 : : const struct rte_flow_action_queue *act_q;
1736 : 0 : act_q = actions->conf;
1737 [ # # ]: 0 : if (act_q->index >= dev->data->nb_rx_queues) {
1738 : 0 : rte_flow_error_set(error, EINVAL,
1739 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1740 : : "Invalid queue ID");
1741 : 0 : goto free_flow;
1742 : : }
1743 : 0 : ret = zxdh_hw_qid_to_logic_qid(dev, act_q->index << 1);
1744 : : if (ret < 0) {
1745 : : rte_flow_error_set(error, EINVAL,
1746 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1747 : : "Invalid phy queue ID .");
1748 : : goto free_flow;
1749 : : }
1750 : 0 : result->qid = rte_cpu_to_le_16(ret);
1751 : 0 : action_bitmap |= (1 << FD_ACTION_QUEUE_BIT);
1752 : :
1753 : 0 : PMD_DRV_LOG(DEBUG, "QID RET 0x%x", result->qid);
1754 : 0 : break;
1755 : : }
1756 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
1757 : : {
1758 : 0 : dest_num++;
1759 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_DROP_BIT)) {
1760 : 0 : rte_flow_error_set(error, EINVAL,
1761 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1762 : : "multi drop action no support.");
1763 : 0 : goto free_flow;
1764 : : }
1765 : 0 : action_bitmap |= (1 << FD_ACTION_DROP_BIT);
1766 : 0 : break;
1767 : : }
1768 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
1769 : : {
1770 : 0 : dest_num++;
1771 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_VXLAN_DECAP)) {
1772 : 0 : rte_flow_error_set(error, EINVAL,
1773 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1774 : : "multi drop action no support.");
1775 : 0 : goto free_flow;
1776 : : }
1777 : 0 : action_bitmap |= (1 << FD_ACTION_VXLAN_DECAP);
1778 : 0 : break;
1779 : : }
1780 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
1781 : 0 : enc_item = ((const struct rte_flow_action_vxlan_encap *)
1782 : 0 : actions->conf)->definition;
1783 [ # # ]: 0 : if (dh_flow != NULL)
1784 : 0 : fd_flow_parse_vxlan_encap(dev, enc_item, dh_flow);
1785 : 0 : dest_num++;
1786 [ # # ]: 0 : if (action_bitmap & (1 << FD_ACTION_VXLAN_ENCAP)) {
1787 : 0 : rte_flow_error_set(error, EINVAL,
1788 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1789 : : "multi drop action no support.");
1790 : 0 : goto free_flow;
1791 : : }
1792 : 0 : action_bitmap |= (1 << FD_ACTION_VXLAN_ENCAP);
1793 : 0 : break;
1794 : 0 : default:
1795 : 0 : rte_flow_error_set(error, EINVAL,
1796 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1797 : : "Invalid action.");
1798 : 0 : goto free_flow;
1799 : : }
1800 : : }
1801 : :
1802 [ # # ]: 0 : if (dest_num >= 2) {
1803 : 0 : rte_flow_error_set(error, EINVAL,
1804 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1805 : : "Unsupported action combination");
1806 : 0 : return -rte_errno;
1807 : : }
1808 : :
1809 [ # # ]: 0 : if (mark_num >= 2) {
1810 : 0 : rte_flow_error_set(error, EINVAL,
1811 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1812 : : "Too many mark actions");
1813 : 0 : return -rte_errno;
1814 : : }
1815 : :
1816 [ # # ]: 0 : if (counter_num >= 2) {
1817 : 0 : rte_flow_error_set(error, EINVAL,
1818 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1819 : : "Too many count actions");
1820 : 0 : return -rte_errno;
1821 : : }
1822 : :
1823 [ # # ]: 0 : if (dest_num + mark_num + counter_num == 0) {
1824 : 0 : rte_flow_error_set(error, EINVAL,
1825 : : RTE_FLOW_ERROR_TYPE_ACTION, actions,
1826 : : "Empty action, packet forwarding as default");
1827 : 0 : return -rte_errno;
1828 : : }
1829 : :
1830 : 0 : result->action_idx = action_bitmap;
1831 : 0 : return 0;
1832 : :
1833 : 0 : free_flow:
1834 [ # # ]: 0 : if (!dh_flow)
1835 : 0 : rte_free(flow);
1836 : 0 : return -rte_errno;
1837 : : }
1838 : :
1839 : : static int
1840 : 0 : fd_parse_pattern_action(struct rte_eth_dev *dev,
1841 : : const struct rte_flow_attr *attr,
1842 : : const struct rte_flow_item pattern[],
1843 : : const struct rte_flow_action *actions,
1844 : : struct rte_flow_error *error, struct zxdh_flow *dh_flow)
1845 : : {
1846 : : int ret = 0;
1847 : 0 : ret = fd_flow_parse_attr(dev, attr, error, dh_flow);
1848 [ # # ]: 0 : if (ret < 0)
1849 : 0 : return -rte_errno;
1850 : 0 : ret = fd_flow_parse_pattern(dev, pattern, error, dh_flow);
1851 [ # # ]: 0 : if (ret < 0)
1852 : 0 : return -rte_errno;
1853 : :
1854 : 0 : ret = fd_flow_parse_action(dev, actions, error, dh_flow);
1855 [ # # ]: 0 : if (ret < 0)
1856 : 0 : return -rte_errno;
1857 : : return 0;
1858 : : }
1859 : :
1860 : : struct dh_flow_engine pf_fd_engine = {
1861 : : .apply = pf_fd_hw_apply,
1862 : : .destroy = pf_fd_hw_destroy,
1863 : : .query_count = pf_fd_hw_query_count,
1864 : : .parse_pattern_action = fd_parse_pattern_action,
1865 : : .type = FLOW_TYPE_FD_TCAM,
1866 : : };
1867 : :
1868 : :
1869 : : static int
1870 : 0 : vf_flow_msg_process(enum zxdh_msg_type msg_type, struct rte_eth_dev *dev,
1871 : : struct zxdh_flow *dh_flow, struct rte_flow_error *error,
1872 : : struct rte_flow_query_count *count)
1873 : : {
1874 : : int ret = 0;
1875 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1876 : 0 : struct zxdh_msg_info msg_info = {0};
1877 : : struct zxdh_flow_op_msg *flow_msg = &msg_info.data.flow_msg;
1878 : :
1879 : 0 : uint8_t zxdh_msg_reply_info[ZXDH_ST_SZ_BYTES(msg_reply_info)] = {0};
1880 : : void *reply_body_addr = ZXDH_ADDR_OF(msg_reply_info, zxdh_msg_reply_info, reply_body);
1881 : : void *flow_rsp_addr = ZXDH_ADDR_OF(msg_reply_body, reply_body_addr, flow_rsp);
1882 : 0 : uint8_t flow_op_rsp[sizeof(struct zxdh_flow_op_rsp)] = {0};
1883 : : uint16_t len = sizeof(struct zxdh_flow_op_rsp) - 4;
1884 : : struct zxdh_flow_op_rsp *flow_rsp = (struct zxdh_flow_op_rsp *)flow_op_rsp;
1885 : :
1886 [ # # ]: 0 : dh_flow->hash_search_index = hw->hash_search_index;
1887 : : rte_memcpy(&flow_msg->dh_flow, dh_flow, sizeof(struct zxdh_flow));
1888 : :
1889 : 0 : zxdh_msg_head_build(hw, msg_type, &msg_info);
1890 : 0 : ret = zxdh_vf_send_msg_to_pf(dev, &msg_info, sizeof(struct zxdh_msg_info),
1891 : : (void *)zxdh_msg_reply_info, ZXDH_ST_SZ_BYTES(msg_reply_info));
1892 : 0 : zxdh_adjust_flow_op_rsp_memory_layout(flow_rsp_addr, len, flow_op_rsp);
1893 [ # # ]: 0 : if (ret) {
1894 : 0 : PMD_DRV_LOG(ERR, "port %d flow op %d failed ret %d", hw->port_id, msg_type, ret);
1895 [ # # ]: 0 : if (ret == -2) {
1896 : 0 : PMD_DRV_LOG(ERR, "port %d flow %d failed: cause %s",
1897 : : hw->port_id, msg_type, flow_rsp->error.reason);
1898 : 0 : rte_flow_error_set(error, EBUSY,
1899 : : RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1900 : : flow_rsp->error.reason);
1901 : : } else {
1902 : 0 : rte_flow_error_set(error, EBUSY,
1903 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1904 : : "msg channel error");
1905 : : }
1906 : 0 : return ret;
1907 : : }
1908 : :
1909 [ # # ]: 0 : if (msg_type == ZXDH_FLOW_HW_ADD)
1910 : 0 : dh_flow->flowentry.hw_idx = flow_rsp->dh_flow.flowentry.hw_idx;
1911 [ # # ]: 0 : if (count)
1912 : : rte_memcpy((void *)count, &flow_rsp->count, sizeof(flow_rsp->count));
1913 : :
1914 : : return ret;
1915 : : }
1916 : :
1917 : : static int
1918 : 0 : vf_fd_apply(struct rte_eth_dev *dev, struct zxdh_flow *dh_flow,
1919 : : struct rte_flow_error *error, uint16_t vport __rte_unused,
1920 : : uint16_t pcieid __rte_unused)
1921 : : {
1922 : : int ret = 0;
1923 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1924 : 0 : ret = vf_flow_msg_process(ZXDH_FLOW_HW_ADD, dev, dh_flow, error, NULL);
1925 [ # # ]: 0 : if (!ret) {
1926 : 0 : uint8_t action_bits = dh_flow->flowentry.fd_flow.result.action_idx;
1927 [ # # ]: 0 : if (((action_bits & (1 << FD_ACTION_VXLAN_ENCAP)) != 0) ||
1928 : : ((action_bits & (1 << FD_ACTION_VXLAN_DECAP)) != 0)) {
1929 : 0 : hw->vxlan_fd_num++;
1930 [ # # ]: 0 : if (hw->vxlan_fd_num == 1) {
1931 : 0 : set_vxlan_enable(dev, 1, error);
1932 : 0 : PMD_DRV_LOG(DEBUG, "vf set_vxlan_enable");
1933 : : }
1934 : : }
1935 : : }
1936 : 0 : return ret;
1937 : : }
1938 : :
1939 : : static int
1940 : 0 : vf_fd_destroy(struct rte_eth_dev *dev, struct zxdh_flow *dh_flow,
1941 : : struct rte_flow_error *error, uint16_t vport __rte_unused,
1942 : : uint16_t pcieid __rte_unused)
1943 : : {
1944 : : int ret = 0;
1945 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
1946 : 0 : ret = vf_flow_msg_process(ZXDH_FLOW_HW_DEL, dev, dh_flow, error, NULL);
1947 [ # # ]: 0 : if (!ret) {
1948 : 0 : uint8_t action_bits = dh_flow->flowentry.fd_flow.result.action_idx;
1949 [ # # ]: 0 : if (((action_bits & (1 << FD_ACTION_VXLAN_ENCAP)) != 0) ||
1950 : : ((action_bits & (1 << FD_ACTION_VXLAN_DECAP)) != 0)) {
1951 : 0 : hw->vxlan_fd_num--;
1952 [ # # ]: 0 : if (hw->vxlan_fd_num == 0) {
1953 : 0 : set_vxlan_enable(dev, 0, error);
1954 : 0 : PMD_DRV_LOG(DEBUG, "vf set_vxlan_disable");
1955 : : }
1956 : : }
1957 : : }
1958 : 0 : return ret;
1959 : : }
1960 : :
1961 : : static int
1962 : 0 : vf_fd_query_count(struct rte_eth_dev *dev,
1963 : : struct zxdh_flow *dh_flow,
1964 : : struct rte_flow_query_count *count,
1965 : : struct rte_flow_error *error)
1966 : : {
1967 : : int ret = 0;
1968 : 0 : ret = vf_flow_msg_process(ZXDH_FLOW_HW_GET, dev, dh_flow, error, count);
1969 : 0 : return ret;
1970 : : }
1971 : :
1972 : :
1973 : : static struct dh_flow_engine vf_fd_engine = {
1974 : : .apply = vf_fd_apply,
1975 : : .destroy = vf_fd_destroy,
1976 : : .parse_pattern_action = fd_parse_pattern_action,
1977 : : .query_count = vf_fd_query_count,
1978 : : .type = FLOW_TYPE_FD_TCAM,
1979 : : };
1980 : :
1981 : 0 : void zxdh_flow_init(struct rte_eth_dev *dev)
1982 : : {
1983 : 0 : struct zxdh_hw *priv = dev->data->dev_private;
1984 [ # # ]: 0 : if (priv->is_pf)
1985 : 0 : zxdh_register_flow_engine(&pf_fd_engine);
1986 : : else
1987 : 0 : zxdh_register_flow_engine(&vf_fd_engine);
1988 : 0 : TAILQ_INIT(&priv->dh_flow_list);
1989 : 0 : }
1990 : :
1991 : : const struct rte_flow_ops zxdh_flow_ops = {
1992 : : .validate = zxdh_flow_validate,
1993 : : .create = zxdh_flow_create,
1994 : : .destroy = zxdh_flow_destroy,
1995 : : .flush = zxdh_flow_flush,
1996 : : .query = zxdh_flow_query,
1997 : : .dev_dump = zxdh_flow_dev_dump,
1998 : : };
1999 : :
2000 : : int
2001 : 0 : zxdh_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
2002 : : const struct rte_flow_ops **ops)
2003 : : {
2004 : 0 : *ops = &zxdh_flow_ops;
2005 : :
2006 : 0 : return 0;
2007 : : }
2008 : :
2009 : : void
2010 : 0 : zxdh_flow_release(struct rte_eth_dev *dev)
2011 : : {
2012 : 0 : struct rte_flow_error error = {0};
2013 : 0 : const struct rte_flow_ops *flow_ops = NULL;
2014 : :
2015 [ # # # # ]: 0 : if (dev->dev_ops && dev->dev_ops->flow_ops_get)
2016 : 0 : dev->dev_ops->flow_ops_get(dev, &flow_ops);
2017 [ # # # # ]: 0 : if (flow_ops && flow_ops->flush)
2018 : 0 : flow_ops->flush(dev, &error);
2019 : 0 : }
|