1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
3 */
4
5 #include "cnxk_ethdev.h"
6 #include <rte_mtr_driver.h>
7
8 #define NIX_MTR_COUNT_PER_FLOW 3 /* 1(leaf) + 1(mid) + 1(top) */
9
10 #define NIX_BPF_STATS_MASK_ALL \
11 { \
12 ROC_NIX_BPF_GREEN_PKT_F_PASS | ROC_NIX_BPF_GREEN_OCTS_F_PASS | \
13 ROC_NIX_BPF_GREEN_PKT_F_DROP | \
14 ROC_NIX_BPF_GREEN_OCTS_F_DROP | \
15 ROC_NIX_BPF_YELLOW_PKT_F_PASS | \
16 ROC_NIX_BPF_YELLOW_OCTS_F_PASS | \
17 ROC_NIX_BPF_YELLOW_PKT_F_DROP | \
18 ROC_NIX_BPF_YELLOW_OCTS_F_DROP | \
19 ROC_NIX_BPF_RED_PKT_F_PASS | \
20 ROC_NIX_BPF_RED_OCTS_F_PASS | \
21 ROC_NIX_BPF_RED_PKT_F_DROP | \
22 ROC_NIX_BPF_RED_OCTS_F_DROP \
23 }
24
25 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF,
26 ROC_NIX_BPF_LEVEL_F_MID,
27 ROC_NIX_BPF_LEVEL_F_TOP};
28
29 static struct rte_mtr_capabilities mtr_capa = {
30 .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
31 /* .identical = , */
32 .shared_identical = true,
33 /* .shared_n_flows_per_mtr_max = ,*/
34 .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
35 .chaining_use_prev_mtr_color_supported = true,
36 .chaining_use_prev_mtr_color_enforced = true,
37 .color_aware_srtcm_rfc2697_supported = true,
38 .color_aware_trtcm_rfc2698_supported = true,
39 .color_aware_trtcm_rfc4115_supported = true,
40 .srtcm_rfc2697_byte_mode_supported = true,
41 .srtcm_rfc2697_packet_mode_supported = true,
42 .trtcm_rfc2698_byte_mode_supported = true,
43 .trtcm_rfc2698_packet_mode_supported = true,
44 .trtcm_rfc4115_byte_mode_supported = true,
45 .trtcm_rfc4115_packet_mode_supported = true,
46 .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
47 RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
48 RTE_MTR_STATS_N_BYTES_GREEN |
49 RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
50 RTE_MTR_STATS_N_BYTES_DROPPED,
51 .input_color_proto_mask = RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN |
52 RTE_MTR_COLOR_IN_PROTO_INNER_VLAN |
53 RTE_MTR_COLOR_IN_PROTO_OUTER_IP |
54 RTE_MTR_COLOR_IN_PROTO_INNER_IP,
55 .separate_input_color_table_per_port = true};
56
57 static struct cnxk_meter_node *
nix_mtr_find(struct cnxk_eth_dev * dev,uint32_t meter_id)58 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id)
59 {
60 struct cnxk_mtr *fms = &dev->mtr;
61 struct cnxk_meter_node *fm;
62
63 TAILQ_FOREACH(fm, fms, next)
64 if (meter_id == fm->id)
65 return fm;
66 return NULL;
67 }
68
69 static struct cnxk_mtr_profile_node *
nix_mtr_profile_find(struct cnxk_eth_dev * dev,uint32_t profile_id)70 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
71 {
72 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
73 struct cnxk_mtr_profile_node *fmp;
74
75 TAILQ_FOREACH(fmp, fmps, next)
76 if (profile_id == fmp->id)
77 return fmp;
78
79 return NULL;
80 }
81
82 static struct cnxk_mtr_policy_node *
nix_mtr_policy_find(struct cnxk_eth_dev * dev,uint32_t meter_policy_id)83 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
84 {
85 struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
86 struct cnxk_mtr_policy_node *fmp;
87
88 TAILQ_FOREACH(fmp, fmps, next)
89 if (meter_policy_id == fmp->id)
90 return fmp;
91 return NULL;
92 }
93
94 static int
nix_mtr_profile_validate(struct cnxk_eth_dev * dev,uint32_t profile_id,struct rte_mtr_meter_profile * profile,struct rte_mtr_error * error)95 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
96 struct rte_mtr_meter_profile *profile,
97 struct rte_mtr_error *error)
98 {
99 int rc = 0;
100
101 PLT_SET_USED(dev);
102
103 if (profile == NULL)
104 return -rte_mtr_error_set(error, EINVAL,
105 RTE_MTR_ERROR_TYPE_METER_PROFILE,
106 NULL, "Meter profile is null.");
107
108 if (profile_id == UINT32_MAX)
109 return -rte_mtr_error_set(error, EINVAL,
110 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
111 NULL, "Meter profile id not valid.");
112
113 switch (profile->alg) {
114 case RTE_MTR_SRTCM_RFC2697:
115 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
116 rc = -rte_mtr_error_set(error, EINVAL,
117 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
118 "CIR exceeds max meter rate");
119
120 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
121 rc = -rte_mtr_error_set(error, EINVAL,
122 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
123 "CBS exceeds max meter burst size");
124
125 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
126 rc = -rte_mtr_error_set(error, EINVAL,
127 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
128 "EBS exceeds max meter burst size");
129 break;
130
131 case RTE_MTR_TRTCM_RFC2698:
132 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
133 rc = -rte_mtr_error_set(error, EINVAL,
134 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
135 "CIR exceeds max meter rate");
136
137 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
138 rc = -rte_mtr_error_set(error, EINVAL,
139 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
140 "PIR exceeds max meter rate");
141
142 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
143 rc = -rte_mtr_error_set(error, EINVAL,
144 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
145 "CBS exceeds max meter burst size");
146
147 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
148 rc = -rte_mtr_error_set(error, EINVAL,
149 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
150 "PBS exceeds max meter burst size");
151 break;
152
153 case RTE_MTR_TRTCM_RFC4115:
154 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
155 mtr_capa.meter_rate_max)
156 rc = -rte_mtr_error_set(error, EINVAL,
157 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
158 "PIR + EIR exceeds max rate");
159
160 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
161 rc = -rte_mtr_error_set(error, EINVAL,
162 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
163 "CBS exceeds max meter burst size");
164
165 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
166 rc = -rte_mtr_error_set(error, EINVAL,
167 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
168 "PBS exceeds max meter burst size");
169 break;
170
171 default:
172 rc = -rte_mtr_error_set(error, EINVAL,
173 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
174 "alg is invalid");
175 break;
176 }
177
178 return rc;
179 }
180
181 static int
cnxk_nix_mtr_capabilities_get(struct rte_eth_dev * dev,struct rte_mtr_capabilities * capa,struct rte_mtr_error * error)182 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
183 struct rte_mtr_capabilities *capa,
184 struct rte_mtr_error *error)
185 {
186 uint8_t lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF | ROC_NIX_BPF_LEVEL_F_MID |
187 ROC_NIX_BPF_LEVEL_F_TOP;
188 struct cnxk_eth_dev *eth_dev = cnxk_eth_pmd_priv(dev);
189 uint16_t count[ROC_NIX_BPF_LEVEL_MAX] = {0};
190 struct roc_nix *nix = ð_dev->nix;
191 uint32_t time_unit;
192 int rc, i;
193
194 RTE_SET_USED(dev);
195
196 if (!capa)
197 return -rte_mtr_error_set(error, EINVAL,
198 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
199 "NULL input parameter");
200
201 rc = roc_nix_bpf_count_get(nix, lvl_mask, count);
202 if (rc)
203 return rc;
204
205 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++)
206 mtr_capa.n_max += count[i];
207
208 mtr_capa.meter_srtcm_rfc2697_n_max = mtr_capa.n_max;
209 mtr_capa.meter_trtcm_rfc2698_n_max = mtr_capa.n_max;
210 mtr_capa.meter_trtcm_rfc4115_n_max = mtr_capa.n_max;
211 mtr_capa.meter_policy_n_max = mtr_capa.n_max;
212
213 rc = roc_nix_bpf_timeunit_get(nix, &time_unit);
214 if (rc)
215 return rc;
216
217 mtr_capa.meter_rate_max =
218 NIX_BPF_RATE(time_unit, NIX_BPF_MAX_RATE_EXPONENT,
219 NIX_BPF_MAX_RATE_MANTISSA, 0) /
220 8;
221
222 *capa = mtr_capa;
223 return 0;
224 }
225
226 static int
cnxk_nix_mtr_profile_add(struct rte_eth_dev * eth_dev,uint32_t profile_id,struct rte_mtr_meter_profile * profile,struct rte_mtr_error * error)227 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
228 struct rte_mtr_meter_profile *profile,
229 struct rte_mtr_error *error)
230 {
231 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
232 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
233 struct cnxk_mtr_profile_node *fmp;
234 int ret;
235
236 /* Check input params. */
237 ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
238 if (ret)
239 return ret;
240
241 fmp = nix_mtr_profile_find(dev, profile_id);
242 if (fmp) {
243 return -rte_mtr_error_set(error, EEXIST,
244 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
245 NULL, "Profile already exist");
246 }
247
248 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
249 if (fmp == NULL)
250 return -rte_mtr_error_set(error, ENOMEM,
251 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
252 "Meter profile memory "
253 "alloc failed.");
254
255 fmp->id = profile_id;
256 fmp->profile = *profile;
257
258 TAILQ_INSERT_TAIL(fmps, fmp, next);
259
260 return 0;
261 }
262
263 static int
cnxk_nix_mtr_profile_delete(struct rte_eth_dev * eth_dev,uint32_t profile_id,struct rte_mtr_error * error)264 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
265 struct rte_mtr_error *error)
266 {
267 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
268 struct cnxk_mtr_profile_node *fmp;
269
270 if (profile_id == UINT32_MAX)
271 return -rte_mtr_error_set(error, EINVAL,
272 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
273 NULL, "Meter profile id not valid.");
274
275 fmp = nix_mtr_profile_find(dev, profile_id);
276 if (fmp == NULL)
277 return -rte_mtr_error_set(error, ENOENT,
278 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
279 &profile_id,
280 "Meter profile is invalid.");
281
282 if (fmp->ref_cnt)
283 return -rte_mtr_error_set(error, EBUSY,
284 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
285 NULL, "Meter profile is in use.");
286
287 TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
288 plt_free(fmp);
289 return 0;
290 }
291
292 static int
update_mtr_err(uint32_t act_color,struct rte_mtr_error * error,bool action)293 update_mtr_err(uint32_t act_color, struct rte_mtr_error *error, bool action)
294 {
295 const char *str = NULL;
296 switch (act_color) {
297 case RTE_COLOR_GREEN:
298 if (action) {
299 str = "Green action is not valid";
300 goto notsup;
301 } else {
302 str = "Green action is null";
303 goto notvalid;
304 }
305 break;
306 case RTE_COLOR_YELLOW:
307 if (action) {
308 str = "Yellow action is not valid";
309 goto notsup;
310 } else {
311 str = "Yellow action is null";
312 goto notvalid;
313 }
314 break;
315 case RTE_COLOR_RED:
316 if (action) {
317 str = "Red action is not valid";
318 goto notsup;
319 } else {
320 str = "Red action is null";
321 goto notvalid;
322 }
323 break;
324 }
325 notsup:
326 return -rte_mtr_error_set(error, ENOTSUP,
327 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
328 notvalid:
329 return -rte_mtr_error_set(error, EINVAL,
330 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
331 }
332
333 static int
cnxk_nix_mtr_policy_validate(struct rte_eth_dev * dev,struct rte_mtr_meter_policy_params * policy,struct rte_mtr_error * error)334 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
335 struct rte_mtr_meter_policy_params *policy,
336 struct rte_mtr_error *error)
337 {
338 bool supported[RTE_COLORS] = {false, false, false};
339 const struct rte_flow_action *action;
340 uint32_t i;
341
342 RTE_SET_USED(dev);
343
344 if (!policy)
345 return 0; /* Nothing to be validated */
346
347 for (i = 0; i < RTE_COLORS; i++) {
348 if (policy->actions[i]) {
349 for (action = policy->actions[i];
350 action->type != RTE_FLOW_ACTION_TYPE_END;
351 action++) {
352 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
353 supported[i] = true;
354
355 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
356 supported[i] = true;
357
358 if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
359 supported[i] = true;
360
361 if (action->type == RTE_FLOW_ACTION_TYPE_SKIP_CMAN)
362 supported[i] = true;
363
364 if (!supported[i])
365 return update_mtr_err(i, error, true);
366 }
367 } else {
368 return update_mtr_err(i, error, false);
369 }
370 }
371
372 return 0;
373 }
374
375 static void
cnxk_fill_policy_actions(struct cnxk_mtr_policy_node * fmp,struct rte_mtr_meter_policy_params * policy)376 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
377 struct rte_mtr_meter_policy_params *policy)
378
379 {
380 const struct rte_flow_action_meter *mtr;
381 const struct rte_flow_action *action;
382 int i;
383
384 for (i = 0; i < RTE_COLORS; i++) {
385 if (policy->actions[i]) {
386 for (action = policy->actions[i];
387 action->type != RTE_FLOW_ACTION_TYPE_END;
388 action++) {
389 if (action->type ==
390 RTE_FLOW_ACTION_TYPE_METER) {
391 fmp->actions[i].action_fate =
392 action->type;
393 mtr = (const struct
394 rte_flow_action_meter *)
395 action->conf;
396 fmp->actions[i].mtr_id = mtr->mtr_id;
397 }
398
399 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
400 fmp->actions[i].action_fate =
401 action->type;
402 }
403
404 if (action->type ==
405 RTE_FLOW_ACTION_TYPE_SKIP_CMAN)
406 fmp->actions[i].skip_red = true;
407 }
408 }
409 }
410 }
411
412 static int
cnxk_nix_mtr_policy_add(struct rte_eth_dev * eth_dev,uint32_t policy_id,struct rte_mtr_meter_policy_params * policy,struct rte_mtr_error * error)413 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
414 struct rte_mtr_meter_policy_params *policy,
415 struct rte_mtr_error *error)
416 {
417 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
418 struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
419 struct cnxk_mtr_policy_node *fmp;
420 int rc;
421
422 fmp = nix_mtr_policy_find(dev, policy_id);
423 if (fmp) {
424 return -rte_mtr_error_set(error, EEXIST,
425 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
426 NULL, "Policy already exist");
427 }
428
429 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
430 if (fmp == NULL) {
431 return -rte_mtr_error_set(error, ENOMEM,
432 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
433 "Memory allocation failure");
434 } else {
435 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
436 if (rc)
437 goto exit;
438 }
439
440 fmp->id = policy_id;
441 cnxk_fill_policy_actions(fmp, policy);
442 TAILQ_INSERT_TAIL(fmps, fmp, next);
443 return 0;
444
445 exit:
446 plt_free(fmp);
447 return rc;
448 }
449
450 static int
cnxk_nix_mtr_policy_delete(struct rte_eth_dev * eth_dev,uint32_t policy_id,struct rte_mtr_error * error)451 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
452 struct rte_mtr_error *error)
453 {
454 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
455 struct cnxk_mtr_policy_node *fmp;
456
457 fmp = nix_mtr_policy_find(dev, policy_id);
458 if (fmp == NULL) {
459 return -rte_mtr_error_set(error, ENOENT,
460 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
461 NULL, "No policy found");
462 }
463
464 if (fmp->ref_cnt)
465 return -rte_mtr_error_set(error, EBUSY,
466 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
467 NULL, "Meter policy is in use.");
468
469 TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
470 plt_free(fmp);
471
472 return 0;
473 }
474
475 static int
cnxk_nix_mtr_create(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_params * params,int shared,struct rte_mtr_error * error)476 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
477 struct rte_mtr_params *params, int shared,
478 struct rte_mtr_error *error)
479 {
480 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
481 struct cnxk_mtr_profile_node *profile;
482 struct cnxk_mtr_policy_node *policy;
483 struct cnxk_mtr *fm = &dev->mtr;
484 enum rte_color *table = NULL;
485 struct cnxk_meter_node *mtr;
486 int i;
487
488 RTE_SET_USED(shared);
489
490 if (params == NULL)
491 return -rte_mtr_error_set(error, ENOENT,
492 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
493 "Meter params are invalid.");
494
495 profile = nix_mtr_profile_find(dev, params->meter_profile_id);
496 if (profile == NULL)
497 return -rte_mtr_error_set(error, ENOENT,
498 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
499 ¶ms->meter_profile_id,
500 "Meter profile is invalid.");
501
502 policy = nix_mtr_policy_find(dev, params->meter_policy_id);
503 if (policy == NULL)
504 return -rte_mtr_error_set(error, ENOENT,
505 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
506 ¶ms->meter_policy_id,
507 "Meter policy is invalid.");
508
509 mtr = nix_mtr_find(dev, mtr_id);
510 if (mtr) {
511 return -rte_mtr_error_set(error, EEXIST,
512 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
513 "Meter already exist");
514 }
515
516 mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
517 if (mtr == NULL) {
518 return -rte_mtr_error_set(error, ENOMEM,
519 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
520 "Meter memory alloc failed.");
521 }
522
523 mtr->id = mtr_id;
524 mtr->profile = profile;
525 mtr->policy = policy;
526 mtr->params = *params;
527 mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
528 mtr->prev_cnt = 0;
529 for (i = 0; i < MAX_PRV_MTR_NODES; i++)
530 mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
531
532 mtr->next_id = ROC_NIX_BPF_ID_INVALID;
533 mtr->is_next = false;
534 mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
535
536 /* populate dscp table for input coloring */
537 if (params->dscp_table) {
538 table = (enum rte_color *)plt_zmalloc(sizeof(enum rte_color) *
539 ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP, ROC_ALIGN);
540 if (table == NULL) {
541 plt_free(mtr);
542 return -rte_mtr_error_set(error, ENOMEM,
543 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
544 NULL, "Memory alloc failed.");
545 }
546
547 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
548 table[i] = params->dscp_table[i];
549
550 mtr->params.dscp_table = table;
551 }
552
553
554 /* populate vlan table for input coloring */
555 if (params->vlan_table) {
556 table = (enum rte_color *)plt_zmalloc(sizeof(enum rte_color) *
557 ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN, ROC_ALIGN);
558 if (table == NULL) {
559 plt_free(mtr->params.dscp_table);
560 plt_free(mtr);
561 return -rte_mtr_error_set(error, ENOMEM,
562 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
563 NULL, "Memory alloc failed.");
564 }
565
566 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
567 table[i] = params->vlan_table[i];
568
569 mtr->params.vlan_table = table;
570 }
571
572 profile->ref_cnt++;
573 policy->ref_cnt++;
574 TAILQ_INSERT_TAIL(fm, mtr, next);
575 return 0;
576 }
577
578 static int
cnxk_nix_mtr_destroy(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_error * error)579 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
580 struct rte_mtr_error *error)
581 {
582 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
583 struct roc_nix_bpf_objs profs = {0};
584 struct cnxk_mtr *fm = &dev->mtr;
585 struct roc_nix *nix = &dev->nix;
586 struct cnxk_meter_node *mtr;
587 struct cnxk_meter_node *mid_mtr;
588 struct cnxk_meter_node *top_mtr;
589 int rc = 0;
590
591 mtr = nix_mtr_find(dev, mtr_id);
592 if (mtr == NULL) {
593 return -rte_mtr_error_set(error, ENOENT,
594 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
595 "Meter id is invalid.");
596 }
597
598 if (mtr->ref_cnt) {
599 return -rte_mtr_error_set(error, EADDRINUSE,
600 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
601 "Meter id in use.");
602 }
603
604 switch (lvl_map[mtr->level]) {
605 case ROC_NIX_BPF_LEVEL_F_LEAF:
606 if (mtr->is_next) {
607 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
608 mtr->bpf_id,
609 ROC_NIX_BPF_ID_INVALID);
610 }
611 break;
612 case ROC_NIX_BPF_LEVEL_F_MID:
613 while ((mtr->prev_cnt) + 1) {
614 mid_mtr =
615 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
616 if (mid_mtr == NULL) {
617 return -rte_mtr_error_set(error, ENOENT,
618 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr->prev_id[mtr->prev_cnt],
619 "Mid meter id is invalid.");
620 }
621 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
622 mid_mtr->bpf_id,
623 ROC_NIX_BPF_ID_INVALID);
624 mtr->prev_cnt--;
625 }
626 if (mtr->is_next) {
627 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
628 mtr->bpf_id,
629 ROC_NIX_BPF_ID_INVALID);
630 }
631 break;
632 case ROC_NIX_BPF_LEVEL_F_TOP:
633 while (mtr->prev_cnt) {
634 top_mtr =
635 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
636 if (top_mtr == NULL) {
637 return -rte_mtr_error_set(error, ENOENT,
638 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr->prev_id[mtr->prev_cnt],
639 "Top meter id is invalid.");
640 }
641 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
642 top_mtr->bpf_id,
643 ROC_NIX_BPF_ID_INVALID);
644 mtr->prev_cnt--;
645 }
646 break;
647 default:
648 return -rte_mtr_error_set(error, EINVAL,
649 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
650 "Invalid meter level");
651 }
652
653 if (rc)
654 goto exit;
655
656 profs.level = mtr->level;
657 profs.count = 1;
658 profs.ids[0] = mtr->bpf_id;
659 rc = roc_nix_bpf_free(nix, &profs, 1);
660 if (rc)
661 goto exit;
662
663 mtr->policy->ref_cnt--;
664 mtr->profile->ref_cnt--;
665 TAILQ_REMOVE(fm, mtr, next);
666
667 if (mtr->params.dscp_table)
668 plt_free(mtr->params.dscp_table);
669
670 if (mtr->params.vlan_table)
671 plt_free(mtr->params.vlan_table);
672
673 plt_free(mtr);
674
675 exit:
676 return rc;
677 }
678
679 static int
cnxk_nix_mtr_enable(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_error * error)680 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
681 struct rte_mtr_error *error)
682 {
683 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
684 struct roc_nix *nix = &dev->nix;
685 struct cnxk_meter_node *mtr;
686 struct roc_nix_rq *rq;
687 uint32_t i;
688 int rc = 0;
689
690 mtr = nix_mtr_find(dev, mtr_id);
691 if (mtr == NULL) {
692 return -rte_mtr_error_set(error, ENOENT,
693 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
694 "Meter id is invalid.");
695 }
696
697 if (mtr->level != 0)
698 return 0;
699
700 for (i = 0; i < mtr->rq_num; i++) {
701 rq = &dev->rqs[mtr->rq_id[i]];
702 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
703 }
704
705 return rc;
706 }
707
708 static int
cnxk_nix_mtr_disable(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_error * error)709 cnxk_nix_mtr_disable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
710 struct rte_mtr_error *error)
711 {
712 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
713 struct roc_nix *nix = &dev->nix;
714 struct cnxk_meter_node *mtr;
715 struct roc_nix_rq *rq;
716 uint32_t i;
717 int rc = 0;
718
719 mtr = nix_mtr_find(dev, mtr_id);
720 if (mtr == NULL) {
721 return -rte_mtr_error_set(error, ENOENT,
722 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
723 "Meter id is invalid.");
724 }
725
726 if (mtr->level != 0)
727 return 0;
728
729 for (i = 0; i < mtr->rq_num; i++) {
730 rq = &dev->rqs[mtr->rq_id[i]];
731 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false);
732 }
733
734 return rc;
735 }
736
737 static int
cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,enum rte_color * dscp_table,struct rte_mtr_error * error)738 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
739 enum rte_mtr_color_in_protocol proto,
740 enum rte_color *dscp_table,
741 struct rte_mtr_error *error)
742 {
743 enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP];
744 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
745 ROC_NIX_BPF_COLOR_YELLOW,
746 ROC_NIX_BPF_COLOR_RED};
747 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
748 struct roc_nix_bpf_precolor table;
749 struct roc_nix *nix = &dev->nix;
750 struct cnxk_meter_node *mtr;
751 int rc, i;
752
753 mtr = nix_mtr_find(dev, mtr_id);
754 if (mtr == NULL) {
755 return -rte_mtr_error_set(error, ENOENT,
756 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
757 "Meter object not found");
758 }
759
760 if (!dscp_table) {
761 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
762 nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
763 } else {
764 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
765 nix_dscp_tbl[i] = color_map[dscp_table[i]];
766 }
767
768 table.count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP;
769
770 switch (proto) {
771 case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
772 table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
773 break;
774 case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
775 table.mode = ROC_NIX_BPF_PC_MODE_DSCP_INNER;
776 break;
777 default:
778 rc = -rte_mtr_error_set(error, EINVAL,
779 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
780 "Invalid input color protocol");
781 goto exit;
782 }
783
784 if (dev->proto != proto) {
785 rc = -rte_mtr_error_set(error, EINVAL,
786 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
787 "input color protocol is not configured");
788 goto exit;
789 }
790
791 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
792 table.color[i] = nix_dscp_tbl[i];
793
794 rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
795 lvl_map[mtr->level], &table);
796 if (rc) {
797 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
798 NULL, NULL);
799 goto exit;
800 }
801
802 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
803 dev->precolor_tbl[i] = nix_dscp_tbl[i];
804
805 exit:
806 return rc;
807 }
808
809 static int
cnxk_nix_mtr_vlan_table_update(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,enum rte_color * vlan_table,struct rte_mtr_error * error)810 cnxk_nix_mtr_vlan_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
811 enum rte_mtr_color_in_protocol proto,
812 enum rte_color *vlan_table,
813 struct rte_mtr_error *error)
814 {
815 enum roc_nix_bpf_color nix_vlan_tbl[ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN];
816 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
817 ROC_NIX_BPF_COLOR_YELLOW,
818 ROC_NIX_BPF_COLOR_RED};
819 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
820 struct roc_nix_bpf_precolor table;
821 struct roc_nix *nix = &dev->nix;
822 struct cnxk_meter_node *mtr;
823 int rc, i;
824
825 mtr = nix_mtr_find(dev, mtr_id);
826 if (mtr == NULL) {
827 return -rte_mtr_error_set(error, ENOENT,
828 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
829 "Meter object not found");
830 }
831
832 if (!vlan_table) {
833 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
834 nix_vlan_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
835 } else {
836 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
837 nix_vlan_tbl[i] = color_map[vlan_table[i]];
838 }
839
840 table.count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN;
841
842 switch (proto) {
843 case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
844 table.mode = ROC_NIX_BPF_PC_MODE_VLAN_OUTER;
845 break;
846 case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
847 table.mode = ROC_NIX_BPF_PC_MODE_VLAN_INNER;
848 break;
849 default:
850 rc = -rte_mtr_error_set(error, EINVAL,
851 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
852 "Invalid input color protocol");
853 goto exit;
854 }
855
856 if (dev->proto != proto) {
857 rc = -rte_mtr_error_set(error, EINVAL,
858 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
859 "input color protocol is not configured");
860 goto exit;
861 }
862
863 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
864 table.color[i] = nix_vlan_tbl[i];
865
866 rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
867 lvl_map[mtr->level], &table);
868 if (rc) {
869 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
870 NULL, NULL);
871 goto exit;
872 }
873
874 for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
875 dev->precolor_tbl[i] = nix_vlan_tbl[i];
876
877 exit:
878 return rc;
879 }
880
881 static int
cnxk_nix_mtr_in_proto_set(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,uint32_t priority,struct rte_mtr_error * error)882 cnxk_nix_mtr_in_proto_set(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
883 enum rte_mtr_color_in_protocol proto,
884 uint32_t priority, struct rte_mtr_error *error)
885 {
886 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
887 struct cnxk_meter_node *mtr;
888
889 RTE_SET_USED(priority);
890
891 mtr = nix_mtr_find(dev, mtr_id);
892 if (mtr == NULL) {
893 return -rte_mtr_error_set(error, ENOENT,
894 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
895 "Meter object not found");
896 }
897
898 dev->proto = proto;
899 return 0;
900 }
901
902 static int
cnxk_nix_mtr_in_proto_get(struct rte_eth_dev * eth_dev,uint32_t mtr_id,uint64_t * proto_mask,struct rte_mtr_error * error)903 cnxk_nix_mtr_in_proto_get(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
904 uint64_t *proto_mask, struct rte_mtr_error *error)
905 {
906 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
907 struct cnxk_meter_node *mtr;
908
909 mtr = nix_mtr_find(dev, mtr_id);
910 if (mtr == NULL) {
911 return -rte_mtr_error_set(error, ENOENT,
912 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
913 "Meter object not found");
914 }
915
916 *proto_mask = dev->proto;
917 return 0;
918 }
919
920 static int
cnxk_nix_mtr_in_proto_prio_get(struct rte_eth_dev * eth_dev,uint32_t mtr_id,enum rte_mtr_color_in_protocol proto,uint32_t * priority,struct rte_mtr_error * error)921 cnxk_nix_mtr_in_proto_prio_get(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
922 enum rte_mtr_color_in_protocol proto,
923 uint32_t *priority, struct rte_mtr_error *error)
924 {
925 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
926 struct cnxk_meter_node *mtr;
927
928 RTE_SET_USED(proto);
929
930 mtr = nix_mtr_find(dev, mtr_id);
931 if (mtr == NULL) {
932 return -rte_mtr_error_set(error, ENOENT,
933 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
934 "Meter object not found");
935 }
936
937 plt_info("Only single priority supported i.e. 0");
938 *priority = 0;
939 return 0;
940 }
941
942 static int
cnxk_nix_mtr_stats_update(struct rte_eth_dev * eth_dev,uint32_t mtr_id,uint64_t stats_mask,struct rte_mtr_error * error)943 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
944 uint64_t stats_mask, struct rte_mtr_error *error)
945 {
946 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
947 struct cnxk_meter_node *mtr;
948
949 if (!stats_mask)
950 return -rte_mtr_error_set(error, EINVAL,
951 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
952 "no bit is set to stats mask");
953
954 mtr = nix_mtr_find(dev, mtr_id);
955 if (mtr == NULL) {
956 return -rte_mtr_error_set(error, ENOENT,
957 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
958 "Meter object not found");
959 }
960
961 mtr->params.stats_mask = stats_mask;
962 return 0;
963 }
964
965 static int
cnxk_nix_mtr_stats_read(struct rte_eth_dev * eth_dev,uint32_t mtr_id,struct rte_mtr_stats * stats,uint64_t * stats_mask,int clear,struct rte_mtr_error * error)966 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
967 struct rte_mtr_stats *stats, uint64_t *stats_mask,
968 int clear, struct rte_mtr_error *error)
969 {
970 uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop;
971 uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop;
972 uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop;
973 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
974 uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop;
975 uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
976 uint64_t mask = NIX_BPF_STATS_MASK_ALL;
977 struct roc_nix *nix = &dev->nix;
978 struct cnxk_meter_node *mtr;
979 int rc;
980
981 if (!stats)
982 return -rte_mtr_error_set(error, EINVAL,
983 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
984 "stats pointer is NULL");
985
986 mtr = nix_mtr_find(dev, mtr_id);
987 if (mtr == NULL) {
988 return -rte_mtr_error_set(error, ENOENT,
989 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
990 "Meter object not found");
991 }
992
993 rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
994 bpf_stats);
995 if (rc) {
996 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
997 NULL, NULL);
998 goto exit;
999 }
1000
1001 green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
1002 green_octs_pass =
1003 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
1004 green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
1005 green_octs_drop =
1006 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
1007 yellow_pkt_pass =
1008 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
1009 yellow_octs_pass =
1010 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
1011 yellow_pkt_drop =
1012 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
1013 yellow_octs_drop =
1014 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
1015 red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
1016 red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
1017 red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
1018 red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
1019
1020 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
1021 stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
1022
1023 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
1024 stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
1025
1026 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
1027 stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
1028
1029 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
1030 stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
1031
1032 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
1033 stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
1034
1035 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
1036 stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
1037
1038 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
1039 stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
1040 bpf_stats[yellow_pkt_drop] +
1041 bpf_stats[red_pkt_drop];
1042
1043 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
1044 stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
1045 bpf_stats[yellow_octs_drop] +
1046 bpf_stats[red_octs_drop];
1047
1048 if (stats_mask)
1049 *stats_mask = mtr->params.stats_mask;
1050
1051 if (clear) {
1052 rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
1053 lvl_map[mtr->level]);
1054 if (rc) {
1055 rte_mtr_error_set(error, rc,
1056 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1057 NULL);
1058 goto exit;
1059 }
1060 }
1061
1062 exit:
1063 return rc;
1064 }
1065
1066 const struct rte_mtr_ops nix_mtr_ops = {
1067 .capabilities_get = cnxk_nix_mtr_capabilities_get,
1068 .meter_profile_add = cnxk_nix_mtr_profile_add,
1069 .meter_profile_delete = cnxk_nix_mtr_profile_delete,
1070 .meter_policy_validate = cnxk_nix_mtr_policy_validate,
1071 .meter_policy_add = cnxk_nix_mtr_policy_add,
1072 .meter_policy_delete = cnxk_nix_mtr_policy_delete,
1073 .create = cnxk_nix_mtr_create,
1074 .destroy = cnxk_nix_mtr_destroy,
1075 .meter_enable = cnxk_nix_mtr_enable,
1076 .meter_disable = cnxk_nix_mtr_disable,
1077 .meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update,
1078 .meter_vlan_table_update = cnxk_nix_mtr_vlan_table_update,
1079 .in_proto_set = cnxk_nix_mtr_in_proto_set,
1080 .in_proto_get = cnxk_nix_mtr_in_proto_get,
1081 .in_proto_prio_get = cnxk_nix_mtr_in_proto_prio_get,
1082 .stats_update = cnxk_nix_mtr_stats_update,
1083 .stats_read = cnxk_nix_mtr_stats_read,
1084 };
1085
1086 int
cnxk_nix_mtr_ops_get(struct rte_eth_dev * dev,void * ops)1087 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
1088 {
1089 RTE_SET_USED(dev);
1090
1091 *(const void **)ops = &nix_mtr_ops;
1092 return 0;
1093 }
1094
1095 int
nix_mtr_validate(struct rte_eth_dev * eth_dev,uint32_t id)1096 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)
1097 {
1098 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1099 struct cnxk_mtr_profile_node *profile;
1100 struct cnxk_mtr_policy_node *policy;
1101 struct cnxk_meter_node *mtr;
1102
1103 mtr = nix_mtr_find(dev, id);
1104 if (mtr == NULL)
1105 return -EINVAL;
1106
1107 profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
1108 if (profile == NULL)
1109 return -EINVAL;
1110
1111 policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
1112 if (policy == NULL)
1113 return -EINVAL;
1114
1115 return 0;
1116 }
1117
1118 int
nix_mtr_policy_act_get(struct rte_eth_dev * eth_dev,uint32_t id,struct cnxk_mtr_policy_node ** policy_act)1119 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,
1120 struct cnxk_mtr_policy_node **policy_act)
1121 {
1122 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1123 struct cnxk_mtr_policy_node *policy;
1124 struct cnxk_meter_node *mtr;
1125
1126 mtr = nix_mtr_find(dev, id);
1127 if (mtr == NULL)
1128 return -EINVAL;
1129
1130 policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
1131 if (policy == NULL)
1132 return -EINVAL;
1133
1134 *policy_act = policy;
1135
1136 return 0;
1137 }
1138
1139 int
nix_mtr_rq_update(struct rte_eth_dev * eth_dev,uint32_t id,uint32_t queue_num,const uint16_t * queue)1140 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,
1141 const uint16_t *queue)
1142 {
1143 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1144 struct cnxk_meter_node *mtr;
1145 uint32_t i;
1146
1147 mtr = nix_mtr_find(dev, id);
1148 if (mtr == NULL)
1149 return -EINVAL;
1150
1151 mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
1152 if (mtr->rq_id == NULL)
1153 return -ENOMEM;
1154
1155 mtr->rq_num = queue_num;
1156 for (i = 0; i < queue_num; i++)
1157 mtr->rq_id[i] = queue[i];
1158
1159 return 0;
1160 }
1161
1162 int
nix_mtr_chain_reset(struct rte_eth_dev * eth_dev,uint32_t cur_id)1163 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
1164 {
1165 struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1166 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1167 uint32_t mtr_id = cur_id;
1168 int i = 0, j = 0;
1169
1170 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1171 mtr[i] = nix_mtr_find(dev, mtr_id);
1172 if (mtr[i])
1173 mtr_id = mtr[i]->next_id;
1174 }
1175 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1176 if (mtr[i]) {
1177 for (j = 0; j < MAX_PRV_MTR_NODES; j++)
1178 mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
1179 mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1180 mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
1181 mtr[i]->is_next = false;
1182 mtr[i]->prev_cnt = 0;
1183 }
1184 }
1185 return 0;
1186 }
1187
1188 int
nix_mtr_chain_update(struct rte_eth_dev * eth_dev,uint32_t cur_id,uint32_t prev_id,uint32_t next_id)1189 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,
1190 uint32_t prev_id, uint32_t next_id)
1191 {
1192 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1193 struct cnxk_meter_node *mtr;
1194
1195 mtr = nix_mtr_find(dev, cur_id);
1196 if (mtr == NULL)
1197 return -EINVAL;
1198
1199 switch (lvl_map[mtr->level]) {
1200 case ROC_NIX_BPF_LEVEL_F_LEAF:
1201 mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
1202 mtr->next_id = next_id;
1203 mtr->is_next = true;
1204 break;
1205 case ROC_NIX_BPF_LEVEL_F_MID:
1206 mtr->prev_id[mtr->prev_cnt] = prev_id;
1207 mtr->next_id = next_id;
1208 mtr->is_next = true;
1209 break;
1210 case ROC_NIX_BPF_LEVEL_F_TOP:
1211 mtr->prev_id[mtr->prev_cnt] = prev_id;
1212 mtr->next_id = ROC_NIX_BPF_ID_INVALID;
1213 mtr->is_next = false;
1214 break;
1215 default:
1216 plt_err("Invalid meter level");
1217 return -EINVAL;
1218 }
1219
1220 return 0;
1221 }
1222
1223 struct cnxk_meter_node *
nix_get_mtr(struct rte_eth_dev * eth_dev,uint32_t id)1224 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)
1225 {
1226 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1227 struct cnxk_meter_node *mtr;
1228
1229 mtr = nix_mtr_find(dev, id);
1230 if (mtr == NULL)
1231 return NULL;
1232
1233 return mtr;
1234 }
1235
1236 int
nix_mtr_level_update(struct rte_eth_dev * eth_dev,uint32_t id,uint32_t level)1237 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)
1238 {
1239 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1240 struct cnxk_meter_node *mtr;
1241
1242 mtr = nix_mtr_find(dev, id);
1243 if (mtr == NULL)
1244 return -EINVAL;
1245
1246 mtr->level = level;
1247 return 0;
1248 }
1249
1250 static void
nix_mtr_config_map(struct cnxk_meter_node * mtr,struct roc_nix_bpf_cfg * cfg)1251 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
1252 {
1253 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1254 ROC_NIX_BPF_COLOR_YELLOW,
1255 ROC_NIX_BPF_COLOR_RED};
1256 enum roc_nix_bpf_algo alg_map[] = {
1257 ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,
1258 ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};
1259 struct cnxk_mtr_profile_node *profile = mtr->profile;
1260 struct cnxk_mtr_policy_node *policy = mtr->policy;
1261
1262 cfg->alg = alg_map[profile->profile.alg];
1263 cfg->lmode = profile->profile.packet_mode;
1264 cfg->icolor = color_map[mtr->params.default_input_color];
1265
1266 switch (RTE_MTR_COLOR_IN_PROTO_OUTER_IP) {
1267 case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
1268 cfg->pc_mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1269 cfg->tnl_ena = false;
1270 break;
1271 case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
1272 cfg->pc_mode = ROC_NIX_BPF_PC_MODE_DSCP_INNER;
1273 cfg->tnl_ena = true;
1274 break;
1275 case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
1276 cfg->pc_mode = ROC_NIX_BPF_PC_MODE_VLAN_OUTER;
1277 cfg->tnl_ena = false;
1278 break;
1279 case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
1280 cfg->pc_mode = ROC_NIX_BPF_PC_MODE_VLAN_INNER;
1281 cfg->tnl_ena = true;
1282 break;
1283 default:
1284 break;
1285 }
1286
1287 switch (cfg->alg) {
1288 case ROC_NIX_BPF_ALGO_2697:
1289 cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1290 cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1291 cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1292 break;
1293 case ROC_NIX_BPF_ALGO_2698:
1294 cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1295 cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1296 cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1297 cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1298 break;
1299 case ROC_NIX_BPF_ALGO_4115:
1300 cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1301 cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1302 cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1303 cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1304 break;
1305 default:
1306 break;
1307 }
1308
1309 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1310 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1311 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1312
1313 if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1314 RTE_FLOW_ACTION_TYPE_DROP)
1315 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1316
1317 if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1318 RTE_FLOW_ACTION_TYPE_DROP)
1319 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1320
1321 if (policy->actions[RTE_COLOR_RED].action_fate ==
1322 RTE_FLOW_ACTION_TYPE_DROP)
1323 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1324 }
1325
1326 static void
nix_mtr_config_red(struct cnxk_meter_node * mtr,struct roc_nix_rq * rq,struct roc_nix_bpf_cfg * cfg)1327 nix_mtr_config_red(struct cnxk_meter_node *mtr, struct roc_nix_rq *rq,
1328 struct roc_nix_bpf_cfg *cfg)
1329 {
1330 struct cnxk_mtr_policy_node *policy = mtr->policy;
1331
1332 if ((rq->red_pass && rq->red_pass >= rq->red_drop) ||
1333 (rq->spb_red_pass && rq->spb_red_pass >= rq->spb_red_drop) ||
1334 (rq->xqe_red_pass && rq->xqe_red_pass >= rq->xqe_red_drop)) {
1335 if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1336 RTE_FLOW_ACTION_TYPE_DROP) {
1337 if (policy->actions[RTE_COLOR_GREEN].skip_red)
1338 cfg->action[ROC_NIX_BPF_COLOR_GREEN] =
1339 ROC_NIX_BPF_ACTION_DROP;
1340 else
1341 cfg->action[ROC_NIX_BPF_COLOR_GREEN] =
1342 ROC_NIX_BPF_ACTION_RED;
1343 }
1344 if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1345 RTE_FLOW_ACTION_TYPE_DROP) {
1346 if (policy->actions[RTE_COLOR_YELLOW].skip_red)
1347 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] =
1348 ROC_NIX_BPF_ACTION_DROP;
1349 else
1350 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] =
1351 ROC_NIX_BPF_ACTION_RED;
1352 }
1353 if (policy->actions[RTE_COLOR_RED].action_fate ==
1354 RTE_FLOW_ACTION_TYPE_DROP) {
1355 if (policy->actions[RTE_COLOR_RED].skip_red)
1356 cfg->action[ROC_NIX_BPF_COLOR_RED] =
1357 ROC_NIX_BPF_ACTION_DROP;
1358 else
1359 cfg->action[ROC_NIX_BPF_COLOR_RED] =
1360 ROC_NIX_BPF_ACTION_RED;
1361 }
1362 }
1363 }
1364
1365 static void
nix_precolor_table_map(struct cnxk_meter_node * mtr,struct roc_nix_bpf_precolor * tbl,enum rte_mtr_color_in_protocol proto)1366 nix_precolor_table_map(struct cnxk_meter_node *mtr,
1367 struct roc_nix_bpf_precolor *tbl,
1368 enum rte_mtr_color_in_protocol proto)
1369 {
1370 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1371 ROC_NIX_BPF_COLOR_YELLOW,
1372 ROC_NIX_BPF_COLOR_RED};
1373 int i;
1374
1375 switch (proto) {
1376 case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
1377 case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
1378 tbl->count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP;
1379 tbl->mode = (proto == RTE_MTR_COLOR_IN_PROTO_OUTER_IP) ?
1380 ROC_NIX_BPF_PC_MODE_DSCP_OUTER :
1381 ROC_NIX_BPF_PC_MODE_DSCP_INNER;
1382
1383 for (i = 0; i < tbl->count; i++)
1384 tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1385
1386 if (mtr->params.dscp_table) {
1387 for (i = 0; i < tbl->count; i++)
1388 tbl->color[i] =
1389 color_map[mtr->params.dscp_table[i]];
1390 }
1391 break;
1392 case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
1393 case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
1394 tbl->count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN;
1395 tbl->mode = (proto == RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN) ?
1396 ROC_NIX_BPF_PC_MODE_VLAN_OUTER :
1397 ROC_NIX_BPF_PC_MODE_VLAN_INNER;
1398
1399 for (i = 0; i < tbl->count; i++)
1400 tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1401
1402 if (mtr->params.vlan_table) {
1403 for (i = 0; i < tbl->count; i++)
1404 tbl->color[i] =
1405 color_map[mtr->params.vlan_table[i]];
1406 }
1407 break;
1408 default:
1409 break;
1410 }
1411 }
1412
1413 int
nix_mtr_destroy(struct rte_eth_dev * eth_dev,uint32_t id,struct rte_mtr_error * error)1414 nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id,
1415 struct rte_mtr_error *error)
1416 {
1417 return cnxk_nix_mtr_destroy(eth_dev, id, error);
1418 }
1419
1420 int
nix_mtr_connect(struct rte_eth_dev * eth_dev,uint32_t id)1421 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)
1422 {
1423 enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1424 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1425 struct cnxk_meter_node *base_mtr, *next_mtr;
1426 struct roc_nix *nix = &dev->nix;
1427 uint32_t cur_mtr_id = id;
1428 int rc, i;
1429
1430 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1431 base_mtr = nix_mtr_find(dev, cur_mtr_id);
1432 if (base_mtr) {
1433 lvl_flag = lvl_map[base_mtr->level];
1434 if (base_mtr->is_next) {
1435 next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1436 if (next_mtr) {
1437 if (!base_mtr->is_used) {
1438 rc = roc_nix_bpf_connect(nix,
1439 lvl_flag,
1440 base_mtr->bpf_id,
1441 next_mtr->bpf_id);
1442 if (rc)
1443 return rc;
1444 }
1445 }
1446 cur_mtr_id = base_mtr->next_id;
1447 }
1448 }
1449 }
1450 return 0;
1451 }
1452
1453 int
nix_mtr_configure(struct rte_eth_dev * eth_dev,uint32_t id)1454 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1455 {
1456 struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1457 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1458 struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];
1459 uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1460 uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1461 uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1462 uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];
1463 int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1464 struct roc_nix *nix = &dev->nix;
1465 struct roc_nix_bpf_precolor tbl;
1466 struct roc_nix_bpf_cfg cfg;
1467 struct roc_nix_rq *rq;
1468 uint8_t lvl_mask;
1469 uint32_t i;
1470 uint32_t j;
1471 int rc;
1472
1473 mtr[0] = nix_mtr_find(dev, id);
1474 if (mtr[0] == NULL)
1475 return -EINVAL;
1476
1477 num_mtr[0] = 1;
1478 idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1479 if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1480 return -EINVAL;
1481
1482 lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1483 if (mtr[0]->is_used)
1484 per_lvl_cnt[idx0] = 0;
1485 else
1486 per_lvl_cnt[idx0] = 1;
1487
1488 if (mtr[0]->is_next) {
1489 mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1490 if (mtr[1] == NULL)
1491 return -EINVAL;
1492 num_mtr[1] = 1;
1493 idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1494 if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1495 return -EINVAL;
1496
1497 lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1498 if (mtr[1]->is_used)
1499 per_lvl_cnt[idx1] = 0;
1500 else
1501 per_lvl_cnt[idx1] = 1;
1502 }
1503
1504 if (mtr[1] && mtr[1]->is_next) {
1505 mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1506 if (mtr[2] == NULL)
1507 return -EINVAL;
1508
1509 num_mtr[2] = 1;
1510 idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1511 if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1512 return -EINVAL;
1513
1514 lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1515 if (mtr[2]->is_used)
1516 per_lvl_cnt[idx2] = 0;
1517 else
1518 per_lvl_cnt[idx2] = 1;
1519 }
1520
1521 rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1522 if (rc)
1523 return rc;
1524 if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1525 mtr[0]->bpf_id = profs[idx0].ids[0];
1526
1527 if (num_mtr[0])
1528 if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1529 if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1530 mtr[1]->bpf_id = profs[idx1].ids[0];
1531
1532 if (num_mtr[1])
1533 if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1534 if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1535 mtr[2]->bpf_id = profs[idx2].ids[0];
1536
1537 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1538 if (num_mtr[i]) {
1539 if (!mtr[i]->is_used) {
1540 memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1541 nix_mtr_config_map(mtr[i], &cfg);
1542 for (j = 0; j < mtr[i]->rq_num; j++) {
1543 rq = &dev->rqs[mtr[i]->rq_id[j]];
1544 nix_mtr_config_red(mtr[i], rq, &cfg);
1545 }
1546 rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1547 lvl_map[mtr[i]->level],
1548 &cfg);
1549
1550 memset(&tbl, 0,
1551 sizeof(struct roc_nix_bpf_precolor));
1552 nix_precolor_table_map(mtr[i], &tbl,
1553 dev->proto);
1554 rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1555 mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1556 &tbl);
1557
1558 if (mtr[i]->params.meter_enable) {
1559 for (j = 0; j < mtr[i]->rq_num; j++) {
1560 rq = &dev->rqs[mtr[i]->rq_id
1561 [j]];
1562 rc = roc_nix_bpf_ena_dis(nix,
1563 mtr[i]->bpf_id, rq,
1564 true);
1565 }
1566 }
1567 }
1568 }
1569 }
1570
1571 return rc;
1572 }
1573
1574 int
nix_mtr_color_action_validate(struct rte_eth_dev * eth_dev,uint32_t id,uint32_t * prev_id,uint32_t * next_id,struct cnxk_mtr_policy_node * policy,int * tree_level)1575 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,
1576 uint32_t *prev_id, uint32_t *next_id,
1577 struct cnxk_mtr_policy_node *policy,
1578 int *tree_level)
1579 {
1580 uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1581 uint32_t action_fate_green =
1582 policy->actions[RTE_COLOR_GREEN].action_fate;
1583 uint32_t action_fate_yellow =
1584 policy->actions[RTE_COLOR_YELLOW].action_fate;
1585 uint32_t cur_mtr_id = *next_id;
1586 uint32_t next_mtr_id = 0xffff;
1587 uint32_t prev_mtr_id = 0xffff;
1588 struct cnxk_meter_node *mtr;
1589
1590 if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1591 next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1592
1593 if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1594 next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1595
1596 if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1597 next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1598
1599 if (next_mtr_id != 0xffff) {
1600 switch (*tree_level) {
1601 case 0:
1602 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1603 if (mtr == NULL)
1604 return -EINVAL;
1605 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1606 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1607 nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1608 next_mtr_id);
1609 } else {
1610 if (mtr->level == 0)
1611 mtr->is_used = true;
1612 else
1613 return -EINVAL;
1614 }
1615 (*tree_level)++;
1616 *next_id = next_mtr_id;
1617 break;
1618 case 1:
1619 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1620 if (mtr == NULL)
1621 return -EINVAL;
1622 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1623 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1624 prev_mtr_id = id;
1625 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1626 prev_mtr_id, next_mtr_id);
1627 } else {
1628 if (mtr->level == 1) {
1629 mtr->prev_cnt++;
1630 prev_mtr_id = id;
1631 nix_mtr_chain_update(eth_dev,
1632 cur_mtr_id, prev_mtr_id,
1633 next_mtr_id);
1634
1635 mtr->is_used = true;
1636 } else {
1637 return -EINVAL;
1638 }
1639 }
1640 (*tree_level)++;
1641 *next_id = next_mtr_id;
1642 *prev_id = cur_mtr_id;
1643 break;
1644 case 2:
1645 nix_mtr_chain_reset(eth_dev, id);
1646 return -EINVAL;
1647 }
1648 } else {
1649 switch (*tree_level) {
1650 case 0:
1651 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1652 if (mtr == NULL)
1653 return -EINVAL;
1654 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1655 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1656 } else {
1657 if (mtr->level == 0)
1658 mtr->is_used = true;
1659 else
1660 return -EINVAL;
1661 }
1662 break;
1663 case 1:
1664 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1665 if (mtr == NULL)
1666 return -EINVAL;
1667 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1668 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1669 prev_mtr_id = id;
1670 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1671 prev_mtr_id, -1);
1672 } else {
1673 if (mtr->level == 1) {
1674 mtr->prev_cnt++;
1675 prev_mtr_id = id;
1676 nix_mtr_chain_update(eth_dev,
1677 cur_mtr_id,
1678 prev_mtr_id, -1);
1679 mtr->is_used = true;
1680 } else {
1681 return -EINVAL;
1682 }
1683 }
1684 break;
1685 case 2:
1686 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1687 if (mtr == NULL)
1688 return -EINVAL;
1689 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1690 nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1691 prev_mtr_id = *prev_id;
1692 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1693 prev_mtr_id, -1);
1694 } else {
1695 if (mtr->level == 2) {
1696 mtr->prev_cnt++;
1697 prev_mtr_id = *prev_id;
1698 nix_mtr_chain_update(eth_dev,
1699 cur_mtr_id,
1700 prev_mtr_id, -1);
1701 mtr->is_used = true;
1702 } else {
1703 return -EINVAL;
1704 }
1705 }
1706 break;
1707 }
1708 *next_id = 0xffff;
1709 }
1710
1711 return 0;
1712 }
1713
1714 int
nix_mtr_capabilities_init(struct rte_eth_dev * eth_dev)1715 nix_mtr_capabilities_init(struct rte_eth_dev *eth_dev)
1716 {
1717 struct rte_mtr_capabilities capa;
1718 struct rte_mtr_error error;
1719
1720 return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error);
1721 }
1722