1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
5 #include "cnxk_ethdev.h"
6 #include <rte_mtr_driver.h>
8 #define NIX_MTR_COUNT_MAX 73 /* 64(leaf) + 8(mid) + 1(top) */
9 #define NIX_MTR_COUNT_PER_FLOW 3 /* 1(leaf) + 1(mid) + 1(top) */
11 #define NIX_BPF_STATS_MASK_ALL \
13 ROC_NIX_BPF_GREEN_PKT_F_PASS | ROC_NIX_BPF_GREEN_OCTS_F_PASS | \
14 ROC_NIX_BPF_GREEN_PKT_F_DROP | \
15 ROC_NIX_BPF_GREEN_OCTS_F_DROP | \
16 ROC_NIX_BPF_YELLOW_PKT_F_PASS | \
17 ROC_NIX_BPF_YELLOW_OCTS_F_PASS | \
18 ROC_NIX_BPF_YELLOW_PKT_F_DROP | \
19 ROC_NIX_BPF_YELLOW_OCTS_F_DROP | \
20 ROC_NIX_BPF_RED_PKT_F_PASS | \
21 ROC_NIX_BPF_RED_OCTS_F_PASS | \
22 ROC_NIX_BPF_RED_PKT_F_DROP | \
23 ROC_NIX_BPF_RED_OCTS_F_DROP \
26 static const enum roc_nix_bpf_level_flag lvl_map[] = {ROC_NIX_BPF_LEVEL_F_LEAF,
27 ROC_NIX_BPF_LEVEL_F_MID,
28 ROC_NIX_BPF_LEVEL_F_TOP};
30 static struct rte_mtr_capabilities mtr_capa = {
31 .n_max = NIX_MTR_COUNT_MAX,
32 .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
34 .shared_identical = true,
35 /* .shared_n_flows_per_mtr_max = ,*/
36 .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
37 .chaining_use_prev_mtr_color_supported = true,
38 .chaining_use_prev_mtr_color_enforced = true,
39 .meter_srtcm_rfc2697_n_max = NIX_MTR_COUNT_MAX,
40 .meter_trtcm_rfc2698_n_max = NIX_MTR_COUNT_MAX,
41 .meter_trtcm_rfc4115_n_max = NIX_MTR_COUNT_MAX,
42 .meter_rate_max = NIX_BPF_RATE_MAX / 8, /* Bytes per second */
43 .meter_policy_n_max = NIX_MTR_COUNT_MAX,
44 .color_aware_srtcm_rfc2697_supported = true,
45 .color_aware_trtcm_rfc2698_supported = true,
46 .color_aware_trtcm_rfc4115_supported = true,
47 .srtcm_rfc2697_byte_mode_supported = true,
48 .srtcm_rfc2697_packet_mode_supported = true,
49 .trtcm_rfc2698_byte_mode_supported = true,
50 .trtcm_rfc2698_packet_mode_supported = true,
51 .trtcm_rfc4115_byte_mode_supported = true,
52 .trtcm_rfc4115_packet_mode_supported = true,
53 .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
54 RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
55 RTE_MTR_STATS_N_BYTES_GREEN |
56 RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
57 RTE_MTR_STATS_N_BYTES_DROPPED};
59 static struct cnxk_meter_node *
60 nix_mtr_find(struct cnxk_eth_dev *dev, uint32_t meter_id)
62 struct cnxk_mtr *fms = &dev->mtr;
63 struct cnxk_meter_node *fm;
65 TAILQ_FOREACH(fm, fms, next)
66 if (meter_id == fm->id)
71 static struct cnxk_mtr_profile_node *
72 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
74 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
75 struct cnxk_mtr_profile_node *fmp;
77 TAILQ_FOREACH(fmp, fmps, next)
78 if (profile_id == fmp->id)
84 static struct cnxk_mtr_policy_node *
85 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
87 struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
88 struct cnxk_mtr_policy_node *fmp;
90 TAILQ_FOREACH(fmp, fmps, next)
91 if (meter_policy_id == fmp->id)
97 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
98 struct rte_mtr_meter_profile *profile,
99 struct rte_mtr_error *error)
106 return -rte_mtr_error_set(error, EINVAL,
107 RTE_MTR_ERROR_TYPE_METER_PROFILE,
108 NULL, "Meter profile is null.");
110 if (profile_id == UINT32_MAX)
111 return -rte_mtr_error_set(error, EINVAL,
112 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
113 NULL, "Meter profile id not valid.");
115 switch (profile->alg) {
116 case RTE_MTR_SRTCM_RFC2697:
117 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
118 rc = -rte_mtr_error_set(error, EINVAL,
119 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
120 "CIR exceeds max meter rate");
122 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
123 rc = -rte_mtr_error_set(error, EINVAL,
124 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
125 "CBS exceeds max meter burst size");
127 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
128 rc = -rte_mtr_error_set(error, EINVAL,
129 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
130 "EBS exceeds max meter burst size");
133 case RTE_MTR_TRTCM_RFC2698:
134 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
135 rc = -rte_mtr_error_set(error, EINVAL,
136 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
137 "CIR exceeds max meter rate");
139 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
140 rc = -rte_mtr_error_set(error, EINVAL,
141 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
142 "PIR exceeds max meter rate");
144 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
145 rc = -rte_mtr_error_set(error, EINVAL,
146 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
147 "CBS exceeds max meter burst size");
149 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
150 rc = -rte_mtr_error_set(error, EINVAL,
151 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
152 "PBS exceeds max meter burst size");
155 case RTE_MTR_TRTCM_RFC4115:
156 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
157 mtr_capa.meter_rate_max)
158 rc = -rte_mtr_error_set(error, EINVAL,
159 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
160 "PIR + EIR exceeds max rate");
162 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
163 rc = -rte_mtr_error_set(error, EINVAL,
164 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
165 "CBS exceeds max meter burst size");
167 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
168 rc = -rte_mtr_error_set(error, EINVAL,
169 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
170 "PBS exceeds max meter burst size");
174 rc = -rte_mtr_error_set(error, EINVAL,
175 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
184 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
185 struct rte_mtr_capabilities *capa,
186 struct rte_mtr_error *error)
191 return -rte_mtr_error_set(error, EINVAL,
192 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
193 "NULL input parameter");
199 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
200 struct rte_mtr_meter_profile *profile,
201 struct rte_mtr_error *error)
203 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
204 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
205 struct cnxk_mtr_profile_node *fmp;
208 /* Check input params. */
209 ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
213 fmp = nix_mtr_profile_find(dev, profile_id);
215 return -rte_mtr_error_set(error, EEXIST,
216 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
217 NULL, "Profile already exist");
220 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
222 return -rte_mtr_error_set(error, ENOMEM,
223 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
224 "Meter profile memory "
227 fmp->id = profile_id;
228 fmp->profile = *profile;
230 TAILQ_INSERT_TAIL(fmps, fmp, next);
236 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
237 struct rte_mtr_error *error)
239 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
240 struct cnxk_mtr_profile_node *fmp;
242 if (profile_id == UINT32_MAX)
243 return -rte_mtr_error_set(error, EINVAL,
244 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
245 NULL, "Meter profile id not valid.");
247 fmp = nix_mtr_profile_find(dev, profile_id);
249 return -rte_mtr_error_set(error, ENOENT,
250 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
252 "Meter profile is invalid.");
255 return -rte_mtr_error_set(error, EBUSY,
256 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
257 NULL, "Meter profile is in use.");
259 TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
265 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
266 struct rte_mtr_meter_policy_params *policy,
267 struct rte_mtr_error *error)
269 static const char *const action_color[] = {"Green", "Yellow", "Red"};
270 bool supported[RTE_COLORS] = {false, false, false};
271 const struct rte_flow_action *action;
278 return 0; /* Nothing to be validated */
280 for (i = 0; i < RTE_COLORS; i++) {
281 if (policy->actions[i]) {
282 for (action = policy->actions[i];
283 action->type != RTE_FLOW_ACTION_TYPE_END;
285 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
288 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
293 "%s action is not valid",
295 return -rte_mtr_error_set(error,
297 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
302 sprintf(message, "%s action is null", action_color[i]);
303 return -rte_mtr_error_set(error, EINVAL,
304 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
313 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
314 struct rte_mtr_meter_policy_params *policy)
317 const struct rte_flow_action_meter *mtr;
318 const struct rte_flow_action *action;
321 for (i = 0; i < RTE_COLORS; i++) {
322 if (policy->actions[i]) {
323 for (action = policy->actions[i];
324 action->type != RTE_FLOW_ACTION_TYPE_END;
327 RTE_FLOW_ACTION_TYPE_METER) {
328 fmp->actions[i].action_fate =
331 rte_flow_action_meter *)
333 fmp->actions[i].mtr_id = mtr->mtr_id;
336 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
337 fmp->actions[i].action_fate =
346 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
347 struct rte_mtr_meter_policy_params *policy,
348 struct rte_mtr_error *error)
350 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
351 struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
352 struct cnxk_mtr_policy_node *fmp;
355 fmp = nix_mtr_policy_find(dev, policy_id);
357 return -rte_mtr_error_set(error, EEXIST,
358 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
359 NULL, "Policy already exist");
362 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
364 return -rte_mtr_error_set(error, ENOMEM,
365 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
366 "Memory allocation failure");
368 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
374 cnxk_fill_policy_actions(fmp, policy);
375 TAILQ_INSERT_TAIL(fmps, fmp, next);
384 cnxk_nix_mtr_policy_delete(struct rte_eth_dev *eth_dev, uint32_t policy_id,
385 struct rte_mtr_error *error)
387 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
388 struct cnxk_mtr_policy_node *fmp;
390 fmp = nix_mtr_policy_find(dev, policy_id);
392 return -rte_mtr_error_set(error, ENOENT,
393 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
394 NULL, "No policy found");
398 return -rte_mtr_error_set(error, EBUSY,
399 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
400 NULL, "Meter policy is in use.");
402 TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
409 cnxk_nix_mtr_create(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
410 struct rte_mtr_params *params, int shared,
411 struct rte_mtr_error *error)
413 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
414 struct cnxk_mtr_profile_node *profile;
415 struct cnxk_mtr_policy_node *policy;
416 struct cnxk_mtr *fm = &dev->mtr;
417 struct cnxk_meter_node *mtr;
420 RTE_SET_USED(shared);
423 return -rte_mtr_error_set(error, ENOENT,
424 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
425 "Meter params are invalid.");
427 profile = nix_mtr_profile_find(dev, params->meter_profile_id);
429 return -rte_mtr_error_set(error, ENOENT,
430 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
431 ¶ms->meter_profile_id,
432 "Meter profile is invalid.");
434 policy = nix_mtr_policy_find(dev, params->meter_policy_id);
436 return -rte_mtr_error_set(error, ENOENT,
437 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
438 ¶ms->meter_policy_id,
439 "Meter policy is invalid.");
441 mtr = nix_mtr_find(dev, mtr_id);
443 return -rte_mtr_error_set(error, EEXIST,
444 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
445 "Meter already exist");
448 mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
450 return -rte_mtr_error_set(error, ENOMEM,
451 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
452 "Meter memory alloc failed.");
456 mtr->profile = profile;
457 mtr->policy = policy;
458 mtr->params = *params;
459 mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
461 for (i = 0; i < MAX_PRV_MTR_NODES; i++)
462 mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
464 mtr->next_id = ROC_NIX_BPF_ID_INVALID;
465 mtr->is_next = false;
466 mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
468 if (params->dscp_table) {
469 mtr->params.dscp_table =
470 plt_zmalloc(ROC_NIX_BPF_PRE_COLOR_MAX, ROC_ALIGN);
471 if (mtr->params.dscp_table == NULL) {
473 return -rte_mtr_error_set(error, ENOMEM,
474 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
475 NULL, "Memory alloc failed.");
478 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
479 mtr->params.dscp_table[i] = params->dscp_table[i];
484 TAILQ_INSERT_TAIL(fm, mtr, next);
489 cnxk_nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
490 struct rte_mtr_error *error)
492 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
493 struct roc_nix_bpf_objs profs = {0};
494 struct cnxk_mtr *fm = &dev->mtr;
495 struct roc_nix *nix = &dev->nix;
496 struct cnxk_meter_node *mtr;
497 struct cnxk_meter_node *mid_mtr;
498 struct cnxk_meter_node *top_mtr;
501 mtr = nix_mtr_find(dev, mtr_id);
503 return -rte_mtr_error_set(error, ENOENT,
504 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
505 "Meter id is invalid.");
509 return -rte_mtr_error_set(error, EADDRINUSE,
510 RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
514 switch (lvl_map[mtr->level]) {
515 case ROC_NIX_BPF_LEVEL_F_LEAF:
517 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
519 ROC_NIX_BPF_ID_INVALID);
522 case ROC_NIX_BPF_LEVEL_F_MID:
523 while ((mtr->prev_cnt) + 1) {
525 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
526 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
528 ROC_NIX_BPF_ID_INVALID);
532 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
534 ROC_NIX_BPF_ID_INVALID);
537 case ROC_NIX_BPF_LEVEL_F_TOP:
538 while (mtr->prev_cnt) {
540 nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
541 rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
543 ROC_NIX_BPF_ID_INVALID);
548 return -rte_mtr_error_set(error, EINVAL,
549 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
550 "Invalid meter level");
556 profs.level = mtr->level;
558 profs.ids[0] = mtr->bpf_id;
559 rc = roc_nix_bpf_free(nix, &profs, 1);
563 mtr->policy->ref_cnt--;
564 mtr->profile->ref_cnt--;
565 TAILQ_REMOVE(fm, mtr, next);
566 plt_free(mtr->params.dscp_table);
574 cnxk_nix_mtr_enable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
575 struct rte_mtr_error *error)
577 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
578 struct roc_nix *nix = &dev->nix;
579 struct cnxk_meter_node *mtr;
580 struct roc_nix_rq *rq;
584 mtr = nix_mtr_find(dev, mtr_id);
586 return -rte_mtr_error_set(error, ENOENT,
587 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
588 "Meter id is invalid.");
594 for (i = 0; i < mtr->rq_num; i++) {
595 rq = &dev->rqs[mtr->rq_id[i]];
596 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
603 cnxk_nix_mtr_disable(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
604 struct rte_mtr_error *error)
606 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
607 struct roc_nix *nix = &dev->nix;
608 struct cnxk_meter_node *mtr;
609 struct roc_nix_rq *rq;
613 mtr = nix_mtr_find(dev, mtr_id);
615 return -rte_mtr_error_set(error, ENOENT,
616 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
617 "Meter id is invalid.");
623 for (i = 0; i < mtr->rq_num; i++) {
624 rq = &dev->rqs[mtr->rq_id[i]];
625 rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false);
632 cnxk_nix_mtr_dscp_table_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
633 enum rte_color *dscp_table,
634 struct rte_mtr_error *error)
636 enum roc_nix_bpf_color nix_dscp_tbl[ROC_NIX_BPF_PRE_COLOR_MAX];
637 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
638 ROC_NIX_BPF_COLOR_YELLOW,
639 ROC_NIX_BPF_COLOR_RED};
640 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
641 struct roc_nix_bpf_precolor table;
642 struct roc_nix *nix = &dev->nix;
643 struct cnxk_meter_node *mtr;
646 mtr = nix_mtr_find(dev, mtr_id);
648 return -rte_mtr_error_set(error, ENOENT,
649 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
650 "Meter object not found");
654 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
655 nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
657 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
658 nix_dscp_tbl[i] = color_map[dscp_table[i]];
661 table.count = ROC_NIX_BPF_PRE_COLOR_MAX;
662 table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
663 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
664 table.color[i] = nix_dscp_tbl[i];
666 rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
667 lvl_map[mtr->level], &table);
669 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
674 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
675 dev->precolor_tbl[i] = nix_dscp_tbl[i];
682 cnxk_nix_mtr_stats_update(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
683 uint64_t stats_mask, struct rte_mtr_error *error)
685 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
686 struct cnxk_meter_node *mtr;
689 return -rte_mtr_error_set(error, EINVAL,
690 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
691 "no bit is set to stats mask");
693 mtr = nix_mtr_find(dev, mtr_id);
695 return -rte_mtr_error_set(error, ENOENT,
696 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
697 "Meter object not found");
700 mtr->params.stats_mask = stats_mask;
705 cnxk_nix_mtr_stats_read(struct rte_eth_dev *eth_dev, uint32_t mtr_id,
706 struct rte_mtr_stats *stats, uint64_t *stats_mask,
707 int clear, struct rte_mtr_error *error)
709 uint8_t yellow_pkt_pass, yellow_octs_pass, yellow_pkt_drop;
710 uint8_t green_octs_drop, yellow_octs_drop, red_octs_drop;
711 uint8_t green_pkt_pass, green_octs_pass, green_pkt_drop;
712 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
713 uint8_t red_pkt_pass, red_octs_pass, red_pkt_drop;
714 uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
715 uint64_t mask = NIX_BPF_STATS_MASK_ALL;
716 struct roc_nix *nix = &dev->nix;
717 struct cnxk_meter_node *mtr;
721 return -rte_mtr_error_set(error, EINVAL,
722 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
723 "stats pointer is NULL");
725 mtr = nix_mtr_find(dev, mtr_id);
727 return -rte_mtr_error_set(error, ENOENT,
728 RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
729 "Meter object not found");
732 rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
735 rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
740 green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
742 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
743 green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
745 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
747 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
749 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
751 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
753 roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
754 red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
755 red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
756 red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
757 red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
759 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
760 stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
762 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
763 stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
765 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
766 stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
768 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
769 stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
771 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
772 stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
774 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
775 stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
777 if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
778 stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
779 bpf_stats[yellow_pkt_drop] +
780 bpf_stats[red_pkt_drop];
782 if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
783 stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
784 bpf_stats[yellow_octs_drop] +
785 bpf_stats[red_octs_drop];
788 *stats_mask = mtr->params.stats_mask;
791 rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
792 lvl_map[mtr->level]);
794 rte_mtr_error_set(error, rc,
795 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
805 const struct rte_mtr_ops nix_mtr_ops = {
806 .capabilities_get = cnxk_nix_mtr_capabilities_get,
807 .meter_profile_add = cnxk_nix_mtr_profile_add,
808 .meter_profile_delete = cnxk_nix_mtr_profile_delete,
809 .meter_policy_validate = cnxk_nix_mtr_policy_validate,
810 .meter_policy_add = cnxk_nix_mtr_policy_add,
811 .meter_policy_delete = cnxk_nix_mtr_policy_delete,
812 .create = cnxk_nix_mtr_create,
813 .destroy = cnxk_nix_mtr_destroy,
814 .meter_enable = cnxk_nix_mtr_enable,
815 .meter_disable = cnxk_nix_mtr_disable,
816 .meter_dscp_table_update = cnxk_nix_mtr_dscp_table_update,
817 .stats_update = cnxk_nix_mtr_stats_update,
818 .stats_read = cnxk_nix_mtr_stats_read,
822 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
826 *(const void **)ops = &nix_mtr_ops;
831 nix_mtr_validate(struct rte_eth_dev *eth_dev, uint32_t id)
833 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
834 struct cnxk_mtr_profile_node *profile;
835 struct cnxk_mtr_policy_node *policy;
836 struct cnxk_meter_node *mtr;
838 mtr = nix_mtr_find(dev, id);
842 profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
846 policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
854 nix_mtr_policy_act_get(struct rte_eth_dev *eth_dev, uint32_t id,
855 struct cnxk_mtr_policy_node **policy_act)
857 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
858 struct cnxk_mtr_policy_node *policy;
859 struct cnxk_meter_node *mtr;
861 mtr = nix_mtr_find(dev, id);
865 policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
869 *policy_act = policy;
875 nix_mtr_rq_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t queue_num,
876 const uint16_t *queue)
878 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
879 struct cnxk_meter_node *mtr;
882 mtr = nix_mtr_find(dev, id);
886 mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
887 if (mtr->rq_id == NULL)
890 mtr->rq_num = queue_num;
891 for (i = 0; i < queue_num; i++)
892 mtr->rq_id[i] = queue[i];
898 nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
900 struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
901 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
902 uint32_t mtr_id = cur_id;
905 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
906 mtr[i] = nix_mtr_find(dev, mtr_id);
908 mtr_id = mtr[i]->next_id;
910 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
912 for (j = 0; j < MAX_PRV_MTR_NODES; j++)
913 mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
914 mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
915 mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
916 mtr[i]->is_next = false;
917 mtr[i]->prev_cnt = 0;
924 nix_mtr_chain_update(struct rte_eth_dev *eth_dev, uint32_t cur_id,
925 uint32_t prev_id, uint32_t next_id)
927 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
928 struct cnxk_meter_node *mtr;
930 mtr = nix_mtr_find(dev, cur_id);
934 switch (lvl_map[mtr->level]) {
935 case ROC_NIX_BPF_LEVEL_F_LEAF:
936 mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
937 mtr->next_id = next_id;
940 case ROC_NIX_BPF_LEVEL_F_MID:
941 mtr->prev_id[mtr->prev_cnt] = prev_id;
942 mtr->next_id = next_id;
945 case ROC_NIX_BPF_LEVEL_F_TOP:
946 mtr->prev_id[mtr->prev_cnt] = prev_id;
947 mtr->next_id = ROC_NIX_BPF_ID_INVALID;
948 mtr->is_next = false;
951 plt_err("Invalid meter level");
958 struct cnxk_meter_node *
959 nix_get_mtr(struct rte_eth_dev *eth_dev, uint32_t id)
961 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
962 struct cnxk_meter_node *mtr;
964 mtr = nix_mtr_find(dev, id);
972 nix_mtr_level_update(struct rte_eth_dev *eth_dev, uint32_t id, uint32_t level)
974 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
975 struct cnxk_meter_node *mtr;
977 mtr = nix_mtr_find(dev, id);
986 nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
988 enum roc_nix_bpf_algo alg_map[] = {
989 ROC_NIX_BPF_ALGO_NONE, ROC_NIX_BPF_ALGO_2697,
990 ROC_NIX_BPF_ALGO_2698, ROC_NIX_BPF_ALGO_4115};
991 struct cnxk_mtr_profile_node *profile = mtr->profile;
992 struct cnxk_mtr_policy_node *policy = mtr->policy;
994 cfg->alg = alg_map[profile->profile.alg];
995 cfg->lmode = profile->profile.packet_mode;
998 case ROC_NIX_BPF_ALGO_2697:
999 cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1000 cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1001 cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1003 case ROC_NIX_BPF_ALGO_2698:
1004 cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1005 cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1006 cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1007 cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1009 case ROC_NIX_BPF_ALGO_4115:
1010 cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1011 cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1012 cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1013 cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1019 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1020 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1021 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1023 if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1024 RTE_FLOW_ACTION_TYPE_DROP)
1025 cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1027 if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1028 RTE_FLOW_ACTION_TYPE_DROP)
1029 cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1031 if (policy->actions[RTE_COLOR_RED].action_fate ==
1032 RTE_FLOW_ACTION_TYPE_DROP)
1033 cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1037 nix_dscp_table_map(struct cnxk_meter_node *mtr,
1038 struct roc_nix_bpf_precolor *tbl)
1040 enum roc_nix_bpf_color color_map[] = {ROC_NIX_BPF_COLOR_GREEN,
1041 ROC_NIX_BPF_COLOR_YELLOW,
1042 ROC_NIX_BPF_COLOR_RED};
1045 tbl->count = ROC_NIX_BPF_PRE_COLOR_MAX;
1046 tbl->mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1048 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1049 tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1051 if (mtr->params.dscp_table) {
1052 for (i = 0; i < ROC_NIX_BPF_PRE_COLOR_MAX; i++)
1053 tbl->color[i] = color_map[mtr->params.dscp_table[i]];
1058 nix_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t id)
1060 enum roc_nix_bpf_level_flag lvl_flag = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1061 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1062 struct cnxk_meter_node *base_mtr, *next_mtr;
1063 struct roc_nix *nix = &dev->nix;
1064 uint32_t cur_mtr_id = id;
1067 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1068 base_mtr = nix_mtr_find(dev, cur_mtr_id);
1070 lvl_flag = lvl_map[base_mtr->level];
1071 if (base_mtr->is_next) {
1072 next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1074 if (!base_mtr->is_used) {
1075 rc = roc_nix_bpf_connect(nix,
1083 cur_mtr_id = base_mtr->next_id;
1091 nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1093 struct cnxk_meter_node *mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1094 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
1095 struct roc_nix_bpf_objs profs[ROC_NIX_BPF_LEVEL_MAX];
1096 uint8_t idx0 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1097 uint8_t idx1 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1098 uint8_t idx2 = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1099 uint16_t per_lvl_cnt[ROC_NIX_BPF_LEVEL_MAX];
1100 int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1101 struct roc_nix *nix = &dev->nix;
1102 struct roc_nix_bpf_precolor tbl;
1103 struct roc_nix_bpf_cfg cfg;
1104 struct roc_nix_rq *rq;
1110 mtr[0] = nix_mtr_find(dev, id);
1115 idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1116 if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1119 lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1120 if (mtr[0]->is_used)
1121 per_lvl_cnt[idx0] = 0;
1123 per_lvl_cnt[idx0] = 1;
1125 if (mtr[0]->is_next) {
1126 mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1130 idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1131 if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1134 lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1135 if (mtr[1]->is_used)
1136 per_lvl_cnt[idx1] = 0;
1138 per_lvl_cnt[idx1] = 1;
1141 if (mtr[1] && mtr[1]->is_next) {
1142 mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1147 idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1148 if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1151 lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1152 if (mtr[2]->is_used)
1153 per_lvl_cnt[idx2] = 0;
1155 per_lvl_cnt[idx2] = 1;
1158 rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1161 if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1162 mtr[0]->bpf_id = profs[idx0].ids[0];
1165 if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1166 if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1167 mtr[1]->bpf_id = profs[idx1].ids[0];
1170 if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1171 if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1172 mtr[2]->bpf_id = profs[idx2].ids[0];
1174 for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1176 if (!mtr[i]->is_used) {
1177 memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1178 nix_mtr_config_map(mtr[i], &cfg);
1179 rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1180 lvl_map[mtr[i]->level],
1184 sizeof(struct roc_nix_bpf_precolor));
1185 nix_dscp_table_map(mtr[i], &tbl);
1186 rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1187 mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1190 if (mtr[i]->params.meter_enable) {
1191 for (j = 0; j < mtr[i]->rq_num; j++) {
1192 rq = &dev->rqs[mtr[i]->rq_id
1194 rc = roc_nix_bpf_ena_dis(nix,
1207 nix_mtr_color_action_validate(struct rte_eth_dev *eth_dev, uint32_t id,
1208 uint32_t *prev_id, uint32_t *next_id,
1209 struct cnxk_mtr_policy_node *policy,
1212 uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1213 uint32_t action_fate_green =
1214 policy->actions[RTE_COLOR_GREEN].action_fate;
1215 uint32_t action_fate_yellow =
1216 policy->actions[RTE_COLOR_YELLOW].action_fate;
1217 uint32_t cur_mtr_id = *next_id;
1218 uint32_t next_mtr_id = 0xffff;
1219 uint32_t prev_mtr_id = 0xffff;
1220 struct cnxk_meter_node *mtr;
1222 if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1223 next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1225 if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1226 next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1228 if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1229 next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1231 if (next_mtr_id != 0xffff) {
1232 switch (*tree_level) {
1234 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1235 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1236 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1237 nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1240 if (mtr->level == 0)
1241 mtr->is_used = true;
1246 *next_id = next_mtr_id;
1249 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1250 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1251 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1253 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1254 prev_mtr_id, next_mtr_id);
1256 if (mtr->level == 1) {
1259 nix_mtr_chain_update(eth_dev,
1260 cur_mtr_id, prev_mtr_id,
1263 mtr->is_used = true;
1269 *next_id = next_mtr_id;
1270 *prev_id = cur_mtr_id;
1273 nix_mtr_chain_reset(eth_dev, id);
1277 switch (*tree_level) {
1279 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1280 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1281 nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1283 if (mtr->level == 0)
1284 mtr->is_used = true;
1290 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1291 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1292 nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1294 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1297 if (mtr->level == 1) {
1300 nix_mtr_chain_update(eth_dev,
1303 mtr->is_used = true;
1310 mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1311 if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1312 nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1313 prev_mtr_id = *prev_id;
1314 nix_mtr_chain_update(eth_dev, cur_mtr_id,
1317 if (mtr->level == 2) {
1319 prev_mtr_id = *prev_id;
1320 nix_mtr_chain_update(eth_dev,
1323 mtr->is_used = true;