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)
53 static struct cnxk_mtr_policy_node *
54 nix_mtr_policy_find(struct cnxk_eth_dev *dev, uint32_t meter_policy_id)
56 struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
57 struct cnxk_mtr_policy_node *fmp;
59 TAILQ_FOREACH(fmp, fmps, next)
60 if (meter_policy_id == fmp->id)
66 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
67 struct rte_mtr_meter_profile *profile,
68 struct rte_mtr_error *error)
75 return -rte_mtr_error_set(error, EINVAL,
76 RTE_MTR_ERROR_TYPE_METER_PROFILE,
77 NULL, "Meter profile is null.");
79 if (profile_id == UINT32_MAX)
80 return -rte_mtr_error_set(error, EINVAL,
81 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
82 NULL, "Meter profile id not valid.");
84 switch (profile->alg) {
85 case RTE_MTR_SRTCM_RFC2697:
86 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
87 rc = -rte_mtr_error_set(error, EINVAL,
88 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
89 "CIR exceeds max meter rate");
91 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
92 rc = -rte_mtr_error_set(error, EINVAL,
93 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
94 "CBS exceeds max meter burst size");
96 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
97 rc = -rte_mtr_error_set(error, EINVAL,
98 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
99 "EBS exceeds max meter burst size");
102 case RTE_MTR_TRTCM_RFC2698:
103 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
104 rc = -rte_mtr_error_set(error, EINVAL,
105 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
106 "CIR exceeds max meter rate");
108 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
109 rc = -rte_mtr_error_set(error, EINVAL,
110 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
111 "PIR exceeds max meter rate");
113 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
114 rc = -rte_mtr_error_set(error, EINVAL,
115 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
116 "CBS exceeds max meter burst size");
118 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
119 rc = -rte_mtr_error_set(error, EINVAL,
120 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
121 "PBS exceeds max meter burst size");
124 case RTE_MTR_TRTCM_RFC4115:
125 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
126 mtr_capa.meter_rate_max)
127 rc = -rte_mtr_error_set(error, EINVAL,
128 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
129 "PIR + EIR exceeds max rate");
131 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
132 rc = -rte_mtr_error_set(error, EINVAL,
133 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
134 "CBS exceeds max meter burst size");
136 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
137 rc = -rte_mtr_error_set(error, EINVAL,
138 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
139 "PBS exceeds max meter burst size");
143 rc = -rte_mtr_error_set(error, EINVAL,
144 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
153 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
154 struct rte_mtr_capabilities *capa,
155 struct rte_mtr_error *error)
160 return -rte_mtr_error_set(error, EINVAL,
161 RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
162 "NULL input parameter");
168 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
169 struct rte_mtr_meter_profile *profile,
170 struct rte_mtr_error *error)
172 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
173 struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
174 struct cnxk_mtr_profile_node *fmp;
177 /* Check input params. */
178 ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
182 fmp = nix_mtr_profile_find(dev, profile_id);
184 return -rte_mtr_error_set(error, EEXIST,
185 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
186 NULL, "Profile already exist");
189 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
191 return -rte_mtr_error_set(error, ENOMEM,
192 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
193 "Meter profile memory "
196 fmp->id = profile_id;
197 fmp->profile = *profile;
199 TAILQ_INSERT_TAIL(fmps, fmp, next);
205 cnxk_nix_mtr_profile_delete(struct rte_eth_dev *eth_dev, uint32_t profile_id,
206 struct rte_mtr_error *error)
208 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
209 struct cnxk_mtr_profile_node *fmp;
211 if (profile_id == UINT32_MAX)
212 return -rte_mtr_error_set(error, EINVAL,
213 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
214 NULL, "Meter profile id not valid.");
216 fmp = nix_mtr_profile_find(dev, profile_id);
218 return -rte_mtr_error_set(error, ENOENT,
219 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
221 "Meter profile is invalid.");
224 return -rte_mtr_error_set(error, EBUSY,
225 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
226 NULL, "Meter profile is in use.");
228 TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
234 cnxk_nix_mtr_policy_validate(struct rte_eth_dev *dev,
235 struct rte_mtr_meter_policy_params *policy,
236 struct rte_mtr_error *error)
238 static const char *const action_color[] = {"Green", "Yellow", "Red"};
239 bool supported[RTE_COLORS] = {false, false, false};
240 const struct rte_flow_action *action;
247 return 0; /* Nothing to be validated */
249 for (i = 0; i < RTE_COLORS; i++) {
250 if (policy->actions[i]) {
251 for (action = policy->actions[i];
252 action->type != RTE_FLOW_ACTION_TYPE_END;
254 if (action->type == RTE_FLOW_ACTION_TYPE_METER)
257 if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
262 "%s action is not valid",
264 return -rte_mtr_error_set(error,
266 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
271 sprintf(message, "%s action is null", action_color[i]);
272 return -rte_mtr_error_set(error, EINVAL,
273 RTE_MTR_ERROR_TYPE_METER_POLICY, NULL,
282 cnxk_fill_policy_actions(struct cnxk_mtr_policy_node *fmp,
283 struct rte_mtr_meter_policy_params *policy)
286 const struct rte_flow_action_meter *mtr;
287 const struct rte_flow_action *action;
290 for (i = 0; i < RTE_COLORS; i++) {
291 if (policy->actions[i]) {
292 for (action = policy->actions[i];
293 action->type != RTE_FLOW_ACTION_TYPE_END;
296 RTE_FLOW_ACTION_TYPE_METER) {
297 fmp->actions[i].action_fate =
300 rte_flow_action_meter *)
302 fmp->actions[i].mtr_id = mtr->mtr_id;
305 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
306 fmp->actions[i].action_fate =
315 cnxk_nix_mtr_policy_add(struct rte_eth_dev *eth_dev, uint32_t policy_id,
316 struct rte_mtr_meter_policy_params *policy,
317 struct rte_mtr_error *error)
319 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
320 struct cnxk_mtr_policy *fmps = &dev->mtr_policy;
321 struct cnxk_mtr_policy_node *fmp;
324 fmp = nix_mtr_policy_find(dev, policy_id);
326 return -rte_mtr_error_set(error, EEXIST,
327 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
328 NULL, "Policy already exist");
331 fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
333 return -rte_mtr_error_set(error, ENOMEM,
334 RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
335 "Memory allocation failure");
337 rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
343 cnxk_fill_policy_actions(fmp, policy);
344 TAILQ_INSERT_TAIL(fmps, fmp, next);
352 const struct rte_mtr_ops nix_mtr_ops = {
353 .capabilities_get = cnxk_nix_mtr_capabilities_get,
354 .meter_profile_add = cnxk_nix_mtr_profile_add,
355 .meter_profile_delete = cnxk_nix_mtr_profile_delete,
356 .meter_policy_validate = cnxk_nix_mtr_policy_validate,
357 .meter_policy_add = cnxk_nix_mtr_policy_add,
361 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
365 *(const void **)ops = &nix_mtr_ops;