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 static struct rte_mtr_capabilities mtr_capa = {
12 .n_max = NIX_MTR_COUNT_MAX,
13 .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
15 .shared_identical = true,
16 /* .shared_n_flows_per_mtr_max = ,*/
17 .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
18 .chaining_use_prev_mtr_color_supported = true,
19 .chaining_use_prev_mtr_color_enforced = true,
20 .meter_srtcm_rfc2697_n_max = NIX_MTR_COUNT_MAX,
21 .meter_trtcm_rfc2698_n_max = NIX_MTR_COUNT_MAX,
22 .meter_trtcm_rfc4115_n_max = NIX_MTR_COUNT_MAX,
23 .meter_rate_max = NIX_BPF_RATE_MAX / 8, /* Bytes per second */
24 .meter_policy_n_max = NIX_MTR_COUNT_MAX,
25 .color_aware_srtcm_rfc2697_supported = true,
26 .color_aware_trtcm_rfc2698_supported = true,
27 .color_aware_trtcm_rfc4115_supported = true,
28 .srtcm_rfc2697_byte_mode_supported = true,
29 .srtcm_rfc2697_packet_mode_supported = true,
30 .trtcm_rfc2698_byte_mode_supported = true,
31 .trtcm_rfc2698_packet_mode_supported = true,
32 .trtcm_rfc4115_byte_mode_supported = true,
33 .trtcm_rfc4115_packet_mode_supported = true,
34 .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
35 RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
36 RTE_MTR_STATS_N_BYTES_GREEN |
37 RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
38 RTE_MTR_STATS_N_BYTES_DROPPED};
40 static struct cnxk_mtr_profile_node *
41 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
43 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
44 struct cnxk_mtr_profile_node *fmp;
46 TAILQ_FOREACH(fmp, fmps, next)
47 if (profile_id == fmp->id)
54 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
55 struct rte_mtr_meter_profile *profile,
56 struct rte_mtr_error *error)
63 return -rte_mtr_error_set(error, EINVAL,
64 RTE_MTR_ERROR_TYPE_METER_PROFILE,
65 NULL, "Meter profile is null.");
67 if (profile_id == UINT32_MAX)
68 return -rte_mtr_error_set(error, EINVAL,
69 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
70 NULL, "Meter profile id not valid.");
72 switch (profile->alg) {
73 case RTE_MTR_SRTCM_RFC2697:
74 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
75 rc = -rte_mtr_error_set(error, EINVAL,
76 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
77 "CIR exceeds max meter rate");
79 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
80 rc = -rte_mtr_error_set(error, EINVAL,
81 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
82 "CBS exceeds max meter burst size");
84 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
85 rc = -rte_mtr_error_set(error, EINVAL,
86 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
87 "EBS exceeds max meter burst size");
90 case RTE_MTR_TRTCM_RFC2698:
91 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
92 rc = -rte_mtr_error_set(error, EINVAL,
93 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
94 "CIR exceeds max meter rate");
96 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
97 rc = -rte_mtr_error_set(error, EINVAL,
98 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
99 "PIR exceeds max meter rate");
101 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
102 rc = -rte_mtr_error_set(error, EINVAL,
103 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
104 "CBS exceeds max meter burst size");
106 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
107 rc = -rte_mtr_error_set(error, EINVAL,
108 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
109 "PBS exceeds max meter burst size");
112 case RTE_MTR_TRTCM_RFC4115:
113 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
114 mtr_capa.meter_rate_max)
115 rc = -rte_mtr_error_set(error, EINVAL,
116 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
117 "PIR + EIR exceeds max rate");
119 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
120 rc = -rte_mtr_error_set(error, EINVAL,
121 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
122 "CBS exceeds max meter burst size");
124 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
125 rc = -rte_mtr_error_set(error, EINVAL,
126 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
127 "PBS exceeds max meter burst size");
131 rc = -rte_mtr_error_set(error, EINVAL,
132 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
141 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
142 struct rte_mtr_capabilities *capa,
143 struct rte_mtr_error *error)
148 return -rte_mtr_error_set(error, EINVAL,
149 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
150 "NULL input parameter");
156 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
157 struct rte_mtr_meter_profile *profile,
158 struct rte_mtr_error *error)
160 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
161 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
162 struct cnxk_mtr_profile_node *fmp;
165 /* Check input params. */
166 ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
170 fmp = nix_mtr_profile_find(dev, profile_id);
172 return -rte_mtr_error_set(error, EEXIST,
173 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
174 NULL, "Profile already exist");
177 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
179 return -rte_mtr_error_set(error, ENOMEM,
180 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
181 "Meter profile memory "
184 fmp->id = profile_id;
185 fmp->profile = *profile;
187 TAILQ_INSERT_TAIL(fmps, fmp, next);
193 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
194 struct rte_mtr_error *error)
196 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
197 struct cnxk_mtr_profile_node *fmp;
199 if (profile_id == UINT32_MAX)
200 return -rte_mtr_error_set(error, EINVAL,
201 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
202 NULL, "Meter profile id not valid.");
204 fmp = nix_mtr_profile_find(dev, profile_id);
206 return -rte_mtr_error_set(error, ENOENT,
207 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
209 "Meter profile is invalid.");
212 return -rte_mtr_error_set(error, EBUSY,
213 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
214 NULL, "Meter profile is in use.");
216 TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
222 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
223 struct rte_mtr_meter_policy_params *policy,
224 struct rte_mtr_error *error)
226 static const char *const action_color[] = {"Green", "Yellow", "Red"};
227 bool supported[RTE_COLORS] = {false, false, false};
228 const struct rte_flow_action *action;
235 return 0; /* Nothing to be validated */
237 for (i = 0; i < RTE_COLORS; i++) {
238 if (policy->actions[i]) {
239 for (action = policy->actions[i];
240 action->type != RTE_FLOW_ACTION_TYPE_END;
242 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
245 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
250 "%s action is not valid",
252 return -rte_mtr_error_set(error,
254 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
259 sprintf(message, "%s action is null", action_color[i]);
260 return -rte_mtr_error_set(error, EINVAL,
261 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
269 const struct rte_mtr_ops nix_mtr_ops = {
270 .capabilities_get = cnxk_nix_mtr_capabilities_get,
271 .meter_profile_add = cnxk_nix_mtr_profile_add,
272 .meter_profile_delete = cnxk_nix_mtr_profile_delete,
273 .meter_policy_validate = cnxk_nix_mtr_policy_validate,
277 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
281 *(const void **)ops = &nix_mtr_ops;