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