Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include <cnxk_flow.h>
5 : :
6 : : const struct cnxk_rte_flow_term_info term[] = {
7 : : [RTE_FLOW_ITEM_TYPE_ETH] = {ROC_NPC_ITEM_TYPE_ETH,
8 : : sizeof(struct rte_flow_item_eth)},
9 : : [RTE_FLOW_ITEM_TYPE_VLAN] = {ROC_NPC_ITEM_TYPE_VLAN,
10 : : sizeof(struct rte_flow_item_vlan)},
11 : : [RTE_FLOW_ITEM_TYPE_E_TAG] = {ROC_NPC_ITEM_TYPE_E_TAG,
12 : : sizeof(struct rte_flow_item_e_tag)},
13 : : [RTE_FLOW_ITEM_TYPE_IPV4] = {ROC_NPC_ITEM_TYPE_IPV4,
14 : : sizeof(struct rte_flow_item_ipv4)},
15 : : [RTE_FLOW_ITEM_TYPE_IPV6] = {ROC_NPC_ITEM_TYPE_IPV6,
16 : : sizeof(struct rte_flow_item_ipv6)},
17 : : [RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT] = {
18 : : ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT,
19 : : sizeof(struct rte_flow_item_ipv6_frag_ext)},
20 : : [RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4] = {
21 : : ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
22 : : sizeof(struct rte_flow_item_arp_eth_ipv4)},
23 : : [RTE_FLOW_ITEM_TYPE_MPLS] = {ROC_NPC_ITEM_TYPE_MPLS,
24 : : sizeof(struct rte_flow_item_mpls)},
25 : : [RTE_FLOW_ITEM_TYPE_ICMP] = {ROC_NPC_ITEM_TYPE_ICMP,
26 : : sizeof(struct rte_flow_item_icmp)},
27 : : [RTE_FLOW_ITEM_TYPE_UDP] = {ROC_NPC_ITEM_TYPE_UDP,
28 : : sizeof(struct rte_flow_item_udp)},
29 : : [RTE_FLOW_ITEM_TYPE_TCP] = {ROC_NPC_ITEM_TYPE_TCP,
30 : : sizeof(struct rte_flow_item_tcp)},
31 : : [RTE_FLOW_ITEM_TYPE_SCTP] = {ROC_NPC_ITEM_TYPE_SCTP,
32 : : sizeof(struct rte_flow_item_sctp)},
33 : : [RTE_FLOW_ITEM_TYPE_ESP] = {ROC_NPC_ITEM_TYPE_ESP,
34 : : sizeof(struct rte_flow_item_esp)},
35 : : [RTE_FLOW_ITEM_TYPE_GRE] = {ROC_NPC_ITEM_TYPE_GRE,
36 : : sizeof(struct rte_flow_item_gre)},
37 : : [RTE_FLOW_ITEM_TYPE_NVGRE] = {ROC_NPC_ITEM_TYPE_NVGRE,
38 : : sizeof(struct rte_flow_item_nvgre)},
39 : : [RTE_FLOW_ITEM_TYPE_VXLAN] = {ROC_NPC_ITEM_TYPE_VXLAN,
40 : : sizeof(struct rte_flow_item_vxlan)},
41 : : [RTE_FLOW_ITEM_TYPE_GTPC] = {ROC_NPC_ITEM_TYPE_GTPC,
42 : : sizeof(struct rte_flow_item_gtp)},
43 : : [RTE_FLOW_ITEM_TYPE_GTPU] = {ROC_NPC_ITEM_TYPE_GTPU,
44 : : sizeof(struct rte_flow_item_gtp)},
45 : : [RTE_FLOW_ITEM_TYPE_GENEVE] = {ROC_NPC_ITEM_TYPE_GENEVE,
46 : : sizeof(struct rte_flow_item_geneve)},
47 : : [RTE_FLOW_ITEM_TYPE_VXLAN_GPE] = {
48 : : ROC_NPC_ITEM_TYPE_VXLAN_GPE,
49 : : sizeof(struct rte_flow_item_vxlan_gpe)},
50 : : [RTE_FLOW_ITEM_TYPE_IPV6_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_EXT,
51 : : sizeof(struct rte_flow_item_ipv6_ext)},
52 : : [RTE_FLOW_ITEM_TYPE_VOID] = {ROC_NPC_ITEM_TYPE_VOID, 0},
53 : : [RTE_FLOW_ITEM_TYPE_ANY] = {ROC_NPC_ITEM_TYPE_ANY, 0},
54 : : [RTE_FLOW_ITEM_TYPE_GRE_KEY] = {ROC_NPC_ITEM_TYPE_GRE_KEY,
55 : : sizeof(uint32_t)},
56 : : [RTE_FLOW_ITEM_TYPE_HIGIG2] = {ROC_NPC_ITEM_TYPE_HIGIG2,
57 : : sizeof(struct rte_flow_item_higig2_hdr)},
58 : : [RTE_FLOW_ITEM_TYPE_RAW] = {ROC_NPC_ITEM_TYPE_RAW,
59 : : sizeof(struct rte_flow_item_raw)},
60 : : [RTE_FLOW_ITEM_TYPE_MARK] = {ROC_NPC_ITEM_TYPE_MARK,
61 : : sizeof(struct rte_flow_item_mark)},
62 : : [RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT,
63 : : sizeof(struct rte_flow_item_ipv6_routing_ext)},
64 : : [RTE_FLOW_ITEM_TYPE_TX_QUEUE] = {ROC_NPC_ITEM_TYPE_TX_QUEUE,
65 : : sizeof(struct rte_flow_item_tx_queue)},
66 : : [RTE_FLOW_ITEM_TYPE_PPPOES] = {ROC_NPC_ITEM_TYPE_PPPOES,
67 : : sizeof(struct rte_flow_item_pppoe)}};
68 : :
69 : : static int
70 : 0 : npc_rss_action_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
71 : : const struct rte_flow_action *act)
72 : : {
73 : : const struct rte_flow_action_rss *rss;
74 : :
75 : 0 : rss = (const struct rte_flow_action_rss *)act->conf;
76 : :
77 [ # # ]: 0 : if (attr->egress) {
78 : 0 : plt_err("No support of RSS in egress");
79 : 0 : return -EINVAL;
80 : : }
81 : :
82 [ # # ]: 0 : if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
83 : 0 : plt_err("multi-queue mode is disabled");
84 : 0 : return -ENOTSUP;
85 : : }
86 : :
87 [ # # # # ]: 0 : if (!rss || !rss->queue_num) {
88 : 0 : plt_err("no valid queues");
89 : 0 : return -EINVAL;
90 : : }
91 : :
92 [ # # ]: 0 : if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
93 : 0 : plt_err("non-default RSS hash functions are not supported");
94 : 0 : return -ENOTSUP;
95 : : }
96 : :
97 [ # # ]: 0 : if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
98 : 0 : plt_err("RSS hash key too large");
99 : 0 : return -ENOTSUP;
100 : : }
101 : :
102 : : return 0;
103 : : }
104 : :
105 : : static void
106 : : npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev, const struct roc_npc_action *rss_action,
107 : : uint32_t *flowkey_cfg, uint64_t default_rss_types)
108 : : {
109 : : const struct roc_npc_action_rss *rss;
110 : : uint64_t rss_types;
111 : :
112 : : rss = (const struct roc_npc_action_rss *)rss_action->conf;
113 : 0 : rss_types = rss->types;
114 : : /* If no RSS types are specified, use default one */
115 : 0 : if (rss_types == 0)
116 : : rss_types = default_rss_types;
117 : :
118 : 0 : *flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss_types, rss->level);
119 : 0 : }
120 : :
121 : : static int
122 : 0 : npc_parse_port_id_action(struct rte_eth_dev *eth_dev, const struct rte_flow_action *action,
123 : : uint16_t *dst_pf_func, uint16_t *dst_channel)
124 : : {
125 : : const struct rte_flow_action_port_id *port_act;
126 : : struct rte_eth_dev *portid_eth_dev;
127 : : char if_name[RTE_ETH_NAME_MAX_LEN];
128 : : struct cnxk_eth_dev *hw_dst;
129 : : struct roc_npc *roc_npc_dst;
130 : : int rc = 0;
131 : :
132 : 0 : port_act = (const struct rte_flow_action_port_id *)action->conf;
133 : :
134 : 0 : rc = rte_eth_dev_get_name_by_port(port_act->id, if_name);
135 [ # # ]: 0 : if (rc) {
136 : 0 : plt_err("Name not found for output port id");
137 : 0 : goto err_exit;
138 : : }
139 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
140 [ # # ]: 0 : if (!portid_eth_dev) {
141 : 0 : plt_err("eth_dev not found for output port id");
142 : 0 : goto err_exit;
143 : : }
144 [ # # ]: 0 : if (strcmp(portid_eth_dev->device->driver->name, eth_dev->device->driver->name) != 0) {
145 : 0 : plt_err("Output port not under same driver");
146 : 0 : goto err_exit;
147 : : }
148 : 0 : hw_dst = portid_eth_dev->data->dev_private;
149 : : roc_npc_dst = &hw_dst->npc;
150 : 0 : *dst_pf_func = roc_npc_dst->pf_func;
151 : 0 : *dst_channel = hw_dst->npc.channel;
152 : :
153 : 0 : return 0;
154 : :
155 : : err_exit:
156 : : return -EINVAL;
157 : : }
158 : :
159 : : static int
160 : 0 : roc_npc_parse_sample_subaction(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[],
161 : : struct roc_npc_action_sample *sample_action)
162 : : {
163 : 0 : uint16_t dst_pf_func = 0, dst_channel = 0;
164 : : const struct roc_npc_action_vf *vf_act;
165 : : int rc = 0, count = 0;
166 : : bool is_empty = true;
167 : :
168 [ # # ]: 0 : if (sample_action->ratio != 1) {
169 : 0 : plt_err("Sample ratio must be 1");
170 : 0 : return -EINVAL;
171 : : }
172 : :
173 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
174 : : is_empty = false;
175 [ # # # # ]: 0 : switch (actions->type) {
176 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
177 : 0 : count++;
178 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_PF;
179 : 0 : break;
180 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
181 : 0 : count++;
182 : 0 : vf_act = (const struct roc_npc_action_vf *)actions->conf;
183 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_VF;
184 : 0 : sample_action->pf_func = vf_act->id & NPC_PFVF_FUNC_MASK;
185 : 0 : break;
186 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
187 : 0 : rc = npc_parse_port_id_action(eth_dev, actions, &dst_pf_func, &dst_channel);
188 [ # # ]: 0 : if (rc)
189 : : return -EINVAL;
190 : :
191 : 0 : count++;
192 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_PORT_ID;
193 : 0 : sample_action->pf_func = dst_pf_func;
194 : 0 : sample_action->channel = dst_channel;
195 : 0 : break;
196 : 0 : default:
197 : 0 : continue;
198 : : }
199 : : }
200 : :
201 [ # # ]: 0 : if (count > 1 || is_empty)
202 : 0 : return -EINVAL;
203 : :
204 : : return 0;
205 : : }
206 : :
207 : : static int
208 : 0 : cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
209 : : const struct rte_flow_action actions[], struct roc_npc_action in_actions[],
210 : : struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
211 : : uint16_t *dst_pf_func)
212 : : {
213 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
214 : : const struct rte_flow_action_queue *act_q = NULL;
215 : : const struct rte_flow_action_ethdev *act_ethdev;
216 : : const struct rte_flow_action_sample *act_sample;
217 : : const struct rte_flow_action_port_id *port_act;
218 : : struct rte_eth_dev *portid_eth_dev;
219 : : char if_name[RTE_ETH_NAME_MAX_LEN];
220 : : struct cnxk_eth_dev *hw_dst;
221 : : struct roc_npc *roc_npc_dst;
222 : : bool is_vf_action = false;
223 : : int i = 0, rc = 0;
224 : : int rq;
225 : :
226 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
227 [ # # # # : 0 : switch (actions->type) {
# # # # #
# # # # #
# # # #
# ]
228 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
229 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VOID;
230 : 0 : break;
231 : :
232 : 0 : case RTE_FLOW_ACTION_TYPE_MARK:
233 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
234 : 0 : in_actions[i].conf = actions->conf;
235 : 0 : break;
236 : :
237 : 0 : case RTE_FLOW_ACTION_TYPE_FLAG:
238 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_FLAG;
239 : 0 : break;
240 : :
241 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
242 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_COUNT;
243 : 0 : break;
244 : :
245 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
246 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_DROP;
247 : 0 : break;
248 : :
249 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
250 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PF;
251 : 0 : break;
252 : :
253 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
254 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VF;
255 : 0 : in_actions[i].conf = actions->conf;
256 : : is_vf_action = true;
257 : 0 : break;
258 : :
259 : 0 : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
260 : : case RTE_FLOW_ACTION_TYPE_PORT_ID:
261 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
262 : 0 : in_actions[i].conf = actions->conf;
263 : : act_ethdev = (const struct rte_flow_action_ethdev *)
264 : : actions->conf;
265 : : port_act = (const struct rte_flow_action_port_id *)
266 : : actions->conf;
267 [ # # # # ]: 0 : if (rte_eth_dev_get_name_by_port(
268 : : actions->type != RTE_FLOW_ACTION_TYPE_PORT_ID ?
269 : 0 : act_ethdev->port_id : port_act->id, if_name)) {
270 : 0 : plt_err("Name not found for output port id");
271 : 0 : goto err_exit;
272 : : }
273 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
274 [ # # ]: 0 : if (!portid_eth_dev) {
275 : 0 : plt_err("eth_dev not found for output port id");
276 : 0 : goto err_exit;
277 : : }
278 : 0 : if (strcmp(portid_eth_dev->device->driver->name,
279 [ # # ]: 0 : eth_dev->device->driver->name) != 0) {
280 : 0 : plt_err("Output port not under same driver");
281 : 0 : goto err_exit;
282 : : }
283 : 0 : hw_dst = portid_eth_dev->data->dev_private;
284 : : roc_npc_dst = &hw_dst->npc;
285 : 0 : *dst_pf_func = roc_npc_dst->pf_func;
286 : 0 : break;
287 : :
288 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
289 : 0 : act_q = (const struct rte_flow_action_queue *)actions->conf;
290 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
291 : 0 : in_actions[i].conf = actions->conf;
292 : 0 : break;
293 : :
294 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
295 : 0 : rc = npc_rss_action_validate(eth_dev, attr, actions);
296 [ # # ]: 0 : if (rc)
297 : 0 : goto err_exit;
298 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
299 : 0 : in_actions[i].conf = actions->conf;
300 : 0 : npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg,
301 [ # # ]: 0 : eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf);
302 : : break;
303 : :
304 : 0 : case RTE_FLOW_ACTION_TYPE_SECURITY:
305 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
306 : 0 : in_actions[i].conf = actions->conf;
307 : 0 : break;
308 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
309 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
310 : 0 : break;
311 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
312 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
313 : 0 : in_actions[i].conf = actions->conf;
314 : 0 : break;
315 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
316 : 0 : in_actions[i].type =
317 : : ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
318 : 0 : in_actions[i].conf = actions->conf;
319 : 0 : break;
320 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
321 : 0 : in_actions[i].type =
322 : : ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
323 : 0 : in_actions[i].conf = actions->conf;
324 : 0 : break;
325 : 0 : case RTE_FLOW_ACTION_TYPE_METER:
326 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_METER;
327 : 0 : in_actions[i].conf = actions->conf;
328 : 0 : break;
329 : 0 : case RTE_FLOW_ACTION_TYPE_AGE:
330 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE;
331 : 0 : in_actions[i].conf = actions->conf;
332 : 0 : break;
333 : 0 : case RTE_FLOW_ACTION_TYPE_SAMPLE:
334 : 0 : act_sample = actions->conf;
335 : 0 : in_sample_actions->ratio = act_sample->ratio;
336 : 0 : rc = roc_npc_parse_sample_subaction(eth_dev, act_sample->actions,
337 : : in_sample_actions);
338 [ # # ]: 0 : if (rc) {
339 : 0 : plt_err("Sample subaction parsing failed.");
340 : 0 : goto err_exit;
341 : : }
342 : :
343 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_SAMPLE;
344 : 0 : in_actions[i].conf = in_sample_actions;
345 : 0 : break;
346 : 0 : default:
347 : 0 : plt_npc_dbg("Action is not supported = %d", actions->type);
348 : 0 : goto err_exit;
349 : : }
350 : 0 : i++;
351 : : }
352 : :
353 [ # # ]: 0 : if (!is_vf_action && act_q) {
354 : 0 : rq = act_q->index;
355 [ # # ]: 0 : if (rq >= eth_dev->data->nb_rx_queues) {
356 : 0 : plt_npc_dbg("Invalid queue index");
357 : 0 : goto err_exit;
358 : : }
359 : : }
360 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_END;
361 : 0 : return 0;
362 : :
363 : : err_exit:
364 : : return -EINVAL;
365 : : }
366 : :
367 : : static int
368 : 0 : cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
369 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
370 : : struct roc_npc_attr *in_attr, struct roc_npc_item_info in_pattern[],
371 : : struct roc_npc_action in_actions[],
372 : : struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
373 : : uint16_t *dst_pf_func)
374 : : {
375 : : int i = 0;
376 : :
377 : 0 : in_attr->priority = attr->priority;
378 : 0 : in_attr->ingress = attr->ingress;
379 : 0 : in_attr->egress = attr->egress;
380 : :
381 [ # # ]: 0 : while (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
382 : 0 : in_pattern[i].spec = pattern->spec;
383 : 0 : in_pattern[i].last = pattern->last;
384 : 0 : in_pattern[i].mask = pattern->mask;
385 : 0 : in_pattern[i].type = term[pattern->type].item_type;
386 : 0 : in_pattern[i].size = term[pattern->type].item_size;
387 : 0 : pattern++;
388 : 0 : i++;
389 : : }
390 : 0 : in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
391 : :
392 : 0 : return cnxk_map_actions(eth_dev, attr, actions, in_actions, in_sample_actions, flowkey_cfg,
393 : : dst_pf_func);
394 : : }
395 : :
396 : : static int
397 [ # # ]: 0 : cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
398 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
399 : : struct rte_flow_error *error)
400 : : {
401 : : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
402 : : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
403 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
404 : : struct roc_npc_action_sample in_sample_action;
405 : 0 : struct roc_npc *npc = &dev->npc;
406 : : struct roc_npc_attr in_attr;
407 : : struct roc_npc_flow flow;
408 : 0 : uint32_t flowkey_cfg = 0;
409 : 0 : uint16_t dst_pf_func = 0;
410 : : int rc;
411 : :
412 : : /* Skip flow validation for MACsec. */
413 [ # # # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
414 : 0 : cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL)
415 : : return 0;
416 : :
417 : : memset(&flow, 0, sizeof(flow));
418 : : memset(&in_sample_action, 0, sizeof(in_sample_action));
419 : 0 : flow.is_validate = true;
420 : :
421 : 0 : rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
422 : : &in_sample_action, &flowkey_cfg, &dst_pf_func);
423 [ # # ]: 0 : if (rc) {
424 : 0 : rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
425 : : "Failed to map flow data");
426 : 0 : return rc;
427 : : }
428 : :
429 : 0 : rc = roc_npc_flow_parse(npc, &in_attr, in_pattern, in_actions, &flow);
430 : :
431 [ # # ]: 0 : if (rc) {
432 : 0 : rte_flow_error_set(error, 0, rc, NULL,
433 : : "Flow validation failed");
434 : 0 : return rc;
435 : : }
436 : : return 0;
437 : : }
438 : :
439 : : struct roc_npc_flow *
440 : 0 : cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
441 : : const struct rte_flow_item pattern[],
442 : : const struct rte_flow_action actions[],
443 : : struct rte_flow_error *error)
444 : : {
445 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
446 : : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
447 : : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
448 : : struct roc_npc_action_sample in_sample_action;
449 : 0 : struct roc_npc *npc = &dev->npc;
450 : : struct roc_npc_attr in_attr;
451 : : struct roc_npc_flow *flow;
452 : 0 : uint16_t dst_pf_func = 0;
453 : 0 : int errcode = 0;
454 : : int rc;
455 : :
456 : : memset(&in_sample_action, 0, sizeof(in_sample_action));
457 : 0 : rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
458 : : &in_sample_action, &npc->flowkey_cfg_state, &dst_pf_func);
459 [ # # ]: 0 : if (rc) {
460 : 0 : rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
461 : : "Failed to map flow data");
462 : 0 : return NULL;
463 : : }
464 : :
465 : 0 : flow = roc_npc_flow_create(npc, &in_attr, in_pattern, in_actions, dst_pf_func, &errcode);
466 [ # # ]: 0 : if (errcode != 0) {
467 : 0 : rte_flow_error_set(error, errcode, errcode, NULL, roc_error_msg_get(errcode));
468 : 0 : return NULL;
469 : : }
470 : :
471 : : return flow;
472 : : }
473 : :
474 : : int
475 : 0 : cnxk_flow_destroy(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
476 : : struct rte_flow_error *error)
477 : : {
478 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
479 : 0 : struct roc_npc *npc = &dev->npc;
480 : : int rc;
481 : :
482 : 0 : rc = roc_npc_flow_destroy(npc, flow);
483 [ # # ]: 0 : if (rc)
484 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
485 : : NULL, "Flow Destroy failed");
486 : 0 : return rc;
487 : : }
488 : :
489 : : static int
490 : 0 : cnxk_flow_flush(struct rte_eth_dev *eth_dev, struct rte_flow_error *error)
491 : : {
492 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
493 : 0 : struct roc_npc *npc = &dev->npc;
494 : : int rc;
495 : :
496 : 0 : rc = roc_npc_mcam_free_all_resources(npc);
497 [ # # ]: 0 : if (rc) {
498 : 0 : rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
499 : : NULL, "Failed to flush filter");
500 : 0 : return -rte_errno;
501 : : }
502 : :
503 : : return 0;
504 : : }
505 : :
506 : : static int
507 [ # # ]: 0 : cnxk_flow_query(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
508 : : const struct rte_flow_action *action, void *data,
509 : : struct rte_flow_error *error)
510 : : {
511 : : struct roc_npc_flow *in_flow = (struct roc_npc_flow *)flow;
512 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
513 : 0 : struct roc_npc *npc = &dev->npc;
514 : : struct rte_flow_query_count *query = data;
515 : : const char *errmsg = NULL;
516 : : int errcode = ENOTSUP;
517 : : int rc;
518 : :
519 [ # # ]: 0 : if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
520 : : errmsg = "Only COUNT is supported in query";
521 : 0 : goto err_exit;
522 : : }
523 : :
524 [ # # ]: 0 : if (in_flow->ctr_id == NPC_COUNTER_NONE) {
525 : : errmsg = "Counter is not available";
526 : 0 : goto err_exit;
527 : : }
528 : :
529 [ # # ]: 0 : if (in_flow->use_pre_alloc)
530 : 0 : rc = roc_npc_inl_mcam_read_counter(in_flow->ctr_id, &query->hits);
531 : : else
532 : 0 : rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
533 [ # # ]: 0 : if (rc != 0) {
534 : : errcode = EIO;
535 : : errmsg = "Error reading flow counter";
536 : 0 : goto err_exit;
537 : : }
538 : 0 : query->hits_set = 1;
539 : 0 : query->bytes_set = 0;
540 : :
541 [ # # ]: 0 : if (query->reset) {
542 [ # # ]: 0 : if (in_flow->use_pre_alloc)
543 : 0 : rc = roc_npc_inl_mcam_clear_counter(in_flow->ctr_id);
544 : : else
545 : 0 : rc = roc_npc_mcam_clear_counter(npc, in_flow->ctr_id);
546 : : }
547 [ # # ]: 0 : if (rc != 0) {
548 : : errcode = EIO;
549 : : errmsg = "Error clearing flow counter";
550 : 0 : goto err_exit;
551 : : }
552 : :
553 : : return 0;
554 : :
555 : 0 : err_exit:
556 : 0 : rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
557 : : NULL, errmsg);
558 : 0 : return -rte_errno;
559 : : }
560 : :
561 : : static int
562 : 0 : cnxk_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused,
563 : : int enable __rte_unused, struct rte_flow_error *error)
564 : : {
565 : : /* If we support, we need to un-install the default mcam
566 : : * entry for this port.
567 : : */
568 : :
569 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
570 : : NULL, "Flow isolation not supported");
571 : :
572 : 0 : return -rte_errno;
573 : : }
574 : :
575 : : static int
576 [ # # ]: 0 : cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
577 : : FILE *file, struct rte_flow_error *error)
578 : : {
579 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
580 : 0 : struct roc_npc *npc = &dev->npc;
581 : :
582 [ # # ]: 0 : if (file == NULL) {
583 : 0 : rte_flow_error_set(error, EINVAL,
584 : : RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
585 : : "Invalid file");
586 : 0 : return -rte_errno;
587 : : }
588 : :
589 [ # # ]: 0 : if (flow != NULL) {
590 : 0 : rte_flow_error_set(error, EINVAL,
591 : : RTE_FLOW_ERROR_TYPE_HANDLE,
592 : : NULL,
593 : : "Invalid argument");
594 : 0 : return -EINVAL;
595 : : }
596 : :
597 : 0 : roc_npc_flow_dump(file, npc);
598 : :
599 : 0 : return 0;
600 : : }
601 : :
602 : : static int
603 [ # # ]: 0 : cnxk_flow_get_aged_flows(struct rte_eth_dev *eth_dev, void **context,
604 : : uint32_t nb_contexts, struct rte_flow_error *err)
605 : : {
606 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
607 : 0 : struct roc_npc *roc_npc = &dev->npc;
608 : : struct roc_npc_flow_age *flow_age;
609 : : uint32_t start_id;
610 : : uint32_t end_id;
611 : : int cnt = 0;
612 : : uint32_t sn;
613 : : uint32_t i;
614 : :
615 : : RTE_SET_USED(err);
616 : :
617 : : flow_age = &roc_npc->flow_age;
618 : :
619 [ # # ]: 0 : if (!flow_age->age_flow_refcnt)
620 : : return 0;
621 : :
622 : : do {
623 : : sn = plt_seqcount_read_begin(&flow_age->seq_cnt);
624 : :
625 [ # # ]: 0 : if (nb_contexts == 0) {
626 : 0 : cnt = flow_age->aged_flows_cnt;
627 : : } else {
628 : 0 : start_id = flow_age->start_id;
629 : 0 : end_id = flow_age->end_id;
630 [ # # ]: 0 : for (i = start_id; i <= end_id; i++) {
631 [ # # ]: 0 : if ((int)nb_contexts == cnt)
632 : : break;
633 [ # # ]: 0 : if (plt_bitmap_get(flow_age->aged_flows, i)) {
634 : 0 : context[cnt] =
635 : 0 : roc_npc_aged_flow_ctx_get(roc_npc, i);
636 : 0 : cnt++;
637 : : }
638 : : }
639 : : }
640 [ # # ]: 0 : } while (plt_seqcount_read_retry(&flow_age->seq_cnt, sn));
641 : :
642 : : return cnt;
643 : : }
644 : :
645 : : struct rte_flow_ops cnxk_flow_ops = {
646 : : .validate = cnxk_flow_validate,
647 : : .flush = cnxk_flow_flush,
648 : : .query = cnxk_flow_query,
649 : : .isolate = cnxk_flow_isolate,
650 : : .dev_dump = cnxk_flow_dev_dump,
651 : : .get_aged_flows = cnxk_flow_get_aged_flows,
652 : : };
|