xref: /dpdk/drivers/net/cnxk/cnxk_flow.c (revision a800675b)
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 
63 static int
npc_rss_action_validate(struct rte_eth_dev * eth_dev,const struct rte_flow_attr * attr,const struct rte_flow_action * act)64 npc_rss_action_validate(struct rte_eth_dev *eth_dev,
65 			const struct rte_flow_attr *attr,
66 			const struct rte_flow_action *act)
67 {
68 	const struct rte_flow_action_rss *rss;
69 
70 	rss = (const struct rte_flow_action_rss *)act->conf;
71 
72 	if (attr->egress) {
73 		plt_err("No support of RSS in egress");
74 		return -EINVAL;
75 	}
76 
77 	if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
78 		plt_err("multi-queue mode is disabled");
79 		return -ENOTSUP;
80 	}
81 
82 	if (!rss || !rss->queue_num) {
83 		plt_err("no valid queues");
84 		return -EINVAL;
85 	}
86 
87 	if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
88 		plt_err("non-default RSS hash functions are not supported");
89 		return -ENOTSUP;
90 	}
91 
92 	if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
93 		plt_err("RSS hash key too large");
94 		return -ENOTSUP;
95 	}
96 
97 	return 0;
98 }
99 
100 static void
npc_rss_flowkey_get(struct cnxk_eth_dev * eth_dev,const struct roc_npc_action * rss_action,uint32_t * flowkey_cfg)101 npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev,
102 		    const struct roc_npc_action *rss_action,
103 		    uint32_t *flowkey_cfg)
104 {
105 	const struct roc_npc_action_rss *rss;
106 
107 	rss = (const struct roc_npc_action_rss *)rss_action->conf;
108 
109 	*flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss->types, rss->level);
110 }
111 
112 static int
cnxk_map_actions(struct rte_eth_dev * eth_dev,const struct rte_flow_attr * attr,const struct rte_flow_action actions[],struct roc_npc_action in_actions[],uint32_t * flowkey_cfg)113 cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
114 		 const struct rte_flow_action actions[],
115 		 struct roc_npc_action in_actions[], uint32_t *flowkey_cfg)
116 {
117 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
118 	const struct rte_flow_action_port_id *port_act;
119 	const struct rte_flow_action_queue *act_q;
120 	struct roc_npc *roc_npc_src = &dev->npc;
121 	struct rte_eth_dev *portid_eth_dev;
122 	char if_name[RTE_ETH_NAME_MAX_LEN];
123 	struct cnxk_eth_dev *hw_dst;
124 	struct roc_npc *roc_npc_dst;
125 	int i = 0, rc = 0;
126 	int rq;
127 
128 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
129 		switch (actions->type) {
130 		case RTE_FLOW_ACTION_TYPE_VOID:
131 			in_actions[i].type = ROC_NPC_ACTION_TYPE_VOID;
132 			break;
133 
134 		case RTE_FLOW_ACTION_TYPE_MARK:
135 			in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
136 			in_actions[i].conf = actions->conf;
137 			break;
138 
139 		case RTE_FLOW_ACTION_TYPE_FLAG:
140 			in_actions[i].type = ROC_NPC_ACTION_TYPE_FLAG;
141 			break;
142 
143 		case RTE_FLOW_ACTION_TYPE_COUNT:
144 			in_actions[i].type = ROC_NPC_ACTION_TYPE_COUNT;
145 			break;
146 
147 		case RTE_FLOW_ACTION_TYPE_DROP:
148 			in_actions[i].type = ROC_NPC_ACTION_TYPE_DROP;
149 			break;
150 
151 		case RTE_FLOW_ACTION_TYPE_PF:
152 			in_actions[i].type = ROC_NPC_ACTION_TYPE_PF;
153 			break;
154 
155 		case RTE_FLOW_ACTION_TYPE_VF:
156 			in_actions[i].type = ROC_NPC_ACTION_TYPE_VF;
157 			in_actions[i].conf = actions->conf;
158 			break;
159 
160 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
161 			in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
162 			in_actions[i].conf = actions->conf;
163 			port_act = (const struct rte_flow_action_port_id *)
164 					   actions->conf;
165 			if (rte_eth_dev_get_name_by_port(port_act->id,
166 							 if_name)) {
167 				plt_err("Name not found for output port id");
168 				goto err_exit;
169 			}
170 			portid_eth_dev = rte_eth_dev_allocated(if_name);
171 			if (!portid_eth_dev) {
172 				plt_err("eth_dev not found for output port id");
173 				goto err_exit;
174 			}
175 			if (strcmp(portid_eth_dev->device->driver->name,
176 				   eth_dev->device->driver->name) != 0) {
177 				plt_err("Output port not under same driver");
178 				goto err_exit;
179 			}
180 			hw_dst = portid_eth_dev->data->dev_private;
181 			roc_npc_dst = &hw_dst->npc;
182 
183 			rc = roc_npc_validate_portid_action(roc_npc_src,
184 							    roc_npc_dst);
185 
186 			if (rc)
187 				goto err_exit;
188 			break;
189 
190 		case RTE_FLOW_ACTION_TYPE_QUEUE:
191 			act_q = (const struct rte_flow_action_queue *)
192 					actions->conf;
193 			rq = act_q->index;
194 			if (rq >= eth_dev->data->nb_rx_queues) {
195 				plt_npc_dbg("Invalid queue index");
196 				goto err_exit;
197 			}
198 			in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
199 			in_actions[i].conf = actions->conf;
200 			break;
201 
202 		case RTE_FLOW_ACTION_TYPE_RSS:
203 			rc = npc_rss_action_validate(eth_dev, attr, actions);
204 			if (rc)
205 				goto err_exit;
206 			in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
207 			in_actions[i].conf = actions->conf;
208 			npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg);
209 			break;
210 
211 		case RTE_FLOW_ACTION_TYPE_SECURITY:
212 			in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
213 			in_actions[i].conf = actions->conf;
214 			break;
215 		case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
216 			in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
217 			break;
218 		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
219 			in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
220 			in_actions[i].conf = actions->conf;
221 			break;
222 		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
223 			in_actions[i].type =
224 				ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
225 			in_actions[i].conf = actions->conf;
226 			break;
227 		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
228 			in_actions[i].type =
229 				ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
230 			in_actions[i].conf = actions->conf;
231 			break;
232 		case RTE_FLOW_ACTION_TYPE_METER:
233 			in_actions[i].type = ROC_NPC_ACTION_TYPE_METER;
234 			in_actions[i].conf = actions->conf;
235 			break;
236 		default:
237 			plt_npc_dbg("Action is not supported = %d",
238 				    actions->type);
239 			goto err_exit;
240 		}
241 		i++;
242 	}
243 	in_actions[i].type = ROC_NPC_ACTION_TYPE_END;
244 	return 0;
245 
246 err_exit:
247 	return -EINVAL;
248 }
249 
250 static int
cnxk_map_flow_data(struct rte_eth_dev * eth_dev,const struct rte_flow_attr * attr,const struct rte_flow_item pattern[],const struct rte_flow_action actions[],struct roc_npc_attr * in_attr,struct roc_npc_item_info in_pattern[],struct roc_npc_action in_actions[],uint32_t * flowkey_cfg)251 cnxk_map_flow_data(struct rte_eth_dev *eth_dev,
252 		   const struct rte_flow_attr *attr,
253 		   const struct rte_flow_item pattern[],
254 		   const struct rte_flow_action actions[],
255 		   struct roc_npc_attr *in_attr,
256 		   struct roc_npc_item_info in_pattern[],
257 		   struct roc_npc_action in_actions[], uint32_t *flowkey_cfg)
258 {
259 	int i = 0;
260 
261 	in_attr->priority = attr->priority;
262 	in_attr->ingress = attr->ingress;
263 	in_attr->egress = attr->egress;
264 
265 	while (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
266 		in_pattern[i].spec = pattern->spec;
267 		in_pattern[i].last = pattern->last;
268 		in_pattern[i].mask = pattern->mask;
269 		in_pattern[i].type = term[pattern->type].item_type;
270 		in_pattern[i].size = term[pattern->type].item_size;
271 		pattern++;
272 		i++;
273 	}
274 	in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
275 
276 	return cnxk_map_actions(eth_dev, attr, actions, in_actions,
277 				flowkey_cfg);
278 }
279 
280 static int
cnxk_flow_validate(struct rte_eth_dev * eth_dev,const struct rte_flow_attr * attr,const struct rte_flow_item pattern[],const struct rte_flow_action actions[],struct rte_flow_error * error)281 cnxk_flow_validate(struct rte_eth_dev *eth_dev,
282 		   const struct rte_flow_attr *attr,
283 		   const struct rte_flow_item pattern[],
284 		   const struct rte_flow_action actions[],
285 		   struct rte_flow_error *error)
286 {
287 	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
288 	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
289 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
290 	struct roc_npc *npc = &dev->npc;
291 	struct roc_npc_attr in_attr;
292 	struct roc_npc_flow flow;
293 	uint32_t flowkey_cfg = 0;
294 	int rc;
295 
296 	memset(&flow, 0, sizeof(flow));
297 
298 	rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr,
299 				in_pattern, in_actions, &flowkey_cfg);
300 	if (rc) {
301 		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
302 				   NULL, "Failed to map flow data");
303 		return rc;
304 	}
305 
306 	rc = roc_npc_flow_parse(npc, &in_attr, in_pattern, in_actions, &flow);
307 
308 	if (rc) {
309 		rte_flow_error_set(error, 0, rc, NULL,
310 				   "Flow validation failed");
311 		return rc;
312 	}
313 	return 0;
314 }
315 
316 struct roc_npc_flow *
cnxk_flow_create(struct rte_eth_dev * eth_dev,const struct rte_flow_attr * attr,const struct rte_flow_item pattern[],const struct rte_flow_action actions[],struct rte_flow_error * error)317 cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
318 		 const struct rte_flow_item pattern[],
319 		 const struct rte_flow_action actions[],
320 		 struct rte_flow_error *error)
321 {
322 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
323 	struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
324 	struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
325 	struct roc_npc *npc = &dev->npc;
326 	struct roc_npc_attr in_attr;
327 	struct roc_npc_flow *flow;
328 	int errcode = 0;
329 	int rc;
330 
331 	rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr,
332 				in_pattern, in_actions,
333 				&npc->flowkey_cfg_state);
334 	if (rc) {
335 		rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
336 				   NULL, "Failed to map flow data");
337 		return NULL;
338 	}
339 
340 	flow = roc_npc_flow_create(npc, &in_attr, in_pattern, in_actions,
341 				   &errcode);
342 	if (errcode != 0) {
343 		rte_flow_error_set(error, errcode, errcode, NULL,
344 				   roc_error_msg_get(errcode));
345 		return NULL;
346 	}
347 
348 	return flow;
349 }
350 
351 int
cnxk_flow_destroy(struct rte_eth_dev * eth_dev,struct roc_npc_flow * flow,struct rte_flow_error * error)352 cnxk_flow_destroy(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
353 		  struct rte_flow_error *error)
354 {
355 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
356 	struct roc_npc *npc = &dev->npc;
357 	int rc;
358 
359 	rc = roc_npc_flow_destroy(npc, flow);
360 	if (rc)
361 		rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
362 				   NULL, "Flow Destroy failed");
363 	return rc;
364 }
365 
366 static int
cnxk_flow_flush(struct rte_eth_dev * eth_dev,struct rte_flow_error * error)367 cnxk_flow_flush(struct rte_eth_dev *eth_dev, struct rte_flow_error *error)
368 {
369 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
370 	struct roc_npc *npc = &dev->npc;
371 	int rc;
372 
373 	rc = roc_npc_mcam_free_all_resources(npc);
374 	if (rc) {
375 		rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
376 				   NULL, "Failed to flush filter");
377 		return -rte_errno;
378 	}
379 
380 	return 0;
381 }
382 
383 static int
cnxk_flow_query(struct rte_eth_dev * eth_dev,struct rte_flow * flow,const struct rte_flow_action * action,void * data,struct rte_flow_error * error)384 cnxk_flow_query(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
385 		const struct rte_flow_action *action, void *data,
386 		struct rte_flow_error *error)
387 {
388 	struct roc_npc_flow *in_flow = (struct roc_npc_flow *)flow;
389 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
390 	struct roc_npc *npc = &dev->npc;
391 	struct rte_flow_query_count *query = data;
392 	const char *errmsg = NULL;
393 	int errcode = ENOTSUP;
394 	int rc;
395 
396 	if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
397 		errmsg = "Only COUNT is supported in query";
398 		goto err_exit;
399 	}
400 
401 	if (in_flow->ctr_id == NPC_COUNTER_NONE) {
402 		errmsg = "Counter is not available";
403 		goto err_exit;
404 	}
405 
406 	rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
407 	if (rc != 0) {
408 		errcode = EIO;
409 		errmsg = "Error reading flow counter";
410 		goto err_exit;
411 	}
412 	query->hits_set = 1;
413 	query->bytes_set = 0;
414 
415 	if (query->reset)
416 		rc = roc_npc_mcam_clear_counter(npc, in_flow->ctr_id);
417 	if (rc != 0) {
418 		errcode = EIO;
419 		errmsg = "Error clearing flow counter";
420 		goto err_exit;
421 	}
422 
423 	return 0;
424 
425 err_exit:
426 	rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
427 			   NULL, errmsg);
428 	return -rte_errno;
429 }
430 
431 static int
cnxk_flow_isolate(struct rte_eth_dev * eth_dev __rte_unused,int enable __rte_unused,struct rte_flow_error * error)432 cnxk_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused,
433 		  int enable __rte_unused, struct rte_flow_error *error)
434 {
435 	/* If we support, we need to un-install the default mcam
436 	 * entry for this port.
437 	 */
438 
439 	rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
440 			   NULL, "Flow isolation not supported");
441 
442 	return -rte_errno;
443 }
444 
445 static int
cnxk_flow_dev_dump(struct rte_eth_dev * eth_dev,struct rte_flow * flow,FILE * file,struct rte_flow_error * error)446 cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
447 		   FILE *file, struct rte_flow_error *error)
448 {
449 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
450 	struct roc_npc *npc = &dev->npc;
451 
452 	if (file == NULL) {
453 		rte_flow_error_set(error, EINVAL,
454 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
455 				   "Invalid file");
456 		return -rte_errno;
457 	}
458 
459 	if (flow != NULL) {
460 		rte_flow_error_set(error, EINVAL,
461 				   RTE_FLOW_ERROR_TYPE_HANDLE,
462 				   NULL,
463 				   "Invalid argument");
464 		return -EINVAL;
465 	}
466 
467 	roc_npc_flow_dump(file, npc);
468 
469 	return 0;
470 }
471 
472 struct rte_flow_ops cnxk_flow_ops = {
473 	.validate = cnxk_flow_validate,
474 	.flush = cnxk_flow_flush,
475 	.query = cnxk_flow_query,
476 	.isolate = cnxk_flow_isolate,
477 	.dev_dump = cnxk_flow_dev_dump,
478 };
479