Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2024 Marvell.
3 : : */
4 : :
5 : : #include <rte_thash.h>
6 : :
7 : : #include <cnxk_eswitch.h>
8 : :
9 : : const uint8_t eswitch_vlan_rss_key[ROC_NIX_RSS_KEY_LEN] = {
10 : : 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
11 : : 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
12 : : 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
13 : : 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
14 : : 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
15 : : 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE};
16 : :
17 : : int
18 : 0 : cnxk_eswitch_flow_rules_remove_list(struct cnxk_eswitch_dev *eswitch_dev, struct flow_list *list,
19 : : uint16_t hw_func)
20 : : {
21 : : struct roc_npc_flow *flow, *tvar;
22 : : int rc = 0;
23 : :
24 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(flow, list, next, tvar) {
25 : 0 : plt_esw_dbg("Removing flow %d", flow->mcam_id);
26 : 0 : rc = roc_eswitch_npc_mcam_delete_rule(&eswitch_dev->npc, flow,
27 : : hw_func);
28 [ # # ]: 0 : if (rc)
29 : 0 : plt_err("Failed to delete rule %d", flow->mcam_id);
30 : 0 : rc = roc_npc_mcam_free(&eswitch_dev->npc, flow);
31 [ # # ]: 0 : if (rc)
32 : 0 : plt_err("Failed to free entry %d", flow->mcam_id);
33 [ # # ]: 0 : TAILQ_REMOVE(list, flow, next);
34 : 0 : rte_free(flow);
35 : : }
36 : :
37 : 0 : return rc;
38 : : }
39 : :
40 : : static int
41 : 0 : eswitch_npc_vlan_rss_configure(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
42 : : {
43 : 0 : struct roc_nix *roc_nix = roc_npc->roc_nix;
44 : : uint32_t qid, idx, hash, vlan_tci;
45 : : uint16_t *reta, reta_sz, id;
46 : : int rc = 0;
47 : :
48 : 0 : id = flow->mcam_id;
49 : : /* Setting up the key */
50 : 0 : roc_nix_rss_key_set(roc_nix, eswitch_vlan_rss_key);
51 : :
52 : 0 : reta_sz = roc_nix->reta_sz;
53 : 0 : reta = plt_zmalloc(reta_sz * sizeof(uint16_t), 0);
54 [ # # ]: 0 : if (!reta) {
55 : 0 : plt_err("Failed to allocate mem for reta table");
56 : : rc = -ENOMEM;
57 : 0 : goto fail;
58 : : }
59 [ # # ]: 0 : for (qid = 0; qid < reta_sz; qid++) {
60 : 0 : vlan_tci = (1 << CNXK_ESWITCH_VFPF_SHIFT) | qid;
61 : 0 : hash = rte_softrss(&vlan_tci, 1, eswitch_vlan_rss_key);
62 : 0 : idx = hash & 0xFF;
63 : 0 : reta[idx] = qid;
64 : : }
65 : 0 : flow->mcam_id = id;
66 : 0 : rc = roc_eswitch_npc_rss_action_configure(roc_npc, flow, FLOW_KEY_TYPE_VLAN, reta);
67 [ # # ]: 0 : if (rc) {
68 : 0 : plt_err("Failed to configure rss action, err %d", rc);
69 : 0 : goto done;
70 : : }
71 : :
72 : 0 : done:
73 : 0 : plt_free(reta);
74 : 0 : fail:
75 : 0 : return rc;
76 : : }
77 : :
78 : : static int
79 : 0 : eswitch_pfvf_mcam_install_rules(struct cnxk_eswitch_dev *eswitch_dev, struct roc_npc_flow *flow,
80 : : bool is_vf)
81 : : {
82 : : uint16_t vlan_tci = 0, hw_func;
83 : : int rc;
84 : :
85 : 0 : hw_func = eswitch_dev->npc.pf_func | is_vf;
86 [ # # ]: 0 : if (!is_vf) {
87 : : /* Eswitch PF RX VLAN rule */
88 : : vlan_tci = 1ULL << CNXK_ESWITCH_VFPF_SHIFT;
89 : 0 : rc = roc_eswitch_npc_mcam_rx_rule(&eswitch_dev->npc, flow, hw_func, vlan_tci,
90 : : 0xFF00);
91 [ # # ]: 0 : if (rc) {
92 : 0 : plt_err("Failed to install RX rule for ESW PF to ESW VF, rc %d", rc);
93 : 0 : goto exit;
94 : : }
95 : 0 : plt_esw_dbg("Installed eswitch PF RX rule %d", flow->mcam_id);
96 : 0 : rc = eswitch_npc_vlan_rss_configure(&eswitch_dev->npc, flow);
97 [ # # ]: 0 : if (rc)
98 : 0 : goto exit;
99 : 0 : flow->enable = true;
100 : : } else {
101 : : /* Eswitch VF RX VLAN rule */
102 : 0 : rc = roc_eswitch_npc_mcam_rx_rule(&eswitch_dev->npc, flow, hw_func, vlan_tci,
103 : : 0xFF00);
104 [ # # ]: 0 : if (rc) {
105 : 0 : plt_err("Failed to install RX rule for ESW VF to ESW PF, rc %d", rc);
106 : 0 : goto exit;
107 : : }
108 : 0 : flow->enable = true;
109 : 0 : plt_esw_dbg("Installed eswitch PF RX rule %d", flow->mcam_id);
110 : : }
111 : :
112 : : return 0;
113 : : exit:
114 : : return rc;
115 : : }
116 : :
117 : : static int
118 : 0 : eswitch_npc_get_counter(struct roc_npc *npc, struct roc_npc_flow *flow)
119 : : {
120 : : uint16_t ctr_id;
121 : : int rc;
122 : :
123 : 0 : rc = roc_npc_mcam_alloc_counter(npc, &ctr_id);
124 [ # # ]: 0 : if (rc < 0) {
125 : 0 : plt_err("Failed to allocate counter, rc %d", rc);
126 : 0 : goto fail;
127 : : }
128 : 0 : flow->ctr_id = ctr_id;
129 : 0 : flow->use_ctr = true;
130 : :
131 : 0 : rc = roc_npc_mcam_clear_counter(npc, flow->ctr_id);
132 [ # # ]: 0 : if (rc < 0) {
133 : 0 : plt_err("Failed to clear counter idx %d, rc %d", flow->ctr_id, rc);
134 : 0 : goto free;
135 : : }
136 : : return 0;
137 : : free:
138 : 0 : roc_npc_mcam_free_counter(npc, ctr_id);
139 : : fail:
140 : : return rc;
141 : : }
142 : :
143 : : static int
144 : 0 : eswitch_npc_get_counter_entry_ref(struct roc_npc *npc, struct roc_npc_flow *flow,
145 : : struct roc_npc_flow *ref_flow)
146 : : {
147 : : int rc = 0, resp_count;
148 : :
149 : 0 : rc = eswitch_npc_get_counter(npc, flow);
150 [ # # ]: 0 : if (rc)
151 : 0 : goto free;
152 : :
153 : : /* Allocate an entry viz higher priority than ref flow */
154 : 0 : rc = roc_npc_mcam_alloc_entry(npc, flow, ref_flow, NPC_MCAM_HIGHER_PRIO, &resp_count);
155 [ # # ]: 0 : if (rc) {
156 : 0 : plt_err("Failed to allocate entry, err %d", rc);
157 : 0 : goto free;
158 : : }
159 : 0 : plt_esw_dbg("New entry %d ref entry %d resp_count %d", flow->mcam_id, ref_flow->mcam_id,
160 : : resp_count);
161 : :
162 : 0 : return 0;
163 : 0 : free:
164 : 0 : roc_npc_mcam_free_counter(npc, flow->ctr_id);
165 : 0 : return rc;
166 : : }
167 : :
168 : : int
169 : 0 : cnxk_eswitch_flow_rule_shift(uint16_t hw_func, uint16_t *entry)
170 : : {
171 : : struct cnxk_esw_repr_hw_info *repr_info;
172 : : struct cnxk_eswitch_dev *eswitch_dev;
173 : : struct roc_npc_flow *ref_flow, *flow;
174 : : uint16_t curr_entry, new_entry;
175 : : int rc = 0, resp_count;
176 : :
177 : : eswitch_dev = cnxk_eswitch_pmd_priv();
178 : : if (!eswitch_dev) {
179 : 0 : plt_err("Invalid eswitch_dev handle");
180 : : rc = -EINVAL;
181 : 0 : goto fail;
182 : : }
183 : :
184 : 0 : repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func);
185 [ # # ]: 0 : if (!repr_info) {
186 : 0 : plt_warn("Failed to get representor group for %x", hw_func);
187 : : rc = -ENOENT;
188 : 0 : goto fail;
189 : : }
190 : :
191 : 0 : ref_flow = TAILQ_FIRST(&repr_info->repr_flow_list);
192 [ # # ]: 0 : if (*entry > ref_flow->mcam_id) {
193 : 0 : flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0);
194 [ # # ]: 0 : if (!flow) {
195 : 0 : plt_err("Failed to allocate memory");
196 : : rc = -ENOMEM;
197 : 0 : goto fail;
198 : : }
199 : :
200 : : /* Allocate a higher priority flow rule */
201 : 0 : rc = roc_npc_mcam_alloc_entry(&eswitch_dev->npc, flow, ref_flow,
202 : : NPC_MCAM_HIGHER_PRIO, &resp_count);
203 [ # # ]: 0 : if (rc < 0) {
204 : 0 : plt_err("Failed to allocate a newmcam entry, rc %d", rc);
205 : 0 : goto fail;
206 : : }
207 : :
208 [ # # ]: 0 : if (flow->mcam_id > ref_flow->mcam_id) {
209 : 0 : plt_err("New flow %d is still at higher priority than ref_flow %d",
210 : : flow->mcam_id, ref_flow->mcam_id);
211 : : rc = -EINVAL;
212 : 0 : goto free_entry;
213 : : }
214 : :
215 : 0 : plt_info("Before shift: HW_func %x curr_entry %d ref flow id %d new_entry %d",
216 : : hw_func, *entry, ref_flow->mcam_id, flow->mcam_id);
217 : :
218 : 0 : curr_entry = *entry;
219 : 0 : new_entry = flow->mcam_id;
220 : :
221 : 0 : rc = roc_npc_mcam_move(&eswitch_dev->npc, curr_entry, new_entry);
222 [ # # ]: 0 : if (rc) {
223 : 0 : plt_err("Failed to shift the new index %d to curr index %d, err %d", *entry,
224 : : curr_entry, rc);
225 : 0 : goto free_entry;
226 : : }
227 : 0 : *entry = flow->mcam_id;
228 : :
229 : : /* Freeing the current entry */
230 : 0 : rc = roc_npc_mcam_free_entry(&eswitch_dev->npc, curr_entry);
231 [ # # ]: 0 : if (rc) {
232 : 0 : plt_err("Failed to free the old entry. err %d", rc);
233 : 0 : goto free_entry;
234 : : }
235 : :
236 : 0 : plt_free(flow);
237 : 0 : plt_info("After shift: HW_func %x old_entry %d new_entry %d", hw_func, curr_entry,
238 : : *entry);
239 : : }
240 : :
241 : : return 0;
242 : : free_entry:
243 : :
244 : : fail:
245 : : return rc;
246 : : }
247 : :
248 : : int
249 : 0 : cnxk_eswitch_flow_rules_delete(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func)
250 : : {
251 : : struct cnxk_esw_repr_hw_info *repr_info;
252 : : struct flow_list *list;
253 : : int rc = 0;
254 : :
255 : 0 : repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func);
256 [ # # ]: 0 : if (!repr_info) {
257 : 0 : plt_warn("Failed to get representor group for %x", hw_func);
258 : : rc = -ENOENT;
259 : 0 : goto fail;
260 : : }
261 : 0 : list = &repr_info->repr_flow_list;
262 : :
263 : 0 : plt_esw_dbg("Deleting flows for %x", hw_func);
264 : 0 : rc = cnxk_eswitch_flow_rules_remove_list(eswitch_dev, list, hw_func);
265 [ # # ]: 0 : if (rc)
266 : 0 : plt_err("Failed to delete rules for hw func %x", hw_func);
267 : :
268 : 0 : fail:
269 : 0 : return rc;
270 : : }
271 : :
272 : : int
273 : 0 : cnxk_eswitch_flow_rules_install(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func)
274 : : {
275 : : struct roc_npc_flow *rx_flow, *tx_flow, *flow_iter, *esw_pf_flow = NULL;
276 : : struct cnxk_esw_repr_hw_info *repr_info;
277 : : struct flow_list *list;
278 : : uint16_t vlan_tci;
279 : : int rc = 0;
280 : :
281 : 0 : repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func);
282 [ # # ]: 0 : if (!repr_info) {
283 : 0 : plt_err("Failed to get representor group for %x", hw_func);
284 : : rc = -EINVAL;
285 : 0 : goto fail;
286 : : }
287 : : list = &repr_info->repr_flow_list;
288 : :
289 : : /* Taking ESW PF as reference entry for installing new rules */
290 [ # # ]: 0 : TAILQ_FOREACH(flow_iter, &eswitch_dev->esw_flow_list, next) {
291 [ # # ]: 0 : if (flow_iter->mcam_id == eswitch_dev->esw_pf_entry) {
292 : : esw_pf_flow = flow_iter;
293 : : break;
294 : : }
295 : : }
296 : :
297 [ # # ]: 0 : if (!esw_pf_flow) {
298 : 0 : plt_err("Failed to get the ESW PF flow");
299 : : rc = -EINVAL;
300 : 0 : goto fail;
301 : : }
302 : :
303 : : /* Installing RX rule */
304 : 0 : rx_flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0);
305 [ # # ]: 0 : if (!rx_flow) {
306 : 0 : plt_err("Failed to allocate memory");
307 : : rc = -ENOMEM;
308 : 0 : goto fail;
309 : : }
310 : :
311 : 0 : rc = eswitch_npc_get_counter_entry_ref(&eswitch_dev->npc, rx_flow, esw_pf_flow);
312 [ # # ]: 0 : if (rc) {
313 : 0 : plt_err("Failed to get counter and mcam entry, rc %d", rc);
314 : 0 : goto free_rx_flow;
315 : : }
316 : :
317 : : /* VLAN TCI value for this representee is the rep id from AF driver */
318 : 0 : vlan_tci = repr_info->rep_id;
319 : 0 : rc = roc_eswitch_npc_mcam_rx_rule(&eswitch_dev->npc, rx_flow, hw_func, vlan_tci, 0xFFFF);
320 [ # # ]: 0 : if (rc) {
321 : 0 : plt_err("Failed to install RX rule for ESW PF to ESW VF, rc %d", rc);
322 : 0 : goto free_rx_entry;
323 : : }
324 : 0 : rx_flow->enable = true;
325 : : /* List in ascending order of mcam entries */
326 [ # # ]: 0 : TAILQ_FOREACH(flow_iter, list, next) {
327 [ # # ]: 0 : if (flow_iter->mcam_id > rx_flow->mcam_id) {
328 : 0 : TAILQ_INSERT_BEFORE(flow_iter, rx_flow, next);
329 : 0 : goto done_rx;
330 : : }
331 : : }
332 : 0 : TAILQ_INSERT_TAIL(list, rx_flow, next);
333 : 0 : done_rx:
334 : 0 : repr_info->num_flow_entries++;
335 : 0 : plt_esw_dbg("Installed RX flow rule %d for representee %x with vlan tci %x MCAM id %d",
336 : : eswitch_dev->num_entries, hw_func, vlan_tci, rx_flow->mcam_id);
337 : :
338 : : /* Installing TX rule */
339 : 0 : tx_flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0);
340 [ # # ]: 0 : if (!tx_flow) {
341 : 0 : plt_err("Failed to allocate memory");
342 : : rc = -ENOMEM;
343 : 0 : goto remove_rx_rule;
344 : : }
345 : :
346 : 0 : rc = eswitch_npc_get_counter_entry_ref(&eswitch_dev->npc, tx_flow, esw_pf_flow);
347 [ # # ]: 0 : if (rc) {
348 : 0 : plt_err("Failed to get counter and mcam entry, rc %d", rc);
349 : 0 : goto free_tx_flow;
350 : : }
351 : :
352 : 0 : vlan_tci = (1ULL << CNXK_ESWITCH_VFPF_SHIFT) | repr_info->rep_id;
353 : 0 : rc = roc_eswitch_npc_mcam_tx_rule(&eswitch_dev->npc, tx_flow, hw_func, vlan_tci);
354 [ # # ]: 0 : if (rc) {
355 : 0 : plt_err("Failed to install RX rule for ESW PF to ESW VF, rc %d", rc);
356 : 0 : goto free_tx_entry;
357 : : }
358 : 0 : tx_flow->enable = true;
359 : : /* List in ascending order of mcam entries */
360 [ # # ]: 0 : TAILQ_FOREACH(flow_iter, list, next) {
361 [ # # ]: 0 : if (flow_iter->mcam_id > tx_flow->mcam_id) {
362 : 0 : TAILQ_INSERT_BEFORE(flow_iter, tx_flow, next);
363 : 0 : goto done_tx;
364 : : }
365 : : }
366 : 0 : TAILQ_INSERT_TAIL(list, tx_flow, next);
367 : 0 : done_tx:
368 : 0 : repr_info->num_flow_entries++;
369 : 0 : plt_esw_dbg("Installed TX flow rule %d for representee %x with vlan tci %x MCAM id %d",
370 : : repr_info->num_flow_entries, hw_func, vlan_tci, tx_flow->mcam_id);
371 : :
372 : 0 : return 0;
373 : : free_tx_entry:
374 : 0 : roc_npc_mcam_free(&eswitch_dev->npc, tx_flow);
375 : 0 : free_tx_flow:
376 : 0 : rte_free(tx_flow);
377 : 0 : remove_rx_rule:
378 [ # # ]: 0 : TAILQ_REMOVE(list, rx_flow, next);
379 : 0 : free_rx_entry:
380 : 0 : roc_npc_mcam_free(&eswitch_dev->npc, rx_flow);
381 : 0 : free_rx_flow:
382 : 0 : rte_free(rx_flow);
383 : : fail:
384 : : return rc;
385 : : }
386 : :
387 : : int
388 : 0 : cnxk_eswitch_pfvf_flow_rules_install(struct cnxk_eswitch_dev *eswitch_dev, bool is_vf)
389 : : {
390 : : struct roc_npc_flow *flow, *flow_iter;
391 : : struct flow_list *list;
392 : : int rc = 0;
393 : :
394 : 0 : list = &eswitch_dev->esw_flow_list;
395 : 0 : flow = plt_zmalloc(sizeof(struct roc_npc_flow), 0);
396 [ # # ]: 0 : if (!flow) {
397 : 0 : plt_err("Failed to allocate memory");
398 : : rc = -ENOMEM;
399 : 0 : goto fail;
400 : : }
401 : :
402 : 0 : rc = eswitch_npc_get_counter(&eswitch_dev->npc, flow);
403 [ # # ]: 0 : if (rc) {
404 : 0 : plt_err("Failed to get counter and mcam entry, rc %d", rc);
405 : 0 : goto free_flow;
406 : : }
407 [ # # ]: 0 : if (!is_vf) {
408 : : /* Reserving an entry for esw VF but will not be installed */
409 : 0 : rc = roc_npc_get_free_mcam_entry(&eswitch_dev->npc, flow);
410 [ # # ]: 0 : if (rc < 0) {
411 : 0 : plt_err("Failed to allocate entry for vf, err %d", rc);
412 : 0 : goto free_flow;
413 : : }
414 : 0 : eswitch_dev->esw_vf_entry = flow->mcam_id;
415 : : /* Allocate an entry for esw PF */
416 : 0 : rc = eswitch_npc_get_counter_entry_ref(&eswitch_dev->npc, flow, flow);
417 [ # # ]: 0 : if (rc) {
418 : 0 : plt_err("Failed to allocate entry for pf, err %d", rc);
419 : 0 : goto free_flow;
420 : : }
421 : 0 : eswitch_dev->esw_pf_entry = flow->mcam_id;
422 : 0 : plt_esw_dbg("Allocated entries for esw: PF %d and VF %d", eswitch_dev->esw_pf_entry,
423 : : eswitch_dev->esw_vf_entry);
424 : : } else {
425 : 0 : flow->mcam_id = eswitch_dev->esw_vf_entry;
426 : : }
427 : :
428 : 0 : rc = eswitch_pfvf_mcam_install_rules(eswitch_dev, flow, is_vf);
429 [ # # ]: 0 : if (rc) {
430 : 0 : plt_err("Failed to install entries, rc %d", rc);
431 : 0 : goto free_flow;
432 : : }
433 : :
434 : : /* List in ascending order of mcam entries */
435 [ # # ]: 0 : TAILQ_FOREACH(flow_iter, list, next) {
436 [ # # ]: 0 : if (flow_iter->mcam_id > flow->mcam_id) {
437 : 0 : TAILQ_INSERT_BEFORE(flow_iter, flow, next);
438 : 0 : goto done;
439 : : }
440 : : }
441 : 0 : TAILQ_INSERT_TAIL(list, flow, next);
442 : 0 : done:
443 : 0 : eswitch_dev->num_entries++;
444 : 0 : plt_esw_dbg("Installed new eswitch flow rule %d with MCAM id %d", eswitch_dev->num_entries,
445 : : flow->mcam_id);
446 : :
447 : 0 : return 0;
448 : :
449 : 0 : free_flow:
450 : 0 : cnxk_eswitch_flow_rules_remove_list(eswitch_dev, &eswitch_dev->esw_flow_list,
451 : 0 : eswitch_dev->npc.pf_func);
452 : : fail:
453 : : return rc;
454 : : }
|