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 : : #include <cnxk_rep.h>
6 : :
7 : : #define IS_REP_BIT 7
8 : :
9 : : #define TNL_DCP_MATCH_ID 5
10 : : #define NRML_MATCH_ID 1
11 : : const struct cnxk_rte_flow_term_info term[] = {
12 : : [RTE_FLOW_ITEM_TYPE_ETH] = {ROC_NPC_ITEM_TYPE_ETH, sizeof(struct rte_flow_item_eth)},
13 : : [RTE_FLOW_ITEM_TYPE_VLAN] = {ROC_NPC_ITEM_TYPE_VLAN, sizeof(struct rte_flow_item_vlan)},
14 : : [RTE_FLOW_ITEM_TYPE_E_TAG] = {ROC_NPC_ITEM_TYPE_E_TAG, sizeof(struct rte_flow_item_e_tag)},
15 : : [RTE_FLOW_ITEM_TYPE_IPV4] = {ROC_NPC_ITEM_TYPE_IPV4, sizeof(struct rte_flow_item_ipv4)},
16 : : [RTE_FLOW_ITEM_TYPE_IPV6] = {ROC_NPC_ITEM_TYPE_IPV6, sizeof(struct rte_flow_item_ipv6)},
17 : : [RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT,
18 : : sizeof(struct rte_flow_item_ipv6_frag_ext)},
19 : : [RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4] = {ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
20 : : sizeof(struct rte_flow_item_arp_eth_ipv4)},
21 : : [RTE_FLOW_ITEM_TYPE_MPLS] = {ROC_NPC_ITEM_TYPE_MPLS, sizeof(struct rte_flow_item_mpls)},
22 : : [RTE_FLOW_ITEM_TYPE_ICMP] = {ROC_NPC_ITEM_TYPE_ICMP, sizeof(struct rte_flow_item_icmp)},
23 : : [RTE_FLOW_ITEM_TYPE_UDP] = {ROC_NPC_ITEM_TYPE_UDP, sizeof(struct rte_flow_item_udp)},
24 : : [RTE_FLOW_ITEM_TYPE_TCP] = {ROC_NPC_ITEM_TYPE_TCP, sizeof(struct rte_flow_item_tcp)},
25 : : [RTE_FLOW_ITEM_TYPE_SCTP] = {ROC_NPC_ITEM_TYPE_SCTP, sizeof(struct rte_flow_item_sctp)},
26 : : [RTE_FLOW_ITEM_TYPE_ESP] = {ROC_NPC_ITEM_TYPE_ESP, sizeof(struct rte_flow_item_esp)},
27 : : [RTE_FLOW_ITEM_TYPE_GRE] = {ROC_NPC_ITEM_TYPE_GRE, sizeof(struct rte_flow_item_gre)},
28 : : [RTE_FLOW_ITEM_TYPE_NVGRE] = {ROC_NPC_ITEM_TYPE_NVGRE, sizeof(struct rte_flow_item_nvgre)},
29 : : [RTE_FLOW_ITEM_TYPE_VXLAN] = {ROC_NPC_ITEM_TYPE_VXLAN, sizeof(struct rte_flow_item_vxlan)},
30 : : [RTE_FLOW_ITEM_TYPE_GTPC] = {ROC_NPC_ITEM_TYPE_GTPC, sizeof(struct rte_flow_item_gtp)},
31 : : [RTE_FLOW_ITEM_TYPE_GTPU] = {ROC_NPC_ITEM_TYPE_GTPU, sizeof(struct rte_flow_item_gtp)},
32 : : [RTE_FLOW_ITEM_TYPE_GENEVE] = {ROC_NPC_ITEM_TYPE_GENEVE,
33 : : sizeof(struct rte_flow_item_geneve)},
34 : : [RTE_FLOW_ITEM_TYPE_VXLAN_GPE] = {ROC_NPC_ITEM_TYPE_VXLAN_GPE,
35 : : sizeof(struct rte_flow_item_vxlan_gpe)},
36 : : [RTE_FLOW_ITEM_TYPE_IPV6_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_EXT,
37 : : sizeof(struct rte_flow_item_ipv6_ext)},
38 : : [RTE_FLOW_ITEM_TYPE_VOID] = {ROC_NPC_ITEM_TYPE_VOID, 0},
39 : : [RTE_FLOW_ITEM_TYPE_ANY] = {ROC_NPC_ITEM_TYPE_ANY, 0},
40 : : [RTE_FLOW_ITEM_TYPE_GRE_KEY] = {ROC_NPC_ITEM_TYPE_GRE_KEY, sizeof(uint32_t)},
41 : : [RTE_FLOW_ITEM_TYPE_HIGIG2] = {ROC_NPC_ITEM_TYPE_HIGIG2,
42 : : sizeof(struct rte_flow_item_higig2_hdr)},
43 : : [RTE_FLOW_ITEM_TYPE_RAW] = {ROC_NPC_ITEM_TYPE_RAW, sizeof(struct rte_flow_item_raw)},
44 : : [RTE_FLOW_ITEM_TYPE_MARK] = {ROC_NPC_ITEM_TYPE_MARK, sizeof(struct rte_flow_item_mark)},
45 : : [RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT] = {ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT,
46 : : sizeof(struct rte_flow_item_ipv6_routing_ext)},
47 : : [RTE_FLOW_ITEM_TYPE_TX_QUEUE] = {ROC_NPC_ITEM_TYPE_TX_QUEUE,
48 : : sizeof(struct rte_flow_item_tx_queue)},
49 : : [RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT] = {ROC_NPC_ITEM_TYPE_REPRESENTED_PORT,
50 : : sizeof(struct rte_flow_item_ethdev)},
51 : : [RTE_FLOW_ITEM_TYPE_PPPOES] = {ROC_NPC_ITEM_TYPE_PPPOES,
52 : : sizeof(struct rte_flow_item_pppoe)}
53 : : };
54 : :
55 : : static int
56 : 0 : npc_rss_action_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
57 : : const struct rte_flow_action *act)
58 : : {
59 : : const struct rte_flow_action_rss *rss;
60 : :
61 : 0 : rss = (const struct rte_flow_action_rss *)act->conf;
62 : :
63 [ # # ]: 0 : if (attr->egress) {
64 : 0 : plt_err("No support of RSS in egress");
65 : 0 : return -EINVAL;
66 : : }
67 : :
68 [ # # ]: 0 : if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
69 : 0 : plt_err("multi-queue mode is disabled");
70 : 0 : return -ENOTSUP;
71 : : }
72 : :
73 [ # # # # ]: 0 : if (!rss || !rss->queue_num) {
74 : 0 : plt_err("no valid queues");
75 : 0 : return -EINVAL;
76 : : }
77 : :
78 [ # # ]: 0 : if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
79 : 0 : plt_err("non-default RSS hash functions are not supported");
80 : 0 : return -ENOTSUP;
81 : : }
82 : :
83 [ # # ]: 0 : if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
84 : 0 : plt_err("RSS hash key too large");
85 : 0 : return -ENOTSUP;
86 : : }
87 : :
88 : : return 0;
89 : : }
90 : :
91 : : static void
92 : : npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev, const struct roc_npc_action *rss_action,
93 : : uint32_t *flowkey_cfg, uint64_t default_rss_types)
94 : : {
95 : : const struct roc_npc_action_rss *rss;
96 : : uint64_t rss_types;
97 : :
98 : : rss = (const struct roc_npc_action_rss *)rss_action->conf;
99 : 0 : rss_types = rss->types;
100 : : /* If no RSS types are specified, use default one */
101 : 0 : if (rss_types == 0)
102 : : rss_types = default_rss_types;
103 : :
104 : 0 : *flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss_types, rss->level);
105 : 0 : }
106 : :
107 : : static int
108 : 0 : npc_parse_port_id_action(struct rte_eth_dev *eth_dev, const struct rte_flow_action *action,
109 : : uint16_t *dst_pf_func, uint16_t *dst_channel)
110 : : {
111 : : const struct rte_flow_action_port_id *port_act;
112 : : struct rte_eth_dev *portid_eth_dev;
113 : : char if_name[RTE_ETH_NAME_MAX_LEN];
114 : : struct cnxk_eth_dev *hw_dst;
115 : : struct roc_npc *roc_npc_dst;
116 : : int rc = 0;
117 : :
118 : 0 : port_act = (const struct rte_flow_action_port_id *)action->conf;
119 : :
120 : 0 : rc = rte_eth_dev_get_name_by_port(port_act->id, if_name);
121 [ # # ]: 0 : if (rc) {
122 : 0 : plt_err("Name not found for output port id");
123 : 0 : goto err_exit;
124 : : }
125 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
126 [ # # ]: 0 : if (!portid_eth_dev) {
127 : 0 : plt_err("eth_dev not found for output port id");
128 : 0 : goto err_exit;
129 : : }
130 [ # # ]: 0 : if (strcmp(portid_eth_dev->device->driver->name, eth_dev->device->driver->name) != 0) {
131 : 0 : plt_err("Output port not under same driver");
132 : 0 : goto err_exit;
133 : : }
134 : 0 : hw_dst = portid_eth_dev->data->dev_private;
135 : : roc_npc_dst = &hw_dst->npc;
136 : 0 : *dst_pf_func = roc_npc_dst->pf_func;
137 : 0 : *dst_channel = hw_dst->npc.channel;
138 : :
139 : 0 : return 0;
140 : :
141 : : err_exit:
142 : : return -EINVAL;
143 : : }
144 : :
145 : : static int
146 : 0 : roc_npc_parse_sample_subaction(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[],
147 : : struct roc_npc_action_sample *sample_action)
148 : : {
149 : 0 : uint16_t dst_pf_func = 0, dst_channel = 0;
150 : : const struct roc_npc_action_vf *vf_act;
151 : : int rc = 0, count = 0;
152 : : bool is_empty = true;
153 : :
154 [ # # ]: 0 : if (sample_action->ratio != 1) {
155 : 0 : plt_err("Sample ratio must be 1");
156 : 0 : return -EINVAL;
157 : : }
158 : :
159 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
160 : : is_empty = false;
161 [ # # # # ]: 0 : switch (actions->type) {
162 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
163 : 0 : count++;
164 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_PF;
165 : 0 : break;
166 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
167 : 0 : count++;
168 : 0 : vf_act = (const struct roc_npc_action_vf *)actions->conf;
169 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_VF;
170 : 0 : sample_action->pf_func = vf_act->id & NPC_PFVF_FUNC_MASK;
171 : 0 : break;
172 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
173 : 0 : rc = npc_parse_port_id_action(eth_dev, actions, &dst_pf_func, &dst_channel);
174 [ # # ]: 0 : if (rc)
175 : : return -EINVAL;
176 : :
177 : 0 : count++;
178 : 0 : sample_action->action_type |= ROC_NPC_ACTION_TYPE_PORT_ID;
179 : 0 : sample_action->pf_func = dst_pf_func;
180 : 0 : sample_action->channel = dst_channel;
181 : 0 : break;
182 : 0 : default:
183 : 0 : continue;
184 : : }
185 : : }
186 : :
187 [ # # ]: 0 : if (count > 1 || is_empty)
188 : 0 : return -EINVAL;
189 : :
190 : : return 0;
191 : : }
192 : :
193 : : static int
194 : 0 : append_mark_action(struct roc_npc_action *in_actions, uint8_t has_tunnel_pattern,
195 : : uint64_t *free_allocs, int *act_cnt)
196 : : {
197 : : struct rte_flow_action_mark *act_mark;
198 : 0 : int i = *act_cnt, j = 0;
199 : :
200 : : /* Add Mark action */
201 : 0 : i++;
202 : 0 : act_mark = plt_zmalloc(sizeof(struct rte_flow_action_mark), 0);
203 [ # # ]: 0 : if (!act_mark) {
204 : 0 : plt_err("Error allocation memory");
205 : 0 : return -ENOMEM;
206 : : }
207 : :
208 [ # # ]: 0 : while (free_allocs[j] != 0)
209 : 0 : j++;
210 : 0 : free_allocs[j] = (uint64_t)act_mark;
211 : : /* Mark ID format: (tunnel type - VxLAN, Geneve << 6) | Tunnel decap */
212 : 0 : act_mark->id =
213 [ # # ]: 0 : has_tunnel_pattern ? ((has_tunnel_pattern << 6) | TNL_DCP_MATCH_ID) : NRML_MATCH_ID;
214 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
215 : 0 : in_actions[i].conf = (struct rte_flow_action_mark *)act_mark;
216 : :
217 : 0 : plt_rep_dbg("Assigned mark ID %x", act_mark->id);
218 : :
219 : 0 : *act_cnt = i;
220 : :
221 : 0 : return 0;
222 : : }
223 : :
224 : : static int
225 : 0 : append_rss_action(struct cnxk_eth_dev *dev, struct roc_npc_action *in_actions, uint16_t nb_rxq,
226 : : uint32_t *flowkey_cfg, uint64_t *free_allocs, uint16_t rss_repte_pf_func,
227 : : int *act_cnt)
228 : : {
229 : : struct roc_npc_action_rss *rss_conf;
230 : 0 : int i = *act_cnt, j = 0, l, rc = 0;
231 : : uint16_t *queue_arr;
232 : :
233 : 0 : rss_conf = plt_zmalloc(sizeof(struct roc_npc_action_rss), 0);
234 [ # # ]: 0 : if (!rss_conf) {
235 : 0 : plt_err("Failed to allocate memory for rss conf");
236 : : rc = -ENOMEM;
237 : 0 : goto fail;
238 : : }
239 : :
240 : : /* Add RSS action */
241 : 0 : rss_conf->queue_num = nb_rxq;
242 : 0 : queue_arr = calloc(1, rss_conf->queue_num * sizeof(uint16_t));
243 [ # # ]: 0 : if (!queue_arr) {
244 : 0 : plt_err("Failed to allocate memory for rss queue");
245 : : rc = -ENOMEM;
246 : 0 : goto free_rss;
247 : : }
248 : :
249 [ # # ]: 0 : for (l = 0; l < nb_rxq; l++)
250 : 0 : queue_arr[l] = l;
251 : 0 : rss_conf->queue = queue_arr;
252 : 0 : rss_conf->key = NULL;
253 : 0 : rss_conf->types = RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP;
254 : :
255 : 0 : i++;
256 : :
257 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
258 : 0 : in_actions[i].conf = (struct roc_npc_action_rss *)rss_conf;
259 : 0 : in_actions[i].rss_repte_pf_func = rss_repte_pf_func;
260 : :
261 : : npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg,
262 : : RTE_ETH_RSS_IP | RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP);
263 : :
264 : 0 : *act_cnt = i;
265 : :
266 [ # # ]: 0 : while (free_allocs[j] != 0)
267 : 0 : j++;
268 : 0 : free_allocs[j] = (uint64_t)rss_conf;
269 : :
270 : 0 : return 0;
271 : : free_rss:
272 : 0 : rte_free(rss_conf);
273 : : fail:
274 : : return rc;
275 : : }
276 : :
277 : : static int
278 [ # # ]: 0 : representor_rep_portid_action(struct roc_npc_action *in_actions, struct rte_eth_dev *eth_dev,
279 : : struct rte_eth_dev *portid_eth_dev,
280 : : enum rte_flow_action_type act_type, uint8_t rep_pattern,
281 : : uint16_t *dst_pf_func, bool is_rep, uint8_t has_tunnel_pattern,
282 : : uint64_t *free_allocs, int *act_cnt, uint32_t *flowkey_cfg)
283 : : {
284 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
285 : : struct rte_eth_dev *rep_eth_dev = portid_eth_dev;
286 : : struct rte_flow_action_of_set_vlan_vid *vlan_vid;
287 : : struct rte_flow_action_of_set_vlan_pcp *vlan_pcp;
288 : : struct rte_flow_action_of_push_vlan *push_vlan;
289 : : struct rte_flow_action_queue *act_q = NULL;
290 : : struct cnxk_rep_dev *rep_dev;
291 : : struct roc_npc *npc;
292 : : uint16_t vlan_tci;
293 : : int j = 0, rc;
294 : :
295 : : /* For inserting an action in the list */
296 [ # # ]: 0 : int i = *act_cnt;
297 : :
298 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
299 [ # # ]: 0 : if (!is_rep) {
300 : : dev = cnxk_eth_pmd_priv(eth_dev);
301 : 0 : npc = &dev->npc;
302 : : } else {
303 : 0 : npc = &rep_dev->parent_dev->npc;
304 : : }
305 [ # # ]: 0 : if (rep_pattern >> IS_REP_BIT) { /* Check for normal/representor port as action */
306 [ # # ]: 0 : if ((rep_pattern & 0x7f) == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
307 : : /* Case: Repr port pattern -> Default TX rule -> LBK ->
308 : : * Pattern RX LBK rule hit -> Action: send to new pf_func
309 : : */
310 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) {
311 : : /* New pf_func corresponds to ESW + queue corresponding to rep_id */
312 : 0 : act_q = plt_zmalloc(sizeof(struct rte_flow_action_queue), 0);
313 [ # # ]: 0 : if (!act_q) {
314 : 0 : plt_err("Error allocation memory");
315 : 0 : return -ENOMEM;
316 : : }
317 : 0 : act_q->index = rep_dev->rep_id;
318 : :
319 [ # # ]: 0 : while (free_allocs[j] != 0)
320 : 0 : j++;
321 : 0 : free_allocs[j] = (uint64_t)act_q;
322 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
323 : 0 : in_actions[i].conf = (struct rte_flow_action_queue *)act_q;
324 : 0 : npc->rep_act_pf_func = rep_dev->parent_dev->npc.pf_func;
325 : : } else {
326 : : /* New pf_func corresponds to hw_func of representee */
327 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
328 : 0 : npc->rep_act_pf_func = rep_dev->hw_func;
329 : 0 : *dst_pf_func = rep_dev->hw_func;
330 : : }
331 : : /* Additional action to strip the VLAN from packets received by LBK */
332 : 0 : i++;
333 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
334 : 0 : goto done;
335 : : }
336 : : /* Case: Repd port pattern -> TX Rule with VLAN -> LBK -> Default RX LBK rule hit
337 : : * base on vlan, if packet goes to ESW or actual pf_func -> Action :
338 : : * act port_representor: send to ESW respective using 1<<8 | rep_id as tci value
339 : : * act represented_port: send to actual port using rep_id as tci value.
340 : : */
341 : : /* Add RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN action */
342 : 0 : push_vlan = plt_zmalloc(sizeof(struct rte_flow_action_of_push_vlan), 0);
343 [ # # ]: 0 : if (!push_vlan) {
344 : 0 : plt_err("Error allocation memory");
345 : 0 : return -ENOMEM;
346 : : }
347 : :
348 [ # # ]: 0 : while (free_allocs[j] != 0)
349 : 0 : j++;
350 : 0 : free_allocs[j] = (uint64_t)push_vlan;
351 : 0 : push_vlan->ethertype = ntohs(ROC_ESWITCH_VLAN_TPID);
352 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
353 : 0 : in_actions[i].conf = (struct rte_flow_action_of_push_vlan *)push_vlan;
354 : 0 : i++;
355 : :
356 : : /* Add RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP action */
357 : 0 : vlan_pcp = plt_zmalloc(sizeof(struct rte_flow_action_of_set_vlan_pcp), 0);
358 [ # # ]: 0 : if (!vlan_pcp) {
359 : 0 : plt_err("Error allocation memory");
360 : 0 : return -ENOMEM;
361 : : }
362 : :
363 : 0 : free_allocs[j + 1] = (uint64_t)vlan_pcp;
364 : 0 : vlan_pcp->vlan_pcp = 0;
365 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
366 : 0 : in_actions[i].conf = (struct rte_flow_action_of_set_vlan_pcp *)vlan_pcp;
367 : 0 : i++;
368 : :
369 : : /* Add RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID action */
370 : 0 : vlan_vid = plt_zmalloc(sizeof(struct rte_flow_action_of_set_vlan_vid), 0);
371 [ # # ]: 0 : if (!vlan_vid) {
372 : 0 : plt_err("Error allocation memory");
373 : 0 : return -ENOMEM;
374 : : }
375 : :
376 : 0 : free_allocs[j + 2] = (uint64_t)vlan_vid;
377 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR)
378 : 0 : vlan_tci = rep_dev->rep_id | (1ULL << CNXK_ESWITCH_VFPF_SHIFT);
379 : : else
380 : 0 : vlan_tci = rep_dev->rep_id;
381 : 0 : vlan_vid->vlan_vid = ntohs(vlan_tci);
382 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
383 : 0 : in_actions[i].conf = (struct rte_flow_action_of_set_vlan_vid *)vlan_vid;
384 : :
385 : : /* Change default channel to UCAST_CHAN (63) while sending */
386 : 0 : npc->rep_act_rep = true;
387 : : } else {
388 [ # # ]: 0 : if (act_type == RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR) {
389 : : /* Case: Pattern wire port -> Pattern RX rule->
390 : : * Action: pf_func = ESW. queue = rep_id
391 : : */
392 : 0 : act_q = plt_zmalloc(sizeof(struct rte_flow_action_queue), 0);
393 [ # # ]: 0 : if (!act_q) {
394 : 0 : plt_err("Error allocation memory");
395 : 0 : return -ENOMEM;
396 : : }
397 [ # # ]: 0 : while (free_allocs[j] != 0)
398 : 0 : j++;
399 : 0 : free_allocs[j] = (uint64_t)act_q;
400 : 0 : act_q->index = rep_dev->rep_id;
401 : :
402 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
403 : 0 : in_actions[i].conf = (struct rte_flow_action_queue *)act_q;
404 : 0 : npc->rep_act_pf_func = rep_dev->parent_dev->npc.pf_func;
405 : : } else {
406 : : /* Case: Pattern wire port -> Pattern RX rule->
407 : : * Action: Receive at actual hw_func
408 : : */
409 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
410 : 0 : npc->rep_act_pf_func = rep_dev->hw_func;
411 : 0 : *dst_pf_func = rep_dev->hw_func;
412 : :
413 : : /* Append a mark action - needed to identify the flow */
414 : 0 : rc = append_mark_action(in_actions, has_tunnel_pattern, free_allocs, &i);
415 [ # # ]: 0 : if (rc)
416 : : return rc;
417 : : /* Append RSS action if representee has RSS enabled */
418 [ # # ]: 0 : if (rep_dev->nb_rxq > 1) {
419 : : /* PF can install rule for only its VF acting as representee */
420 [ # # # # ]: 0 : if (rep_dev->hw_func &&
421 : 0 : roc_eswitch_is_repte_pfs_vf(rep_dev->hw_func,
422 : 0 : roc_nix_get_pf_func(npc->roc_nix))) {
423 : 0 : rc = append_rss_action(dev, in_actions, rep_dev->nb_rxq,
424 : : flowkey_cfg, free_allocs,
425 : 0 : rep_dev->hw_func, &i);
426 [ # # ]: 0 : if (rc)
427 : : return rc;
428 : : }
429 : : }
430 : : }
431 : : }
432 : 0 : done:
433 : 0 : *act_cnt = i;
434 : :
435 : 0 : return 0;
436 : : }
437 : :
438 : : static int
439 : 0 : representor_portid_action(struct roc_npc_action *in_actions, struct rte_eth_dev *portid_eth_dev,
440 : : uint16_t *dst_pf_func, uint8_t has_tunnel_pattern, uint64_t *free_allocs,
441 : : int *act_cnt)
442 : : {
443 : : struct rte_eth_dev *rep_eth_dev = portid_eth_dev;
444 : : struct cnxk_rep_dev *rep_dev;
445 : : /* For inserting an action in the list */
446 : 0 : int i = *act_cnt, rc;
447 : :
448 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
449 : :
450 : 0 : *dst_pf_func = rep_dev->hw_func;
451 : :
452 : 0 : rc = append_mark_action(in_actions, has_tunnel_pattern, free_allocs, &i);
453 [ # # ]: 0 : if (rc)
454 : : return rc;
455 : :
456 : 0 : *act_cnt = i;
457 : 0 : plt_rep_dbg("Rep port %d ID %d rep_dev->hw_func 0x%x", rep_dev->port_id, rep_dev->rep_id,
458 : : rep_dev->hw_func);
459 : :
460 : 0 : return 0;
461 : : }
462 : :
463 : : static int
464 : 0 : cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
465 : : const struct rte_flow_action actions[], struct roc_npc_action in_actions[],
466 : : struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
467 : : uint16_t *dst_pf_func, uint64_t *npc_default_action, uint8_t has_tunnel_pattern,
468 : : bool is_rep, uint8_t rep_pattern, uint64_t *free_allocs, uint32_t flow_flags)
469 : : {
470 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
471 : : const struct rte_flow_action_queue *act_q = NULL;
472 : : const struct rte_flow_action_ethdev *act_ethdev;
473 : : const struct rte_flow_action_sample *act_sample;
474 : : const struct rte_flow_action_port_id *port_act;
475 : : struct rte_eth_dev *portid_eth_dev;
476 : : char if_name[RTE_ETH_NAME_MAX_LEN];
477 : : struct cnxk_eth_dev *hw_dst;
478 : : struct roc_npc *roc_npc_dst;
479 : : bool is_vf_action = false;
480 : 0 : int i = 0, rc = 0;
481 : : int rq;
482 : :
483 [ # # ]: 0 : for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
484 [ # # # # : 0 : switch (actions->type) {
# # # # #
# # # # #
# # # # #
# # ]
485 : 0 : case RTE_FLOW_ACTION_TYPE_VOID:
486 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VOID;
487 : 0 : break;
488 : :
489 : 0 : case RTE_FLOW_ACTION_TYPE_MARK:
490 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_MARK;
491 : 0 : in_actions[i].conf = actions->conf;
492 : 0 : break;
493 : :
494 : 0 : case RTE_FLOW_ACTION_TYPE_FLAG:
495 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_FLAG;
496 : 0 : break;
497 : :
498 : 0 : case RTE_FLOW_ACTION_TYPE_COUNT:
499 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_COUNT;
500 : 0 : break;
501 : :
502 : 0 : case RTE_FLOW_ACTION_TYPE_DROP:
503 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_DROP;
504 : 0 : break;
505 : :
506 : 0 : case RTE_FLOW_ACTION_TYPE_PF:
507 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PF;
508 : 0 : break;
509 : :
510 : 0 : case RTE_FLOW_ACTION_TYPE_VF:
511 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VF;
512 : 0 : in_actions[i].conf = actions->conf;
513 : : is_vf_action = true;
514 : 0 : break;
515 : :
516 : 0 : case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
517 : : case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
518 : 0 : in_actions[i].conf = actions->conf;
519 : : act_ethdev = (const struct rte_flow_action_ethdev *)actions->conf;
520 [ # # ]: 0 : if (rte_eth_dev_get_name_by_port(act_ethdev->port_id, if_name)) {
521 : 0 : plt_err("Name not found for output port id");
522 : 0 : goto err_exit;
523 : : }
524 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
525 [ # # ]: 0 : if (!portid_eth_dev) {
526 : 0 : plt_err("eth_dev not found for output port id");
527 : 0 : goto err_exit;
528 : : }
529 : :
530 : 0 : plt_rep_dbg("Rule installed by port %d if_name %s act_ethdev->port_id %d",
531 : : eth_dev->data->port_id, if_name, act_ethdev->port_id);
532 [ # # ]: 0 : if (cnxk_ethdev_is_representor(if_name)) {
533 [ # # ]: 0 : if (representor_rep_portid_action(in_actions, eth_dev,
534 : 0 : portid_eth_dev, actions->type,
535 : : rep_pattern, dst_pf_func,
536 : : is_rep, has_tunnel_pattern,
537 : : free_allocs, &i, flowkey_cfg)) {
538 : 0 : plt_err("Representor port action set failed");
539 : 0 : goto err_exit;
540 : : }
541 : : } else {
542 [ # # ]: 0 : if (actions->type == RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT)
543 : 0 : continue;
544 : : /* Normal port as represented_port as action not supported*/
545 : : return -ENOTSUP;
546 : : }
547 : : break;
548 : 0 : case RTE_FLOW_ACTION_TYPE_PORT_ID:
549 : : /* No port ID action on representor ethdevs */
550 [ # # ]: 0 : if (is_rep)
551 : 0 : continue;
552 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_PORT_ID;
553 : 0 : in_actions[i].conf = actions->conf;
554 : : act_ethdev = (const struct rte_flow_action_ethdev *)actions->conf;
555 : : port_act = (const struct rte_flow_action_port_id *)actions->conf;
556 [ # # ]: 0 : if (rte_eth_dev_get_name_by_port(
557 : : actions->type != RTE_FLOW_ACTION_TYPE_PORT_ID ?
558 : : act_ethdev->port_id :
559 : 0 : port_act->id,
560 : : if_name)) {
561 : 0 : plt_err("Name not found for output port id");
562 : 0 : goto err_exit;
563 : : }
564 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
565 [ # # ]: 0 : if (!portid_eth_dev) {
566 : 0 : plt_err("eth_dev not found for output port id");
567 : 0 : goto err_exit;
568 : : }
569 : :
570 [ # # ]: 0 : if (cnxk_ethdev_is_representor(if_name)) {
571 : 0 : plt_rep_dbg("Representor port %d act port %d", port_act->id,
572 : : act_ethdev->port_id);
573 [ # # ]: 0 : if (representor_portid_action(in_actions, portid_eth_dev,
574 : : dst_pf_func, has_tunnel_pattern,
575 : : free_allocs, &i)) {
576 : 0 : plt_err("Representor port action set failed");
577 : 0 : goto err_exit;
578 : : }
579 : : } else {
580 : 0 : if (strcmp(portid_eth_dev->device->driver->name,
581 [ # # ]: 0 : eth_dev->device->driver->name) != 0) {
582 : 0 : plt_err("Output port not under same driver");
583 : 0 : goto err_exit;
584 : : }
585 : :
586 : 0 : hw_dst = portid_eth_dev->data->dev_private;
587 : 0 : roc_npc_mcam_default_rule_action_get(&hw_dst->npc,
588 : : npc_default_action);
589 : : roc_npc_dst = &hw_dst->npc;
590 : 0 : *dst_pf_func = roc_npc_dst->pf_func;
591 : : }
592 : : break;
593 : :
594 : 0 : case RTE_FLOW_ACTION_TYPE_QUEUE:
595 : 0 : act_q = (const struct rte_flow_action_queue *)actions->conf;
596 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_QUEUE;
597 : 0 : in_actions[i].conf = actions->conf;
598 : 0 : break;
599 : :
600 : 0 : case RTE_FLOW_ACTION_TYPE_RSS:
601 : : /* No RSS action on representor ethdevs */
602 [ # # ]: 0 : if (is_rep)
603 : 0 : continue;
604 : 0 : rc = npc_rss_action_validate(eth_dev, attr, actions);
605 [ # # ]: 0 : if (rc)
606 : 0 : goto err_exit;
607 : :
608 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
609 : 0 : in_actions[i].conf = actions->conf;
610 : 0 : npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg,
611 [ # # ]: 0 : eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf);
612 : : break;
613 : :
614 : 0 : case RTE_FLOW_ACTION_TYPE_SECURITY:
615 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
616 : 0 : in_actions[i].conf = actions->conf;
617 : 0 : in_actions[i].is_non_inp = flow_flags & CNXK_FLOW_NON_INPLACE;
618 : 0 : in_actions[i].no_sec_action = flow_flags & CNXK_FLOW_NO_SEC_ACTION;
619 : 0 : break;
620 : 0 : case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
621 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
622 : 0 : break;
623 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
624 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
625 : 0 : in_actions[i].conf = actions->conf;
626 : 0 : break;
627 : 0 : case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
628 : 0 : in_actions[i].type =
629 : : ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
630 : 0 : in_actions[i].conf = actions->conf;
631 : 0 : break;
632 : 0 : case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
633 : 0 : in_actions[i].type =
634 : : ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
635 : 0 : in_actions[i].conf = actions->conf;
636 : 0 : break;
637 : 0 : case RTE_FLOW_ACTION_TYPE_METER:
638 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_METER;
639 : 0 : in_actions[i].conf = actions->conf;
640 : 0 : break;
641 : 0 : case RTE_FLOW_ACTION_TYPE_AGE:
642 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE;
643 : 0 : in_actions[i].conf = actions->conf;
644 : 0 : break;
645 : 0 : case RTE_FLOW_ACTION_TYPE_SAMPLE:
646 : 0 : act_sample = actions->conf;
647 : 0 : in_sample_actions->ratio = act_sample->ratio;
648 : 0 : rc = roc_npc_parse_sample_subaction(eth_dev, act_sample->actions,
649 : : in_sample_actions);
650 [ # # ]: 0 : if (rc) {
651 : 0 : plt_err("Sample subaction parsing failed.");
652 : 0 : goto err_exit;
653 : : }
654 : :
655 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_SAMPLE;
656 : 0 : in_actions[i].conf = in_sample_actions;
657 : 0 : break;
658 : 0 : case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
659 : 0 : continue;
660 : 0 : default:
661 : 0 : plt_npc_dbg("Action is not supported = %d", actions->type);
662 : 0 : goto err_exit;
663 : : }
664 : 0 : i++;
665 : : }
666 : :
667 [ # # ]: 0 : if (!is_vf_action && act_q) {
668 : 0 : rq = act_q->index;
669 [ # # ]: 0 : if (rq >= eth_dev->data->nb_rx_queues) {
670 : 0 : plt_npc_dbg("Invalid queue index");
671 : 0 : goto err_exit;
672 : : }
673 : : }
674 : 0 : in_actions[i].type = ROC_NPC_ACTION_TYPE_END;
675 : 0 : return 0;
676 : :
677 : : err_exit:
678 : : return -EINVAL;
679 : : }
680 : :
681 : : static int
682 : 0 : cnxk_map_pattern(struct rte_eth_dev *eth_dev, const struct rte_flow_item pattern[],
683 : : struct roc_npc_item_info in_pattern[], uint8_t *has_tunnel_pattern, bool is_rep,
684 : : uint8_t *rep_pattern, uint64_t *free_allocs)
685 : : {
686 : : const struct rte_flow_item_ethdev *rep_eth_dev;
687 : : struct rte_eth_dev *portid_eth_dev;
688 : : char if_name[RTE_ETH_NAME_MAX_LEN];
689 : : struct cnxk_eth_dev *hw_dst;
690 : : struct cnxk_rep_dev *rdev;
691 : : struct cnxk_eth_dev *dev;
692 : : struct roc_npc *npc;
693 : : int i = 0, j = 0;
694 : :
695 [ # # ]: 0 : if (!is_rep) {
696 : : dev = cnxk_eth_pmd_priv(eth_dev);
697 : 0 : npc = &dev->npc;
698 : : } else {
699 : : rdev = cnxk_rep_pmd_priv(eth_dev);
700 : 0 : npc = &rdev->parent_dev->npc;
701 : :
702 : 0 : npc->rep_npc = npc;
703 : 0 : npc->rep_port_id = rdev->port_id;
704 : 0 : npc->rep_pf_func = rdev->hw_func;
705 : : }
706 : :
707 [ # # ]: 0 : while (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
708 : 0 : in_pattern[i].spec = pattern->spec;
709 : 0 : in_pattern[i].last = pattern->last;
710 : 0 : in_pattern[i].mask = pattern->mask;
711 : 0 : in_pattern[i].type = term[pattern->type].item_type;
712 : 0 : in_pattern[i].size = term[pattern->type].item_size;
713 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT ||
714 : : pattern->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
715 : : rep_eth_dev = (const struct rte_flow_item_ethdev *)pattern->spec;
716 [ # # ]: 0 : if (rte_eth_dev_get_name_by_port(rep_eth_dev->port_id, if_name)) {
717 : 0 : plt_err("Name not found for output port id");
718 : 0 : goto fail;
719 : : }
720 : 0 : portid_eth_dev = rte_eth_dev_allocated(if_name);
721 [ # # ]: 0 : if (!portid_eth_dev) {
722 : 0 : plt_err("eth_dev not found for output port id");
723 : 0 : goto fail;
724 : : }
725 : 0 : *rep_pattern = pattern->type;
726 [ # # ]: 0 : if (cnxk_ethdev_is_representor(if_name)) {
727 : : /* Case where represented port not part of same
728 : : * app and represented by a representor port.
729 : : */
730 : : struct cnxk_rep_dev *rep_dev;
731 : : struct cnxk_eswitch_dev *eswitch_dev;
732 : :
733 : : rep_dev = cnxk_rep_pmd_priv(portid_eth_dev);
734 : 0 : eswitch_dev = rep_dev->parent_dev;
735 : 0 : npc->rep_npc = &eswitch_dev->npc;
736 : 0 : npc->rep_port_id = rep_eth_dev->port_id;
737 : 0 : npc->rep_pf_func = rep_dev->hw_func;
738 : :
739 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
740 : : struct rte_flow_item_vlan *vlan;
741 : :
742 : 0 : npc->rep_pf_func = eswitch_dev->npc.pf_func;
743 : : /* Add VLAN pattern corresponding to rep_id */
744 : 0 : i++;
745 : 0 : vlan = plt_zmalloc(sizeof(struct rte_flow_item_vlan), 0);
746 [ # # ]: 0 : if (!vlan) {
747 : 0 : plt_err("error allocation memory");
748 : 0 : return -ENOMEM;
749 : : }
750 : :
751 [ # # ]: 0 : while (free_allocs[j] != 0)
752 : 0 : j++;
753 : 0 : free_allocs[j] = (uint64_t)vlan;
754 : :
755 : 0 : npc->rep_rx_channel = ROC_ESWITCH_LBK_CHAN;
756 : 0 : vlan->hdr.vlan_tci = RTE_BE16(rep_dev->rep_id);
757 : 0 : in_pattern[i].spec = (struct rte_flow_item_vlan *)vlan;
758 : 0 : in_pattern[i].last = NULL;
759 : 0 : in_pattern[i].mask = &rte_flow_item_vlan_mask;
760 : 0 : in_pattern[i].type =
761 : : term[RTE_FLOW_ITEM_TYPE_VLAN].item_type;
762 : 0 : in_pattern[i].size =
763 : : term[RTE_FLOW_ITEM_TYPE_VLAN].item_size;
764 : : }
765 : 0 : *rep_pattern |= 1 << IS_REP_BIT;
766 : 0 : plt_rep_dbg("Represented port %d act port %d rep_dev->hw_func 0x%x",
767 : : rep_eth_dev->port_id, eth_dev->data->port_id,
768 : : rep_dev->hw_func);
769 : : } else {
770 : 0 : if (strcmp(portid_eth_dev->device->driver->name,
771 [ # # ]: 0 : eth_dev->device->driver->name) != 0) {
772 : 0 : plt_err("Output port not under same driver");
773 : 0 : goto fail;
774 : : }
775 : : /* Normal port as port_representor pattern can't be supported */
776 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR)
777 : : return -ENOTSUP;
778 : : /* Case where represented port part of same app
779 : : * as PF.
780 : : */
781 : 0 : hw_dst = portid_eth_dev->data->dev_private;
782 : 0 : npc->rep_npc = &hw_dst->npc;
783 : 0 : npc->rep_port_id = rep_eth_dev->port_id;
784 : 0 : npc->rep_pf_func = hw_dst->npc.pf_func;
785 : : }
786 : : }
787 : :
788 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
789 [ # # ]: 0 : pattern->type == RTE_FLOW_ITEM_TYPE_VXLAN_GPE ||
790 : : pattern->type == RTE_FLOW_ITEM_TYPE_GRE)
791 : 0 : *has_tunnel_pattern = pattern->type;
792 : :
793 : 0 : pattern++;
794 : 0 : i++;
795 : : }
796 : 0 : in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
797 : 0 : return 0;
798 : : fail:
799 : : return -EINVAL;
800 : : }
801 : :
802 : : static int
803 : 0 : cnxk_map_flow_data(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
804 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
805 : : struct roc_npc_attr *in_attr, struct roc_npc_item_info in_pattern[],
806 : : struct roc_npc_action in_actions[],
807 : : struct roc_npc_action_sample *in_sample_actions, uint32_t *flowkey_cfg,
808 : : uint16_t *dst_pf_func, uint64_t *def_action, bool is_rep, uint64_t *free_allocs,
809 : : uint32_t flow_flags)
810 : : {
811 : 0 : uint8_t has_tunnel_pattern = 0, rep_pattern = 0;
812 : : int rc;
813 : :
814 : 0 : in_attr->priority = attr->priority;
815 : 0 : in_attr->ingress = attr->ingress;
816 : 0 : in_attr->egress = attr->egress;
817 : :
818 : 0 : rc = cnxk_map_pattern(eth_dev, pattern, in_pattern, &has_tunnel_pattern, is_rep,
819 : : &rep_pattern, free_allocs);
820 [ # # ]: 0 : if (rc) {
821 : 0 : plt_err("Failed to map pattern list");
822 : 0 : return rc;
823 : : }
824 : :
825 [ # # ]: 0 : if (attr->transfer) {
826 : : /* rep_pattern is used to identify if RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT
827 : : * OR RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR is defined + if pattern's portid is
828 : : * normal port or representor port.
829 : : * For normal port_id, rep_pattern = pattern-> type
830 : : * For representor port, rep_pattern = pattern-> type | 1 << IS_REP_BIT
831 : : */
832 [ # # # # ]: 0 : if (is_rep || rep_pattern) {
833 [ # # # # ]: 0 : if (rep_pattern == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT ||
834 : : ((rep_pattern & 0x7f) == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR))
835 : : /* If pattern is port_representor or pattern has normal port as
836 : : * represented port, install ingress rule.
837 : : */
838 : 0 : in_attr->ingress = attr->transfer;
839 : : else
840 : 0 : in_attr->egress = attr->transfer;
841 : : } else {
842 : 0 : in_attr->ingress = attr->transfer;
843 : : }
844 : : }
845 : :
846 : 0 : return cnxk_map_actions(eth_dev, attr, actions, in_actions, in_sample_actions, flowkey_cfg,
847 : : dst_pf_func, def_action, has_tunnel_pattern, is_rep, rep_pattern,
848 : : free_allocs, flow_flags);
849 : : }
850 : :
851 : : int
852 : 0 : cnxk_flow_validate_common(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
853 : : const struct rte_flow_item pattern[],
854 : : const struct rte_flow_action actions[], struct rte_flow_error *error,
855 : : bool is_rep, uint32_t flow_flags)
856 : : {
857 : : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1];
858 : : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT];
859 : : struct roc_npc_action_sample in_sample_action;
860 : 0 : uint64_t npc_default_action = 0;
861 : : struct cnxk_rep_dev *rep_dev;
862 : : struct roc_npc_attr in_attr;
863 : : uint64_t *free_allocs, sz;
864 : : struct cnxk_eth_dev *dev;
865 : : struct roc_npc_flow flow;
866 : 0 : uint16_t dst_pf_func = 0;
867 : 0 : uint32_t flowkey_cfg = 0;
868 : : struct roc_npc *npc = 0;
869 : : int rc, j;
870 : :
871 : : /* is_rep set for operation performed via representor ports */
872 [ # # ]: 0 : if (!is_rep) {
873 : : dev = cnxk_eth_pmd_priv(eth_dev);
874 : 0 : npc = &dev->npc;
875 : : /* Skip flow validation for MACsec. */
876 [ # # # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
877 : 0 : cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL)
878 : : return 0;
879 : : } else {
880 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
881 : 0 : npc = &rep_dev->parent_dev->npc;
882 : : }
883 : :
884 : : memset(&flow, 0, sizeof(flow));
885 : : memset(&in_sample_action, 0, sizeof(in_sample_action));
886 : 0 : flow.is_validate = true;
887 : :
888 : : sz = ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1;
889 : 0 : free_allocs = plt_zmalloc(sz * sizeof(uint64_t), 0);
890 [ # # ]: 0 : if (!free_allocs) {
891 : 0 : rte_flow_error_set(error, -ENOMEM, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
892 : : "Failed to map flow data");
893 : 0 : return -ENOMEM;
894 : : }
895 : 0 : rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
896 : : &in_sample_action, &flowkey_cfg, &dst_pf_func, &npc_default_action,
897 : : is_rep, free_allocs, flow_flags);
898 [ # # ]: 0 : if (rc) {
899 : 0 : rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
900 : : "Failed to map flow data");
901 : 0 : goto clean;
902 : : }
903 : :
904 : 0 : rc = roc_npc_flow_parse(npc, &in_attr, in_pattern, in_actions, &flow);
905 : :
906 [ # # ]: 0 : if (rc) {
907 : 0 : rte_flow_error_set(error, 0, rc, NULL,
908 : : "Flow validation failed");
909 : 0 : goto clean;
910 : : }
911 : 0 : clean:
912 : : /* Freeing the allocations done for additional patterns/actions */
913 [ # # # # ]: 0 : for (j = 0; (j < (int)sz) && free_allocs[j]; j++)
914 : 0 : plt_free((void *)free_allocs[j]);
915 : 0 : plt_free(free_allocs);
916 : :
917 : 0 : return rc;
918 : : }
919 : :
920 : : static int
921 [ # # ]: 0 : cnxk_flow_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
922 : : const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
923 : : struct rte_flow_error *error)
924 : : {
925 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
926 : : struct cnxk_eth_sec_sess *eth_sec = NULL;
927 : : uint32_t flow_flags = 0;
928 : :
929 [ # # ]: 0 : if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY) {
930 : 0 : eth_sec = cnxk_eth_sec_sess_get_by_sess(dev, actions[0].conf);
931 [ # # ]: 0 : if (eth_sec != NULL) {
932 [ # # ]: 0 : flow_flags = eth_sec->inb_oop ? CNXK_FLOW_NON_INPLACE : 0;
933 : 0 : flow_flags |= CNXK_FLOW_NO_SEC_ACTION;
934 : : }
935 : : }
936 : :
937 : 0 : return cnxk_flow_validate_common(eth_dev, attr, pattern, actions, error, false, flow_flags);
938 : : }
939 : :
940 : : struct roc_npc_flow *
941 : 0 : cnxk_flow_create_common(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
942 : : const struct rte_flow_item pattern[],
943 : : const struct rte_flow_action actions[], struct rte_flow_error *error,
944 : : bool is_rep, uint32_t flow_flags)
945 : : {
946 : 0 : struct roc_npc_item_info in_pattern[ROC_NPC_ITEM_TYPE_END + 1] = {0};
947 : 0 : struct roc_npc_action in_actions[ROC_NPC_MAX_ACTION_COUNT] = {0};
948 : : struct roc_npc_action_sample in_sample_action;
949 : : struct cnxk_rep_dev *rep_dev = NULL;
950 : : struct roc_npc_flow *flow = NULL;
951 : : struct cnxk_eth_dev *dev = NULL;
952 : 0 : uint64_t npc_default_action = 0;
953 : : struct roc_npc_attr in_attr;
954 : : struct roc_npc *npc = NULL;
955 : : uint64_t *free_allocs, sz;
956 : 0 : uint16_t dst_pf_func = 0;
957 : 0 : int errcode = 0;
958 : : int rc, j;
959 : :
960 : : /* is_rep set for operation performed via representor ports */
961 [ # # ]: 0 : if (!is_rep) {
962 : : dev = cnxk_eth_pmd_priv(eth_dev);
963 : 0 : npc = &dev->npc;
964 : : } else {
965 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
966 : 0 : npc = &rep_dev->parent_dev->npc;
967 : : }
968 : :
969 : : sz = ROC_NPC_MAX_ACTION_COUNT + ROC_NPC_ITEM_TYPE_END + 1;
970 : 0 : free_allocs = plt_zmalloc(sz * sizeof(uint64_t), 0);
971 [ # # ]: 0 : if (!free_allocs) {
972 : 0 : rte_flow_error_set(error, -ENOMEM, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
973 : : "Failed to map flow data");
974 : 0 : return NULL;
975 : : }
976 : : memset(&in_sample_action, 0, sizeof(in_sample_action));
977 : : memset(&in_attr, 0, sizeof(struct roc_npc_attr));
978 : 0 : rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr, in_pattern, in_actions,
979 : : &in_sample_action, &npc->flowkey_cfg_state, &dst_pf_func,
980 : : &npc_default_action, is_rep, free_allocs, flow_flags);
981 [ # # ]: 0 : if (rc) {
982 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
983 : : "Failed to map flow data");
984 : 0 : goto clean;
985 : : }
986 : :
987 : 0 : flow = roc_npc_flow_create(npc, &in_attr, in_pattern, in_actions, dst_pf_func,
988 : : npc_default_action, &errcode);
989 [ # # ]: 0 : if (errcode != 0) {
990 : 0 : rte_flow_error_set(error, errcode, errcode, NULL, roc_error_msg_get(errcode));
991 : 0 : goto clean;
992 : : }
993 : :
994 : 0 : clean:
995 : : /* Freeing the allocations done for additional patterns/actions */
996 [ # # # # ]: 0 : for (j = 0; (j < (int)sz) && free_allocs[j]; j++)
997 : 0 : plt_free((void *)free_allocs[j]);
998 : 0 : plt_free(free_allocs);
999 : :
1000 : 0 : return flow;
1001 : : }
1002 : :
1003 : : int
1004 : 0 : cnxk_flow_destroy_common(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
1005 : : struct rte_flow_error *error, bool is_rep)
1006 : : {
1007 : : struct cnxk_rep_dev *rep_dev;
1008 : : struct cnxk_eth_dev *dev;
1009 : : struct roc_npc *npc;
1010 : : int rc;
1011 : :
1012 : : /* is_rep set for operation performed via representor ports */
1013 [ # # ]: 0 : if (!is_rep) {
1014 : : dev = cnxk_eth_pmd_priv(eth_dev);
1015 : 0 : npc = &dev->npc;
1016 : : } else {
1017 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1018 : 0 : npc = &rep_dev->parent_dev->npc;
1019 : : }
1020 : :
1021 : 0 : rc = roc_npc_flow_destroy(npc, flow);
1022 [ # # ]: 0 : if (rc)
1023 : 0 : rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1024 : : "Flow Destroy failed");
1025 : 0 : return rc;
1026 : : }
1027 : :
1028 : : int
1029 : 0 : cnxk_flow_destroy(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
1030 : : struct rte_flow_error *error)
1031 : : {
1032 : 0 : return cnxk_flow_destroy_common(eth_dev, flow, error, false);
1033 : : }
1034 : :
1035 : : int
1036 : 0 : cnxk_flow_flush_common(struct rte_eth_dev *eth_dev, struct rte_flow_error *error, bool is_rep)
1037 : : {
1038 : : struct cnxk_rep_dev *rep_dev;
1039 : : struct cnxk_eth_dev *dev;
1040 : : struct roc_npc *npc;
1041 : : int rc;
1042 : :
1043 : : /* is_rep set for operation performed via representor ports */
1044 [ # # ]: 0 : if (!is_rep) {
1045 : : dev = cnxk_eth_pmd_priv(eth_dev);
1046 : 0 : npc = &dev->npc;
1047 : : } else {
1048 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1049 : 0 : npc = &rep_dev->parent_dev->npc;
1050 : : }
1051 : :
1052 : 0 : rc = roc_npc_mcam_free_all_resources(npc);
1053 [ # # ]: 0 : if (rc) {
1054 : 0 : rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1055 : : "Failed to flush filter");
1056 : 0 : return -rte_errno;
1057 : : }
1058 : :
1059 : : return 0;
1060 : : }
1061 : :
1062 : : static int
1063 : 0 : cnxk_flow_flush(struct rte_eth_dev *eth_dev, struct rte_flow_error *error)
1064 : : {
1065 : 0 : return cnxk_flow_flush_common(eth_dev, error, false);
1066 : : }
1067 : :
1068 : : int
1069 : 0 : cnxk_flow_query_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
1070 : : const struct rte_flow_action *action, void *data,
1071 : : struct rte_flow_error *error, bool is_rep)
1072 : : {
1073 : : struct roc_npc_flow *in_flow = (struct roc_npc_flow *)flow;
1074 : : struct rte_flow_query_count *query = data;
1075 : : struct cnxk_rep_dev *rep_dev;
1076 : : struct cnxk_eth_dev *dev;
1077 : : struct roc_npc *npc;
1078 : : const char *errmsg = NULL;
1079 : : int errcode = ENOTSUP;
1080 : : int rc;
1081 : :
1082 [ # # ]: 0 : if (action->type != RTE_FLOW_ACTION_TYPE_COUNT) {
1083 : : errmsg = "Only COUNT is supported in query";
1084 : 0 : goto err_exit;
1085 : : }
1086 : :
1087 [ # # ]: 0 : if (in_flow->ctr_id == NPC_COUNTER_NONE) {
1088 : : errmsg = "Counter is not available";
1089 : 0 : goto err_exit;
1090 : : }
1091 : :
1092 : : /* is_rep set for operation performed via representor ports */
1093 [ # # ]: 0 : if (!is_rep) {
1094 : : dev = cnxk_eth_pmd_priv(eth_dev);
1095 : 0 : npc = &dev->npc;
1096 : : } else {
1097 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1098 : 0 : npc = &rep_dev->parent_dev->npc;
1099 : : }
1100 : :
1101 [ # # ]: 0 : if (in_flow->use_pre_alloc) {
1102 : 0 : rc = roc_npc_inl_mcam_read_counter(in_flow->ctr_id, &query->hits);
1103 : : } else {
1104 [ # # ]: 0 : if (roc_model_is_cn20k())
1105 : 0 : rc = roc_npc_mcam_get_stats(npc, in_flow, &query->hits);
1106 : : else
1107 : 0 : rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
1108 : : }
1109 [ # # ]: 0 : if (rc != 0) {
1110 : : errcode = EIO;
1111 : : errmsg = "Error reading flow counter";
1112 : 0 : goto err_exit;
1113 : : }
1114 : 0 : query->hits_set = 1;
1115 : 0 : query->bytes_set = 0;
1116 : :
1117 [ # # ]: 0 : if (query->reset) {
1118 [ # # ]: 0 : if (in_flow->use_pre_alloc)
1119 : 0 : rc = roc_npc_inl_mcam_clear_counter(in_flow->ctr_id);
1120 : : else
1121 : 0 : rc = roc_npc_mcam_clear_counter(npc, in_flow->ctr_id);
1122 : : }
1123 [ # # ]: 0 : if (rc != 0) {
1124 : : errcode = EIO;
1125 : : errmsg = "Error clearing flow counter";
1126 : 0 : goto err_exit;
1127 : : }
1128 : :
1129 : : return 0;
1130 : :
1131 : 0 : err_exit:
1132 : 0 : rte_flow_error_set(error, errcode, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1133 : : NULL, errmsg);
1134 : 0 : return -rte_errno;
1135 : : }
1136 : :
1137 : : static int
1138 : 0 : cnxk_flow_query(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
1139 : : const struct rte_flow_action *action, void *data, struct rte_flow_error *error)
1140 : : {
1141 : 0 : return cnxk_flow_query_common(eth_dev, flow, action, data, error, false);
1142 : : }
1143 : :
1144 : : static int
1145 : 0 : cnxk_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused, int enable __rte_unused,
1146 : : struct rte_flow_error *error)
1147 : : {
1148 : : /* If we support, we need to un-install the default mcam
1149 : : * entry for this port.
1150 : : */
1151 : :
1152 : 0 : rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1153 : : NULL, "Flow isolation not supported");
1154 : :
1155 : 0 : return -rte_errno;
1156 : : }
1157 : :
1158 : : int
1159 : 0 : cnxk_flow_dev_dump_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow, FILE *file,
1160 : : struct rte_flow_error *error, bool is_rep)
1161 : : {
1162 : : struct cnxk_rep_dev *rep_dev;
1163 : : struct cnxk_eth_dev *dev;
1164 : : struct roc_npc *npc;
1165 : :
1166 : : /* is_rep set for operation performed via representor ports */
1167 [ # # ]: 0 : if (!is_rep) {
1168 : : dev = cnxk_eth_pmd_priv(eth_dev);
1169 : 0 : npc = &dev->npc;
1170 : : } else {
1171 : : rep_dev = cnxk_rep_pmd_priv(eth_dev);
1172 : 0 : npc = &rep_dev->parent_dev->npc;
1173 : : }
1174 : :
1175 [ # # ]: 0 : if (file == NULL) {
1176 : 0 : rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1177 : : "Invalid file");
1178 : 0 : return -rte_errno;
1179 : : }
1180 : :
1181 [ # # ]: 0 : if (flow != NULL) {
1182 : 0 : roc_npc_flow_mcam_dump(file, npc, (struct roc_npc_flow *)flow);
1183 : 0 : return 0;
1184 : : }
1185 : :
1186 : 0 : roc_npc_flow_dump(file, npc, -1);
1187 : :
1188 : 0 : return 0;
1189 : : }
1190 : :
1191 : : static int
1192 : 0 : cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow, FILE *file,
1193 : : struct rte_flow_error *error)
1194 : : {
1195 : 0 : return cnxk_flow_dev_dump_common(eth_dev, flow, file, error, false);
1196 : : }
1197 : :
1198 : : static int
1199 [ # # ]: 0 : cnxk_flow_get_aged_flows(struct rte_eth_dev *eth_dev, void **context, uint32_t nb_contexts,
1200 : : struct rte_flow_error *err)
1201 : : {
1202 : : struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1203 : 0 : struct roc_npc *roc_npc = &dev->npc;
1204 : : struct roc_npc_flow_age *flow_age;
1205 : : uint32_t start_id;
1206 : : uint32_t end_id;
1207 : : int cnt = 0;
1208 : : uint32_t sn;
1209 : : uint32_t i;
1210 : :
1211 : : RTE_SET_USED(err);
1212 : :
1213 : : flow_age = &roc_npc->flow_age;
1214 : :
1215 [ # # ]: 0 : if (!flow_age->age_flow_refcnt)
1216 : : return 0;
1217 : :
1218 : : do {
1219 : : sn = plt_seqcount_read_begin(&flow_age->seq_cnt);
1220 : :
1221 [ # # ]: 0 : if (nb_contexts == 0) {
1222 : 0 : cnt = flow_age->aged_flows_cnt;
1223 : : } else {
1224 : 0 : start_id = flow_age->start_id;
1225 : 0 : end_id = flow_age->end_id;
1226 [ # # ]: 0 : for (i = start_id; i <= end_id; i++) {
1227 [ # # ]: 0 : if ((int)nb_contexts == cnt)
1228 : : break;
1229 [ # # ]: 0 : if (plt_bitmap_get(flow_age->aged_flows, i)) {
1230 : 0 : context[cnt] =
1231 : 0 : roc_npc_aged_flow_ctx_get(roc_npc, i);
1232 : 0 : cnt++;
1233 : : }
1234 : : }
1235 : : }
1236 [ # # ]: 0 : } while (plt_seqcount_read_retry(&flow_age->seq_cnt, sn));
1237 : :
1238 : : return cnt;
1239 : : }
1240 : :
1241 : : static int
1242 : 0 : cnxk_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev, struct rte_flow_tunnel *tunnel,
1243 : : struct rte_flow_action **pmd_actions, uint32_t *num_of_actions,
1244 : : __rte_unused struct rte_flow_error *err)
1245 : : {
1246 : : struct rte_flow_action *nfp_action;
1247 : :
1248 : 0 : nfp_action = rte_zmalloc("nfp_tun_action", sizeof(struct rte_flow_action), 0);
1249 [ # # ]: 0 : if (nfp_action == NULL) {
1250 : 0 : plt_err("Alloc memory for nfp tunnel action failed.");
1251 : 0 : return -ENOMEM;
1252 : : }
1253 : :
1254 [ # # ]: 0 : if (tunnel->is_ipv6)
1255 : 0 : nfp_action->conf = (void *)~0;
1256 : :
1257 [ # # ]: 0 : switch (tunnel->type) {
1258 : 0 : case RTE_FLOW_ITEM_TYPE_VXLAN:
1259 : 0 : nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
1260 : 0 : *pmd_actions = nfp_action;
1261 : 0 : *num_of_actions = 1;
1262 : 0 : break;
1263 : 0 : default:
1264 : 0 : *pmd_actions = NULL;
1265 : 0 : *num_of_actions = 0;
1266 : 0 : rte_free(nfp_action);
1267 : 0 : break;
1268 : : }
1269 : :
1270 : : return 0;
1271 : : }
1272 : :
1273 : : static int
1274 : 0 : cnxk_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
1275 : : struct rte_flow_action *pmd_actions, uint32_t num_of_actions,
1276 : : __rte_unused struct rte_flow_error *err)
1277 : : {
1278 : : uint32_t i;
1279 : : struct rte_flow_action *nfp_action;
1280 : :
1281 [ # # ]: 0 : for (i = 0; i < num_of_actions; i++) {
1282 : 0 : nfp_action = &pmd_actions[i];
1283 : 0 : nfp_action->conf = NULL;
1284 : 0 : rte_free(nfp_action);
1285 : : }
1286 : :
1287 : 0 : return 0;
1288 : : }
1289 : :
1290 : : static int
1291 : 0 : cnxk_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
1292 : : __rte_unused struct rte_flow_tunnel *tunnel,
1293 : : __rte_unused struct rte_flow_item **pmd_items, uint32_t *num_of_items,
1294 : : __rte_unused struct rte_flow_error *err)
1295 : : {
1296 : 0 : *num_of_items = 0;
1297 : :
1298 : 0 : return 0;
1299 : : }
1300 : :
1301 : : static int
1302 : 0 : cnxk_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
1303 : : __rte_unused struct rte_flow_item *pmd_items,
1304 : : __rte_unused uint32_t num_of_items,
1305 : : __rte_unused struct rte_flow_error *err)
1306 : : {
1307 : 0 : return 0;
1308 : : }
1309 : :
1310 : : struct rte_flow_ops cnxk_flow_ops = {
1311 : : .validate = cnxk_flow_validate,
1312 : : .flush = cnxk_flow_flush,
1313 : : .query = cnxk_flow_query,
1314 : : .isolate = cnxk_flow_isolate,
1315 : : .dev_dump = cnxk_flow_dev_dump,
1316 : : .get_aged_flows = cnxk_flow_get_aged_flows,
1317 : : .tunnel_match = cnxk_flow_tunnel_match,
1318 : : .tunnel_item_release = cnxk_flow_tunnel_item_release,
1319 : : .tunnel_decap_set = cnxk_flow_tunnel_decap_set,
1320 : : .tunnel_action_decap_release = cnxk_flow_tunnel_action_decap_release,
1321 : : };
|