Branch data Line data Source code
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 *
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 [ # # # # : 0 : TAILQ_FOREACH(fm, fms, next)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
64 [ # # # # : 0 : if (meter_id == fm->id)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
65 : : return fm;
66 : : return NULL;
67 : : }
68 : :
69 : : static struct cnxk_mtr_profile_node *
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 [ # # # # : 0 : TAILQ_FOREACH(fmp, fmps, next)
# # # # ]
76 [ # # # # : 0 : if (profile_id == fmp->id)
# # # # ]
77 : : return fmp;
78 : :
79 : : return NULL;
80 : : }
81 : :
82 : : static struct cnxk_mtr_policy_node *
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 [ # # # # : 0 : TAILQ_FOREACH(fmp, fmps, next)
# # # # #
# ]
89 [ # # # # : 0 : if (meter_policy_id == fmp->id)
# # # # #
# ]
90 : : return fmp;
91 : : return NULL;
92 : : }
93 : :
94 : : static int
95 : 0 : 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 [ # # ]: 0 : if (profile == NULL)
104 : 0 : return -rte_mtr_error_set(error, EINVAL,
105 : : RTE_MTR_ERROR_TYPE_METER_PROFILE,
106 : : NULL, "Meter profile is null.");
107 : :
108 [ # # ]: 0 : if (profile_id == UINT32_MAX)
109 : 0 : return -rte_mtr_error_set(error, EINVAL,
110 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
111 : : NULL, "Meter profile id not valid.");
112 : :
113 [ # # # # ]: 0 : switch (profile->alg) {
114 : 0 : case RTE_MTR_SRTCM_RFC2697:
115 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : 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 : 0 : case RTE_MTR_TRTCM_RFC2698:
132 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : 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 : 0 : case RTE_MTR_TRTCM_RFC4115:
154 : 0 : if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
155 [ # # ]: 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : 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 : 0 : break;
176 : : }
177 : :
178 : : return rc;
179 : : }
180 : :
181 : : static int
182 [ # # ]: 0 : 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 : 0 : uint16_t count[ROC_NIX_BPF_LEVEL_MAX] = {0};
190 : 0 : struct roc_nix *nix = ð_dev->nix;
191 : : uint32_t time_unit;
192 : : int rc, i;
193 : :
194 : : RTE_SET_USED(dev);
195 : :
196 [ # # ]: 0 : if (!capa)
197 : 0 : return -rte_mtr_error_set(error, EINVAL,
198 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
199 : : "NULL input parameter");
200 : :
201 : 0 : rc = roc_nix_bpf_count_get(nix, lvl_mask, count);
202 [ # # ]: 0 : if (rc)
203 : : return rc;
204 : :
205 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++)
206 : 0 : mtr_capa.n_max += count[i];
207 : :
208 : 0 : mtr_capa.meter_srtcm_rfc2697_n_max = mtr_capa.n_max;
209 : 0 : mtr_capa.meter_trtcm_rfc2698_n_max = mtr_capa.n_max;
210 : 0 : mtr_capa.meter_trtcm_rfc4115_n_max = mtr_capa.n_max;
211 : 0 : mtr_capa.meter_policy_n_max = mtr_capa.n_max;
212 : :
213 : 0 : rc = roc_nix_bpf_timeunit_get(nix, &time_unit);
214 [ # # ]: 0 : if (rc)
215 : : return rc;
216 : :
217 : 0 : mtr_capa.meter_rate_max =
218 : 0 : NIX_BPF_RATE(time_unit, NIX_BPF_MAX_RATE_EXPONENT,
219 : 0 : NIX_BPF_MAX_RATE_MANTISSA, 0) /
220 : : 8;
221 : :
222 : 0 : *capa = mtr_capa;
223 : 0 : return 0;
224 : : }
225 : :
226 : : static int
227 : 0 : 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 : 0 : ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
238 [ # # ]: 0 : if (ret)
239 : : return ret;
240 : :
241 : : fmp = nix_mtr_profile_find(dev, profile_id);
242 [ # # ]: 0 : if (fmp) {
243 : 0 : return -rte_mtr_error_set(error, EEXIST,
244 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
245 : : NULL, "Profile already exist");
246 : : }
247 : :
248 : 0 : fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
249 [ # # ]: 0 : if (fmp == NULL)
250 : 0 : return -rte_mtr_error_set(error, ENOMEM,
251 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
252 : : "Meter profile memory "
253 : : "alloc failed.");
254 : :
255 : 0 : fmp->id = profile_id;
256 : 0 : fmp->profile = *profile;
257 : :
258 : 0 : TAILQ_INSERT_TAIL(fmps, fmp, next);
259 : :
260 : 0 : return 0;
261 : : }
262 : :
263 : : static int
264 [ # # ]: 0 : 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 [ # # ]: 0 : if (profile_id == UINT32_MAX)
271 : 0 : 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 [ # # ]: 0 : if (fmp == NULL)
277 : 0 : 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 [ # # ]: 0 : if (fmp->ref_cnt)
283 : 0 : return -rte_mtr_error_set(error, EBUSY,
284 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
285 : : NULL, "Meter profile is in use.");
286 : :
287 [ # # ]: 0 : TAILQ_REMOVE(&dev->mtr_profiles, fmp, next);
288 : 0 : plt_free(fmp);
289 : 0 : return 0;
290 : : }
291 : :
292 : : static int
293 : : update_mtr_err(uint32_t act_color, struct rte_mtr_error *error, bool action)
294 : : {
295 : : const char *str = NULL;
296 [ # # # # : 0 : switch (act_color) {
# # ]
297 : : case RTE_COLOR_GREEN:
298 : : if (action) {
299 : : str = "Green action is not valid";
300 : 0 : goto notsup;
301 : : } else {
302 : : str = "Green action is null";
303 : 0 : goto notvalid;
304 : : }
305 : : break;
306 : : case RTE_COLOR_YELLOW:
307 : : if (action) {
308 : : str = "Yellow action is not valid";
309 : 0 : goto notsup;
310 : : } else {
311 : : str = "Yellow action is null";
312 : 0 : goto notvalid;
313 : : }
314 : : break;
315 : : case RTE_COLOR_RED:
316 : : if (action) {
317 : : str = "Red action is not valid";
318 : 0 : goto notsup;
319 : : } else {
320 : : str = "Red action is null";
321 : 0 : goto notvalid;
322 : : }
323 : : break;
324 : : }
325 [ # # ]: 0 : notsup:
326 : : return -rte_mtr_error_set(error, ENOTSUP,
327 : : RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
328 [ # # ]: 0 : notvalid:
329 : : return -rte_mtr_error_set(error, EINVAL,
330 : : RTE_MTR_ERROR_TYPE_METER_POLICY, NULL, str);
331 : : }
332 : :
333 : : static int
334 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (!policy)
345 : : return 0; /* Nothing to be validated */
346 : :
347 [ # # ]: 0 : for (i = 0; i < RTE_COLORS; i++) {
348 [ # # ]: 0 : if (policy->actions[i]) {
349 : : for (action = policy->actions[i];
350 [ # # ]: 0 : action->type != RTE_FLOW_ACTION_TYPE_END;
351 : 0 : action++) {
352 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_METER)
353 : 0 : supported[i] = true;
354 : :
355 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_DROP)
356 : 0 : supported[i] = true;
357 : :
358 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
359 : 0 : supported[i] = true;
360 : :
361 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_SKIP_CMAN)
362 : 0 : supported[i] = true;
363 : :
364 [ # # ]: 0 : if (!supported[i])
365 : 0 : return update_mtr_err(i, error, true);
366 : : }
367 : : } else {
368 : 0 : return update_mtr_err(i, error, false);
369 : : }
370 : : }
371 : :
372 : : return 0;
373 : : }
374 : :
375 : : static void
376 : 0 : 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 [ # # ]: 0 : for (i = 0; i < RTE_COLORS; i++) {
385 [ # # ]: 0 : if (policy->actions[i]) {
386 : : for (action = policy->actions[i];
387 [ # # ]: 0 : action->type != RTE_FLOW_ACTION_TYPE_END;
388 : 0 : action++) {
389 [ # # ]: 0 : if (action->type ==
390 : : RTE_FLOW_ACTION_TYPE_METER) {
391 : 0 : fmp->actions[i].action_fate =
392 : : action->type;
393 : 0 : mtr = (const struct
394 : : rte_flow_action_meter *)
395 : : action->conf;
396 : 0 : fmp->actions[i].mtr_id = mtr->mtr_id;
397 : : }
398 : :
399 [ # # ]: 0 : if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
400 : 0 : fmp->actions[i].action_fate =
401 : : action->type;
402 : : }
403 : :
404 [ # # ]: 0 : if (action->type ==
405 : : RTE_FLOW_ACTION_TYPE_SKIP_CMAN)
406 : 0 : fmp->actions[i].skip_red = true;
407 : : }
408 : : }
409 : : }
410 : 0 : }
411 : :
412 : : static int
413 : 0 : 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 [ # # ]: 0 : if (fmp) {
424 : 0 : return -rte_mtr_error_set(error, EEXIST,
425 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
426 : : NULL, "Policy already exist");
427 : : }
428 : :
429 : 0 : fmp = plt_zmalloc(sizeof(struct cnxk_mtr_policy_node), ROC_ALIGN);
430 [ # # ]: 0 : if (fmp == NULL) {
431 : 0 : return -rte_mtr_error_set(error, ENOMEM,
432 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
433 : : "Memory allocation failure");
434 : : } else {
435 : 0 : rc = cnxk_nix_mtr_policy_validate(eth_dev, policy, error);
436 [ # # ]: 0 : if (rc)
437 : 0 : goto exit;
438 : : }
439 : :
440 : 0 : fmp->id = policy_id;
441 : 0 : cnxk_fill_policy_actions(fmp, policy);
442 : 0 : TAILQ_INSERT_TAIL(fmps, fmp, next);
443 : 0 : return 0;
444 : :
445 : : exit:
446 : 0 : plt_free(fmp);
447 : 0 : return rc;
448 : : }
449 : :
450 : : static int
451 : 0 : 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 [ # # ]: 0 : if (fmp == NULL) {
459 : 0 : return -rte_mtr_error_set(error, ENOENT,
460 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
461 : : NULL, "No policy found");
462 : : }
463 : :
464 [ # # ]: 0 : if (fmp->ref_cnt)
465 : 0 : return -rte_mtr_error_set(error, EBUSY,
466 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
467 : : NULL, "Meter policy is in use.");
468 : :
469 [ # # ]: 0 : TAILQ_REMOVE(&dev->mtr_policy, fmp, next);
470 : 0 : plt_free(fmp);
471 : :
472 : 0 : return 0;
473 : : }
474 : :
475 : : static int
476 [ # # ]: 0 : 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 [ # # ]: 0 : if (params == NULL)
491 : 0 : return -rte_mtr_error_set(error, ENOENT,
492 : : RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
493 : : "Meter params are invalid.");
494 : :
495 : 0 : profile = nix_mtr_profile_find(dev, params->meter_profile_id);
496 [ # # ]: 0 : if (profile == NULL)
497 : 0 : return -rte_mtr_error_set(error, ENOENT,
498 : : RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
499 [ # # ]: 0 : ¶ms->meter_profile_id,
500 : : "Meter profile is invalid.");
501 : :
502 : 0 : policy = nix_mtr_policy_find(dev, params->meter_policy_id);
503 [ # # ]: 0 : if (policy == NULL)
504 : 0 : return -rte_mtr_error_set(error, ENOENT,
505 : : RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
506 [ # # ]: 0 : ¶ms->meter_policy_id,
507 : : "Meter policy is invalid.");
508 : :
509 : : mtr = nix_mtr_find(dev, mtr_id);
510 [ # # ]: 0 : if (mtr) {
511 : 0 : return -rte_mtr_error_set(error, EEXIST,
512 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
513 : : "Meter already exist");
514 : : }
515 : :
516 : 0 : mtr = plt_zmalloc(sizeof(struct cnxk_meter_node), ROC_ALIGN);
517 [ # # ]: 0 : if (mtr == NULL) {
518 : 0 : return -rte_mtr_error_set(error, ENOMEM,
519 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
520 : : "Meter memory alloc failed.");
521 : : }
522 : :
523 : 0 : mtr->id = mtr_id;
524 : 0 : mtr->profile = profile;
525 : 0 : mtr->policy = policy;
526 : 0 : mtr->params = *params;
527 : 0 : mtr->bpf_id = ROC_NIX_BPF_ID_INVALID;
528 : 0 : mtr->prev_cnt = 0;
529 [ # # ]: 0 : for (i = 0; i < MAX_PRV_MTR_NODES; i++)
530 : 0 : mtr->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
531 : :
532 : 0 : mtr->next_id = ROC_NIX_BPF_ID_INVALID;
533 : 0 : mtr->is_next = false;
534 : 0 : mtr->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
535 : :
536 : : /* populate dscp table for input coloring */
537 [ # # ]: 0 : if (params->dscp_table) {
538 : 0 : table = (enum rte_color *)plt_zmalloc(sizeof(enum rte_color) *
539 : : ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP, ROC_ALIGN);
540 [ # # ]: 0 : if (table == NULL) {
541 : 0 : plt_free(mtr);
542 : 0 : return -rte_mtr_error_set(error, ENOMEM,
543 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
544 : : NULL, "Memory alloc failed.");
545 : : }
546 : :
547 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
548 : 0 : table[i] = params->dscp_table[i];
549 : :
550 : 0 : mtr->params.dscp_table = table;
551 : : }
552 : :
553 : :
554 : : /* populate vlan table for input coloring */
555 [ # # ]: 0 : if (params->vlan_table) {
556 : 0 : table = (enum rte_color *)plt_zmalloc(sizeof(enum rte_color) *
557 : : ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN, ROC_ALIGN);
558 [ # # ]: 0 : if (table == NULL) {
559 : 0 : plt_free(mtr->params.dscp_table);
560 : 0 : plt_free(mtr);
561 : 0 : return -rte_mtr_error_set(error, ENOMEM,
562 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED,
563 : : NULL, "Memory alloc failed.");
564 : : }
565 : :
566 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
567 : 0 : table[i] = params->vlan_table[i];
568 : :
569 : 0 : mtr->params.vlan_table = table;
570 : : }
571 : :
572 : 0 : profile->ref_cnt++;
573 : 0 : policy->ref_cnt++;
574 : 0 : TAILQ_INSERT_TAIL(fm, mtr, next);
575 : 0 : return 0;
576 : : }
577 : :
578 : : static int
579 : 0 : 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 : 0 : struct roc_nix_bpf_objs profs = {0};
584 : : struct cnxk_mtr *fm = &dev->mtr;
585 : 0 : 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 : 0 : mtr = nix_mtr_find(dev, mtr_id);
592 [ # # ]: 0 : if (mtr == NULL) {
593 : 0 : return -rte_mtr_error_set(error, ENOENT,
594 : : RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
595 : : "Meter id is invalid.");
596 : : }
597 : :
598 [ # # ]: 0 : if (mtr->ref_cnt) {
599 : 0 : return -rte_mtr_error_set(error, EADDRINUSE,
600 : : RTE_MTR_ERROR_TYPE_MTR_ID, &mtr_id,
601 : : "Meter id in use.");
602 : : }
603 : :
604 [ # # # # ]: 0 : switch (lvl_map[mtr->level]) {
605 : 0 : case ROC_NIX_BPF_LEVEL_F_LEAF:
606 [ # # ]: 0 : if (mtr->is_next) {
607 : 0 : rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
608 : 0 : mtr->bpf_id,
609 : : ROC_NIX_BPF_ID_INVALID);
610 : : }
611 : : break;
612 : : case ROC_NIX_BPF_LEVEL_F_MID:
613 [ # # ]: 0 : while ((mtr->prev_cnt) + 1) {
614 : : mid_mtr =
615 : 0 : nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
616 [ # # ]: 0 : if (mid_mtr == NULL) {
617 : 0 : return -rte_mtr_error_set(error, ENOENT,
618 [ # # ]: 0 : RTE_MTR_ERROR_TYPE_MTR_ID, &mtr->prev_id[mtr->prev_cnt],
619 : : "Mid meter id is invalid.");
620 : : }
621 : 0 : rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_LEAF,
622 : 0 : mid_mtr->bpf_id,
623 : : ROC_NIX_BPF_ID_INVALID);
624 : 0 : mtr->prev_cnt--;
625 : : }
626 [ # # ]: 0 : if (mtr->is_next) {
627 : 0 : rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
628 : 0 : mtr->bpf_id,
629 : : ROC_NIX_BPF_ID_INVALID);
630 : : }
631 : : break;
632 : : case ROC_NIX_BPF_LEVEL_F_TOP:
633 [ # # ]: 0 : while (mtr->prev_cnt) {
634 : : top_mtr =
635 : 0 : nix_mtr_find(dev, mtr->prev_id[mtr->prev_cnt]);
636 [ # # ]: 0 : if (top_mtr == NULL) {
637 : 0 : return -rte_mtr_error_set(error, ENOENT,
638 [ # # ]: 0 : RTE_MTR_ERROR_TYPE_MTR_ID, &mtr->prev_id[mtr->prev_cnt],
639 : : "Top meter id is invalid.");
640 : : }
641 : 0 : rc = roc_nix_bpf_connect(nix, ROC_NIX_BPF_LEVEL_F_MID,
642 : 0 : top_mtr->bpf_id,
643 : : ROC_NIX_BPF_ID_INVALID);
644 : 0 : mtr->prev_cnt--;
645 : : }
646 : : break;
647 : : default:
648 : 0 : return -rte_mtr_error_set(error, EINVAL,
649 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
650 : : "Invalid meter level");
651 : : }
652 : :
653 [ # # ]: 0 : if (rc)
654 : 0 : goto exit;
655 : :
656 : 0 : profs.level = mtr->level;
657 : 0 : profs.count = 1;
658 : 0 : profs.ids[0] = mtr->bpf_id;
659 : 0 : rc = roc_nix_bpf_free(nix, &profs, 1);
660 [ # # ]: 0 : if (rc)
661 : 0 : goto exit;
662 : :
663 : 0 : mtr->policy->ref_cnt--;
664 : 0 : mtr->profile->ref_cnt--;
665 [ # # ]: 0 : TAILQ_REMOVE(fm, mtr, next);
666 : :
667 [ # # ]: 0 : if (mtr->params.dscp_table)
668 : 0 : plt_free(mtr->params.dscp_table);
669 : :
670 [ # # ]: 0 : if (mtr->params.vlan_table)
671 : 0 : plt_free(mtr->params.vlan_table);
672 : :
673 : 0 : plt_free(mtr);
674 : :
675 : : exit:
676 : : return rc;
677 : : }
678 : :
679 : : static int
680 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
692 : 0 : return -rte_mtr_error_set(error, ENOENT,
693 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
694 : : "Meter id is invalid.");
695 : : }
696 : :
697 [ # # ]: 0 : if (mtr->level != 0)
698 : : return 0;
699 : :
700 [ # # ]: 0 : for (i = 0; i < mtr->rq_num; i++) {
701 : 0 : rq = &dev->rqs[mtr->rq_id[i]];
702 : 0 : rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, true);
703 : : }
704 : :
705 : : return rc;
706 : : }
707 : :
708 : : static int
709 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
721 : 0 : return -rte_mtr_error_set(error, ENOENT,
722 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
723 : : "Meter id is invalid.");
724 : : }
725 : :
726 [ # # ]: 0 : if (mtr->level != 0)
727 : : return 0;
728 : :
729 [ # # ]: 0 : for (i = 0; i < mtr->rq_num; i++) {
730 : 0 : rq = &dev->rqs[mtr->rq_id[i]];
731 : 0 : rc |= roc_nix_bpf_ena_dis(nix, mtr->bpf_id, rq, false);
732 : : }
733 : :
734 : : return rc;
735 : : }
736 : :
737 : : static int
738 : 0 : 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 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
755 : 0 : return -rte_mtr_error_set(error, ENOENT,
756 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
757 : : "Meter object not found");
758 : : }
759 : :
760 [ # # ]: 0 : if (!dscp_table) {
761 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
762 : 0 : nix_dscp_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
763 : : } else {
764 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
765 : 0 : nix_dscp_tbl[i] = color_map[dscp_table[i]];
766 : : }
767 : :
768 : 0 : table.count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP;
769 : :
770 [ # # # ]: 0 : switch (proto) {
771 : 0 : case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
772 : 0 : table.mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
773 : 0 : break;
774 : 0 : case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
775 : 0 : table.mode = ROC_NIX_BPF_PC_MODE_DSCP_INNER;
776 : 0 : break;
777 : : default:
778 : : rc = -rte_mtr_error_set(error, EINVAL,
779 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
780 : : "Invalid input color protocol");
781 : 0 : goto exit;
782 : : }
783 : :
784 [ # # ]: 0 : 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 : 0 : goto exit;
789 : : }
790 : :
791 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
792 : 0 : table.color[i] = nix_dscp_tbl[i];
793 : :
794 : 0 : rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
795 : 0 : lvl_map[mtr->level], &table);
796 [ # # ]: 0 : if (rc) {
797 : : rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
798 : : NULL, NULL);
799 : 0 : goto exit;
800 : : }
801 : :
802 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP; i++)
803 : 0 : dev->precolor_tbl[i] = nix_dscp_tbl[i];
804 : :
805 : 0 : exit:
806 : : return rc;
807 : : }
808 : :
809 : : static int
810 : 0 : 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 : 0 : 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 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
827 : 0 : return -rte_mtr_error_set(error, ENOENT,
828 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
829 : : "Meter object not found");
830 : : }
831 : :
832 [ # # ]: 0 : if (!vlan_table) {
833 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
834 : 0 : nix_vlan_tbl[i] = ROC_NIX_BPF_COLOR_GREEN;
835 : : } else {
836 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
837 : 0 : nix_vlan_tbl[i] = color_map[vlan_table[i]];
838 : : }
839 : :
840 : 0 : table.count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN;
841 : :
842 [ # # # ]: 0 : switch (proto) {
843 : 0 : case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
844 : 0 : table.mode = ROC_NIX_BPF_PC_MODE_VLAN_OUTER;
845 : 0 : break;
846 : 0 : case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
847 : 0 : table.mode = ROC_NIX_BPF_PC_MODE_VLAN_INNER;
848 : 0 : break;
849 : : default:
850 : : rc = -rte_mtr_error_set(error, EINVAL,
851 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
852 : : "Invalid input color protocol");
853 : 0 : goto exit;
854 : : }
855 : :
856 [ # # ]: 0 : 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 : 0 : goto exit;
861 : : }
862 : :
863 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
864 : 0 : table.color[i] = nix_vlan_tbl[i];
865 : :
866 : 0 : rc = roc_nix_bpf_pre_color_tbl_setup(nix, mtr->bpf_id,
867 : 0 : lvl_map[mtr->level], &table);
868 [ # # ]: 0 : if (rc) {
869 : : rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
870 : : NULL, NULL);
871 : 0 : goto exit;
872 : : }
873 : :
874 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN; i++)
875 : 0 : dev->precolor_tbl[i] = nix_vlan_tbl[i];
876 : :
877 : 0 : exit:
878 : : return rc;
879 : : }
880 : :
881 : : static int
882 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
893 : 0 : return -rte_mtr_error_set(error, ENOENT,
894 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
895 : : "Meter object not found");
896 : : }
897 : :
898 : 0 : dev->proto = proto;
899 : 0 : return 0;
900 : : }
901 : :
902 : : static int
903 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
911 : 0 : return -rte_mtr_error_set(error, ENOENT,
912 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
913 : : "Meter object not found");
914 : : }
915 : :
916 : 0 : *proto_mask = dev->proto;
917 : 0 : return 0;
918 : : }
919 : :
920 : : static int
921 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
932 : 0 : return -rte_mtr_error_set(error, ENOENT,
933 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
934 : : "Meter object not found");
935 : : }
936 : :
937 : 0 : plt_info("Only single priority supported i.e. 0");
938 : 0 : *priority = 0;
939 : 0 : return 0;
940 : : }
941 : :
942 : : static int
943 [ # # ]: 0 : 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 [ # # ]: 0 : if (!stats_mask)
950 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
956 : 0 : return -rte_mtr_error_set(error, ENOENT,
957 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
958 : : "Meter object not found");
959 : : }
960 : :
961 : 0 : mtr->params.stats_mask = stats_mask;
962 : 0 : return 0;
963 : : }
964 : :
965 : : static int
966 [ # # ]: 0 : 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 : 0 : uint64_t bpf_stats[ROC_NIX_BPF_STATS_MAX] = {0};
976 : : uint64_t mask = NIX_BPF_STATS_MASK_ALL;
977 : 0 : struct roc_nix *nix = &dev->nix;
978 : : struct cnxk_meter_node *mtr;
979 : : int rc;
980 : :
981 [ # # ]: 0 : if (!stats)
982 : 0 : 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 [ # # ]: 0 : if (mtr == NULL) {
988 : 0 : return -rte_mtr_error_set(error, ENOENT,
989 : : RTE_MTR_ERROR_TYPE_MTR_ID, NULL,
990 : : "Meter object not found");
991 : : }
992 : :
993 : 0 : rc = roc_nix_bpf_stats_read(nix, mtr->bpf_id, mask, lvl_map[mtr->level],
994 : : bpf_stats);
995 [ # # ]: 0 : if (rc) {
996 : : rte_mtr_error_set(error, rc, RTE_MTR_ERROR_TYPE_UNSPECIFIED,
997 : : NULL, NULL);
998 : 0 : goto exit;
999 : : }
1000 : :
1001 : 0 : green_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_PASS);
1002 : : green_octs_pass =
1003 : 0 : roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_PASS);
1004 : 0 : green_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_PKT_F_DROP);
1005 : : green_octs_drop =
1006 : 0 : roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_GREEN_OCTS_F_DROP);
1007 : : yellow_pkt_pass =
1008 : 0 : roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_PASS);
1009 : : yellow_octs_pass =
1010 : 0 : roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_PASS);
1011 : : yellow_pkt_drop =
1012 : 0 : roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_PKT_F_DROP);
1013 : : yellow_octs_drop =
1014 : 0 : roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_YELLOW_OCTS_F_DROP);
1015 : 0 : red_pkt_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_PASS);
1016 : 0 : red_octs_pass = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_PASS);
1017 : 0 : red_pkt_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_PKT_F_DROP);
1018 : 0 : red_octs_drop = roc_nix_bpf_stats_to_idx(ROC_NIX_BPF_RED_OCTS_F_DROP);
1019 : :
1020 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_GREEN)
1021 : 0 : stats->n_pkts[RTE_COLOR_GREEN] = bpf_stats[green_pkt_pass];
1022 : :
1023 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_YELLOW)
1024 : 0 : stats->n_pkts[RTE_COLOR_YELLOW] = bpf_stats[yellow_pkt_pass];
1025 : :
1026 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_RED)
1027 : 0 : stats->n_pkts[RTE_COLOR_RED] = bpf_stats[red_pkt_pass];
1028 : :
1029 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_GREEN)
1030 : 0 : stats->n_bytes[RTE_COLOR_GREEN] = bpf_stats[green_octs_pass];
1031 : :
1032 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_YELLOW)
1033 : 0 : stats->n_bytes[RTE_COLOR_YELLOW] = bpf_stats[yellow_octs_pass];
1034 : :
1035 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_RED)
1036 : 0 : stats->n_bytes[RTE_COLOR_RED] = bpf_stats[red_octs_pass];
1037 : :
1038 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_PKTS_DROPPED)
1039 : 0 : stats->n_pkts_dropped = bpf_stats[green_pkt_drop] +
1040 : 0 : bpf_stats[yellow_pkt_drop] +
1041 : 0 : bpf_stats[red_pkt_drop];
1042 : :
1043 [ # # ]: 0 : if (mtr->params.stats_mask & RTE_MTR_STATS_N_BYTES_DROPPED)
1044 : 0 : stats->n_bytes_dropped = bpf_stats[green_octs_drop] +
1045 : 0 : bpf_stats[yellow_octs_drop] +
1046 : 0 : bpf_stats[red_octs_drop];
1047 : :
1048 [ # # ]: 0 : if (stats_mask)
1049 : 0 : *stats_mask = mtr->params.stats_mask;
1050 : :
1051 [ # # ]: 0 : if (clear) {
1052 : 0 : rc = roc_nix_bpf_stats_reset(nix, mtr->bpf_id, mask,
1053 : 0 : lvl_map[mtr->level]);
1054 [ # # ]: 0 : if (rc) {
1055 : : rte_mtr_error_set(error, rc,
1056 : : RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
1057 : : NULL);
1058 : 0 : goto exit;
1059 : : }
1060 : : }
1061 : :
1062 : 0 : 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
1087 : 0 : cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
1088 : : {
1089 : : RTE_SET_USED(dev);
1090 : :
1091 : 0 : *(const void **)ops = &nix_mtr_ops;
1092 : 0 : return 0;
1093 : : }
1094 : :
1095 : : int
1096 : 0 : 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 [ # # ]: 0 : if (mtr == NULL)
1105 : : return -EINVAL;
1106 : :
1107 : 0 : profile = nix_mtr_profile_find(dev, mtr->params.meter_profile_id);
1108 [ # # ]: 0 : if (profile == NULL)
1109 : : return -EINVAL;
1110 : :
1111 : 0 : policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
1112 [ # # ]: 0 : if (policy == NULL)
1113 : 0 : return -EINVAL;
1114 : :
1115 : : return 0;
1116 : : }
1117 : :
1118 : : int
1119 : 0 : 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 [ # # ]: 0 : if (mtr == NULL)
1128 : : return -EINVAL;
1129 : :
1130 : 0 : policy = nix_mtr_policy_find(dev, mtr->params.meter_policy_id);
1131 [ # # ]: 0 : if (policy == NULL)
1132 : : return -EINVAL;
1133 : :
1134 : 0 : *policy_act = policy;
1135 : :
1136 : 0 : return 0;
1137 : : }
1138 : :
1139 : : int
1140 : 0 : 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 [ # # ]: 0 : if (mtr == NULL)
1149 : : return -EINVAL;
1150 : :
1151 : 0 : mtr->rq_id = plt_zmalloc(queue_num * sizeof(uint32_t), ROC_ALIGN);
1152 [ # # ]: 0 : if (mtr->rq_id == NULL)
1153 : : return -ENOMEM;
1154 : :
1155 : 0 : mtr->rq_num = queue_num;
1156 [ # # ]: 0 : for (i = 0; i < queue_num; i++)
1157 : 0 : mtr->rq_id[i] = queue[i];
1158 : :
1159 : : return 0;
1160 : : }
1161 : :
1162 : : int
1163 : 0 : nix_mtr_chain_reset(struct rte_eth_dev *eth_dev, uint32_t cur_id)
1164 : : {
1165 : 0 : 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 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1171 : 0 : mtr[i] = nix_mtr_find(dev, mtr_id);
1172 [ # # ]: 0 : if (mtr[i])
1173 : 0 : mtr_id = mtr[i]->next_id;
1174 : : }
1175 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1176 [ # # ]: 0 : if (mtr[i]) {
1177 [ # # ]: 0 : for (j = 0; j < MAX_PRV_MTR_NODES; j++)
1178 : 0 : mtr[i]->prev_id[i] = ROC_NIX_BPF_ID_INVALID;
1179 : 0 : mtr[i]->level = ROC_NIX_BPF_LEVEL_IDX_INVALID;
1180 : 0 : mtr[i]->next_id = ROC_NIX_BPF_ID_INVALID;
1181 : 0 : mtr[i]->is_next = false;
1182 : 0 : mtr[i]->prev_cnt = 0;
1183 : : }
1184 : : }
1185 : 0 : return 0;
1186 : : }
1187 : :
1188 : : int
1189 : 0 : 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 [ # # ]: 0 : if (mtr == NULL)
1197 : : return -EINVAL;
1198 : :
1199 [ # # # # ]: 0 : switch (lvl_map[mtr->level]) {
1200 : 0 : case ROC_NIX_BPF_LEVEL_F_LEAF:
1201 : 0 : mtr->prev_id[mtr->prev_cnt] = ROC_NIX_BPF_ID_INVALID;
1202 : 0 : mtr->next_id = next_id;
1203 : 0 : mtr->is_next = true;
1204 : 0 : break;
1205 : 0 : case ROC_NIX_BPF_LEVEL_F_MID:
1206 : 0 : mtr->prev_id[mtr->prev_cnt] = prev_id;
1207 : 0 : mtr->next_id = next_id;
1208 : 0 : mtr->is_next = true;
1209 : 0 : break;
1210 : 0 : case ROC_NIX_BPF_LEVEL_F_TOP:
1211 : 0 : mtr->prev_id[mtr->prev_cnt] = prev_id;
1212 : 0 : mtr->next_id = ROC_NIX_BPF_ID_INVALID;
1213 : 0 : mtr->is_next = false;
1214 : 0 : break;
1215 : 0 : default:
1216 : 0 : plt_err("Invalid meter level");
1217 : 0 : return -EINVAL;
1218 : : }
1219 : :
1220 : : return 0;
1221 : : }
1222 : :
1223 : : struct cnxk_meter_node *
1224 : 0 : 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 [ # # ]: 0 : if (mtr == NULL)
1231 : 0 : return NULL;
1232 : :
1233 : : return mtr;
1234 : : }
1235 : :
1236 : : int
1237 : 0 : 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 [ # # ]: 0 : if (mtr == NULL)
1244 : : return -EINVAL;
1245 : :
1246 : 0 : mtr->level = level;
1247 : 0 : return 0;
1248 : : }
1249 : :
1250 : : static void
1251 : 0 : nix_mtr_config_map(struct cnxk_meter_node *mtr, struct roc_nix_bpf_cfg *cfg)
1252 : : {
1253 : 0 : 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 : 0 : 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 : 0 : struct cnxk_mtr_profile_node *profile = mtr->profile;
1260 : 0 : struct cnxk_mtr_policy_node *policy = mtr->policy;
1261 : :
1262 : 0 : cfg->alg = alg_map[profile->profile.alg];
1263 : 0 : cfg->lmode = profile->profile.packet_mode;
1264 : 0 : 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 : 0 : cfg->pc_mode = ROC_NIX_BPF_PC_MODE_DSCP_OUTER;
1269 : 0 : 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 [ # # # # ]: 0 : switch (cfg->alg) {
1288 : 0 : case ROC_NIX_BPF_ALGO_2697:
1289 : 0 : cfg->algo2697.cir = profile->profile.srtcm_rfc2697.cir * 8;
1290 : 0 : cfg->algo2697.cbs = profile->profile.srtcm_rfc2697.cbs;
1291 : 0 : cfg->algo2697.ebs = profile->profile.srtcm_rfc2697.ebs;
1292 : 0 : break;
1293 : 0 : case ROC_NIX_BPF_ALGO_2698:
1294 : 0 : cfg->algo2698.cir = profile->profile.trtcm_rfc2698.cir * 8;
1295 : 0 : cfg->algo2698.pir = profile->profile.trtcm_rfc2698.pir * 8;
1296 : 0 : cfg->algo2698.cbs = profile->profile.trtcm_rfc2698.cbs;
1297 : 0 : cfg->algo2698.pbs = profile->profile.trtcm_rfc2698.pbs;
1298 : 0 : break;
1299 : 0 : case ROC_NIX_BPF_ALGO_4115:
1300 : 0 : cfg->algo4115.cir = profile->profile.trtcm_rfc4115.cir * 8;
1301 : 0 : cfg->algo4115.eir = profile->profile.trtcm_rfc4115.eir * 8;
1302 : 0 : cfg->algo4115.cbs = profile->profile.trtcm_rfc4115.cbs;
1303 : 0 : cfg->algo4115.ebs = profile->profile.trtcm_rfc4115.ebs;
1304 : 0 : break;
1305 : : default:
1306 : : break;
1307 : : }
1308 : :
1309 : 0 : cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_PASS;
1310 : 0 : cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_PASS;
1311 : 0 : cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_PASS;
1312 : :
1313 [ # # ]: 0 : if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1314 : : RTE_FLOW_ACTION_TYPE_DROP)
1315 : 0 : cfg->action[ROC_NIX_BPF_COLOR_GREEN] = ROC_NIX_BPF_ACTION_DROP;
1316 : :
1317 [ # # ]: 0 : if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1318 : : RTE_FLOW_ACTION_TYPE_DROP)
1319 : 0 : cfg->action[ROC_NIX_BPF_COLOR_YELLOW] = ROC_NIX_BPF_ACTION_DROP;
1320 : :
1321 [ # # ]: 0 : if (policy->actions[RTE_COLOR_RED].action_fate ==
1322 : : RTE_FLOW_ACTION_TYPE_DROP)
1323 : 0 : cfg->action[ROC_NIX_BPF_COLOR_RED] = ROC_NIX_BPF_ACTION_DROP;
1324 : 0 : }
1325 : :
1326 : : static void
1327 : 0 : nix_mtr_config_red(struct cnxk_meter_node *mtr, struct roc_nix_rq *rq,
1328 : : struct roc_nix_bpf_cfg *cfg)
1329 : : {
1330 : 0 : struct cnxk_mtr_policy_node *policy = mtr->policy;
1331 : :
1332 [ # # # # ]: 0 : if ((rq->red_pass && rq->red_pass >= rq->red_drop) ||
1333 [ # # # # ]: 0 : (rq->spb_red_pass && rq->spb_red_pass >= rq->spb_red_drop) ||
1334 [ # # # # ]: 0 : (rq->xqe_red_pass && rq->xqe_red_pass >= rq->xqe_red_drop)) {
1335 [ # # ]: 0 : if (policy->actions[RTE_COLOR_GREEN].action_fate ==
1336 : : RTE_FLOW_ACTION_TYPE_DROP) {
1337 [ # # ]: 0 : if (policy->actions[RTE_COLOR_GREEN].skip_red)
1338 : 0 : cfg->action[ROC_NIX_BPF_COLOR_GREEN] =
1339 : : ROC_NIX_BPF_ACTION_DROP;
1340 : : else
1341 : 0 : cfg->action[ROC_NIX_BPF_COLOR_GREEN] =
1342 : : ROC_NIX_BPF_ACTION_RED;
1343 : : }
1344 [ # # ]: 0 : if (policy->actions[RTE_COLOR_YELLOW].action_fate ==
1345 : : RTE_FLOW_ACTION_TYPE_DROP) {
1346 [ # # ]: 0 : if (policy->actions[RTE_COLOR_YELLOW].skip_red)
1347 : 0 : cfg->action[ROC_NIX_BPF_COLOR_YELLOW] =
1348 : : ROC_NIX_BPF_ACTION_DROP;
1349 : : else
1350 : 0 : cfg->action[ROC_NIX_BPF_COLOR_YELLOW] =
1351 : : ROC_NIX_BPF_ACTION_RED;
1352 : : }
1353 [ # # ]: 0 : if (policy->actions[RTE_COLOR_RED].action_fate ==
1354 : : RTE_FLOW_ACTION_TYPE_DROP) {
1355 [ # # ]: 0 : if (policy->actions[RTE_COLOR_RED].skip_red)
1356 : 0 : cfg->action[ROC_NIX_BPF_COLOR_RED] =
1357 : : ROC_NIX_BPF_ACTION_DROP;
1358 : : else
1359 : 0 : cfg->action[ROC_NIX_BPF_COLOR_RED] =
1360 : : ROC_NIX_BPF_ACTION_RED;
1361 : : }
1362 : : }
1363 : 0 : }
1364 : :
1365 : : static void
1366 : 0 : 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 : 0 : 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 [ # # # ]: 0 : switch (proto) {
1376 : 0 : case RTE_MTR_COLOR_IN_PROTO_OUTER_IP:
1377 : : case RTE_MTR_COLOR_IN_PROTO_INNER_IP:
1378 : 0 : tbl->count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_DSCP;
1379 : 0 : tbl->mode = (proto == RTE_MTR_COLOR_IN_PROTO_OUTER_IP) ?
1380 [ # # ]: 0 : ROC_NIX_BPF_PC_MODE_DSCP_OUTER :
1381 : : ROC_NIX_BPF_PC_MODE_DSCP_INNER;
1382 : :
1383 [ # # ]: 0 : for (i = 0; i < tbl->count; i++)
1384 : 0 : tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1385 : :
1386 [ # # ]: 0 : if (mtr->params.dscp_table) {
1387 [ # # ]: 0 : for (i = 0; i < tbl->count; i++)
1388 : 0 : tbl->color[i] =
1389 : 0 : color_map[mtr->params.dscp_table[i]];
1390 : : }
1391 : : break;
1392 : 0 : case RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN:
1393 : : case RTE_MTR_COLOR_IN_PROTO_INNER_VLAN:
1394 : 0 : tbl->count = ROC_NIX_BPF_PRECOLOR_TBL_SIZE_VLAN;
1395 : 0 : tbl->mode = (proto == RTE_MTR_COLOR_IN_PROTO_OUTER_VLAN) ?
1396 : 0 : ROC_NIX_BPF_PC_MODE_VLAN_OUTER :
1397 : : ROC_NIX_BPF_PC_MODE_VLAN_INNER;
1398 : :
1399 [ # # ]: 0 : for (i = 0; i < tbl->count; i++)
1400 : 0 : tbl->color[i] = ROC_NIX_BPF_COLOR_GREEN;
1401 : :
1402 [ # # ]: 0 : if (mtr->params.vlan_table) {
1403 [ # # ]: 0 : for (i = 0; i < tbl->count; i++)
1404 : 0 : tbl->color[i] =
1405 : 0 : color_map[mtr->params.vlan_table[i]];
1406 : : }
1407 : : break;
1408 : : default:
1409 : : break;
1410 : : }
1411 : 0 : }
1412 : :
1413 : : int
1414 : 0 : nix_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t id,
1415 : : struct rte_mtr_error *error)
1416 : : {
1417 : 0 : return cnxk_nix_mtr_destroy(eth_dev, id, error);
1418 : : }
1419 : :
1420 : : int
1421 : 0 : 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 : 0 : struct roc_nix *nix = &dev->nix;
1427 : : uint32_t cur_mtr_id = id;
1428 : : int rc, i;
1429 : :
1430 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1431 : : base_mtr = nix_mtr_find(dev, cur_mtr_id);
1432 [ # # ]: 0 : if (base_mtr) {
1433 : 0 : lvl_flag = lvl_map[base_mtr->level];
1434 [ # # ]: 0 : if (base_mtr->is_next) {
1435 : 0 : next_mtr = nix_mtr_find(dev, base_mtr->next_id);
1436 [ # # ]: 0 : if (next_mtr) {
1437 [ # # ]: 0 : if (!base_mtr->is_used) {
1438 : 0 : rc = roc_nix_bpf_connect(nix,
1439 : : lvl_flag,
1440 : 0 : base_mtr->bpf_id,
1441 : 0 : next_mtr->bpf_id);
1442 [ # # ]: 0 : if (rc)
1443 : 0 : return rc;
1444 : : }
1445 : : }
1446 : 0 : cur_mtr_id = base_mtr->next_id;
1447 : : }
1448 : : }
1449 : : }
1450 : : return 0;
1451 : : }
1452 : :
1453 : : int
1454 : 0 : nix_mtr_configure(struct rte_eth_dev *eth_dev, uint32_t id)
1455 : : {
1456 : 0 : 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 : 0 : int num_mtr[ROC_NIX_BPF_LEVEL_MAX] = {0};
1464 : 0 : 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 : 0 : mtr[0] = nix_mtr_find(dev, id);
1474 [ # # ]: 0 : if (mtr[0] == NULL)
1475 : : return -EINVAL;
1476 : :
1477 : 0 : num_mtr[0] = 1;
1478 : 0 : idx0 = roc_nix_bpf_level_to_idx(lvl_map[mtr[0]->level]);
1479 [ # # ]: 0 : if (idx0 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1480 : : return -EINVAL;
1481 : :
1482 : : lvl_mask = ROC_NIX_BPF_LEVEL_F_LEAF;
1483 [ # # ]: 0 : if (mtr[0]->is_used)
1484 : 0 : per_lvl_cnt[idx0] = 0;
1485 : : else
1486 : 0 : per_lvl_cnt[idx0] = 1;
1487 : :
1488 [ # # ]: 0 : if (mtr[0]->is_next) {
1489 : 0 : mtr[1] = nix_mtr_find(dev, mtr[0]->next_id);
1490 [ # # ]: 0 : if (mtr[1] == NULL)
1491 : : return -EINVAL;
1492 : 0 : num_mtr[1] = 1;
1493 : 0 : idx1 = roc_nix_bpf_level_to_idx(lvl_map[mtr[1]->level]);
1494 [ # # ]: 0 : if (idx1 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1495 : : return -EINVAL;
1496 : :
1497 : : lvl_mask |= ROC_NIX_BPF_LEVEL_F_MID;
1498 [ # # ]: 0 : if (mtr[1]->is_used)
1499 : 0 : per_lvl_cnt[idx1] = 0;
1500 : : else
1501 : 0 : per_lvl_cnt[idx1] = 1;
1502 : : }
1503 : :
1504 [ # # # # ]: 0 : if (mtr[1] && mtr[1]->is_next) {
1505 : 0 : mtr[2] = nix_mtr_find(dev, mtr[1]->next_id);
1506 [ # # ]: 0 : if (mtr[2] == NULL)
1507 : : return -EINVAL;
1508 : :
1509 : 0 : num_mtr[2] = 1;
1510 : 0 : idx2 = roc_nix_bpf_level_to_idx(lvl_map[mtr[2]->level]);
1511 [ # # ]: 0 : if (idx2 == ROC_NIX_BPF_LEVEL_IDX_INVALID)
1512 : : return -EINVAL;
1513 : :
1514 : 0 : lvl_mask |= ROC_NIX_BPF_LEVEL_F_TOP;
1515 [ # # ]: 0 : if (mtr[2]->is_used)
1516 : 0 : per_lvl_cnt[idx2] = 0;
1517 : : else
1518 : 0 : per_lvl_cnt[idx2] = 1;
1519 : : }
1520 : :
1521 : 0 : rc = roc_nix_bpf_alloc(nix, lvl_mask, per_lvl_cnt, profs);
1522 [ # # ]: 0 : if (rc)
1523 : : return rc;
1524 [ # # ]: 0 : if (mtr[0]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1525 : 0 : mtr[0]->bpf_id = profs[idx0].ids[0];
1526 : :
1527 : : if (num_mtr[0])
1528 [ # # # # ]: 0 : if (mtr[0]->is_next && idx1 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1529 [ # # ]: 0 : if (mtr[1]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1530 : 0 : mtr[1]->bpf_id = profs[idx1].ids[0];
1531 : :
1532 [ # # ]: 0 : if (num_mtr[1])
1533 [ # # # # ]: 0 : if (mtr[1]->is_next && idx2 != ROC_NIX_BPF_LEVEL_IDX_INVALID)
1534 [ # # ]: 0 : if (mtr[2]->bpf_id == ROC_NIX_BPF_ID_INVALID)
1535 : 0 : mtr[2]->bpf_id = profs[idx2].ids[0];
1536 : :
1537 [ # # ]: 0 : for (i = 0; i < ROC_NIX_BPF_LEVEL_MAX; i++) {
1538 [ # # ]: 0 : if (num_mtr[i]) {
1539 [ # # ]: 0 : if (!mtr[i]->is_used) {
1540 : : memset(&cfg, 0, sizeof(struct roc_nix_bpf_cfg));
1541 : 0 : nix_mtr_config_map(mtr[i], &cfg);
1542 [ # # ]: 0 : for (j = 0; j < mtr[i]->rq_num; j++) {
1543 : 0 : rq = &dev->rqs[mtr[i]->rq_id[j]];
1544 : 0 : nix_mtr_config_red(mtr[i], rq, &cfg);
1545 : : }
1546 : 0 : rc = roc_nix_bpf_config(nix, mtr[i]->bpf_id,
1547 : 0 : lvl_map[mtr[i]->level],
1548 : : &cfg);
1549 : :
1550 : : memset(&tbl, 0,
1551 : : sizeof(struct roc_nix_bpf_precolor));
1552 : 0 : nix_precolor_table_map(mtr[i], &tbl,
1553 : : dev->proto);
1554 : 0 : rc = roc_nix_bpf_pre_color_tbl_setup(nix,
1555 : 0 : mtr[i]->bpf_id, lvl_map[mtr[i]->level],
1556 : : &tbl);
1557 : :
1558 [ # # ]: 0 : if (mtr[i]->params.meter_enable) {
1559 [ # # ]: 0 : for (j = 0; j < mtr[i]->rq_num; j++) {
1560 : 0 : rq = &dev->rqs[mtr[i]->rq_id
1561 : 0 : [j]];
1562 : 0 : rc = roc_nix_bpf_ena_dis(nix,
1563 : 0 : mtr[i]->bpf_id, rq,
1564 : : true);
1565 : : }
1566 : : }
1567 : : }
1568 : : }
1569 : : }
1570 : :
1571 : : return rc;
1572 : : }
1573 : :
1574 : : int
1575 : 0 : 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 : 0 : uint32_t action_fate_red = policy->actions[RTE_COLOR_RED].action_fate;
1581 : 0 : uint32_t action_fate_green =
1582 : : policy->actions[RTE_COLOR_GREEN].action_fate;
1583 : 0 : uint32_t action_fate_yellow =
1584 : : policy->actions[RTE_COLOR_YELLOW].action_fate;
1585 : 0 : 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 [ # # ]: 0 : if (action_fate_green == RTE_FLOW_ACTION_TYPE_METER)
1591 : 0 : next_mtr_id = policy->actions[RTE_COLOR_GREEN].mtr_id;
1592 : :
1593 [ # # ]: 0 : if (action_fate_yellow == RTE_FLOW_ACTION_TYPE_METER)
1594 : 0 : next_mtr_id = policy->actions[RTE_COLOR_YELLOW].mtr_id;
1595 : :
1596 [ # # ]: 0 : if (action_fate_red == RTE_FLOW_ACTION_TYPE_METER)
1597 : 0 : next_mtr_id = policy->actions[RTE_COLOR_RED].mtr_id;
1598 : :
1599 [ # # ]: 0 : if (next_mtr_id != 0xffff) {
1600 [ # # # # ]: 0 : switch (*tree_level) {
1601 : 0 : case 0:
1602 : 0 : mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1603 [ # # ]: 0 : if (mtr == NULL)
1604 : : return -EINVAL;
1605 [ # # ]: 0 : if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1606 : 0 : nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1607 : 0 : nix_mtr_chain_update(eth_dev, cur_mtr_id, -1,
1608 : : next_mtr_id);
1609 : : } else {
1610 [ # # ]: 0 : if (mtr->level == 0)
1611 : 0 : mtr->is_used = true;
1612 : : else
1613 : : return -EINVAL;
1614 : : }
1615 : 0 : (*tree_level)++;
1616 : 0 : *next_id = next_mtr_id;
1617 : 0 : break;
1618 : 0 : case 1:
1619 : 0 : mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1620 [ # # ]: 0 : if (mtr == NULL)
1621 : : return -EINVAL;
1622 [ # # ]: 0 : if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1623 : 0 : nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1624 : : prev_mtr_id = id;
1625 : 0 : nix_mtr_chain_update(eth_dev, cur_mtr_id,
1626 : : prev_mtr_id, next_mtr_id);
1627 : : } else {
1628 [ # # ]: 0 : if (mtr->level == 1) {
1629 : 0 : mtr->prev_cnt++;
1630 : : prev_mtr_id = id;
1631 : 0 : nix_mtr_chain_update(eth_dev,
1632 : : cur_mtr_id, prev_mtr_id,
1633 : : next_mtr_id);
1634 : :
1635 : 0 : mtr->is_used = true;
1636 : : } else {
1637 : : return -EINVAL;
1638 : : }
1639 : : }
1640 : 0 : (*tree_level)++;
1641 : 0 : *next_id = next_mtr_id;
1642 : 0 : *prev_id = cur_mtr_id;
1643 : 0 : break;
1644 : 0 : case 2:
1645 : 0 : nix_mtr_chain_reset(eth_dev, id);
1646 : 0 : return -EINVAL;
1647 : : }
1648 : : } else {
1649 [ # # # # ]: 0 : switch (*tree_level) {
1650 : 0 : case 0:
1651 : 0 : mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1652 [ # # ]: 0 : if (mtr == NULL)
1653 : : return -EINVAL;
1654 [ # # ]: 0 : if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1655 : 0 : nix_mtr_level_update(eth_dev, cur_mtr_id, 0);
1656 : : } else {
1657 [ # # ]: 0 : if (mtr->level == 0)
1658 : 0 : mtr->is_used = true;
1659 : : else
1660 : : return -EINVAL;
1661 : : }
1662 : : break;
1663 : 0 : case 1:
1664 : 0 : mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1665 [ # # ]: 0 : if (mtr == NULL)
1666 : : return -EINVAL;
1667 [ # # ]: 0 : if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1668 : 0 : nix_mtr_level_update(eth_dev, cur_mtr_id, 1);
1669 : : prev_mtr_id = id;
1670 : 0 : nix_mtr_chain_update(eth_dev, cur_mtr_id,
1671 : : prev_mtr_id, -1);
1672 : : } else {
1673 [ # # ]: 0 : if (mtr->level == 1) {
1674 : 0 : mtr->prev_cnt++;
1675 : : prev_mtr_id = id;
1676 : 0 : nix_mtr_chain_update(eth_dev,
1677 : : cur_mtr_id,
1678 : : prev_mtr_id, -1);
1679 : 0 : mtr->is_used = true;
1680 : : } else {
1681 : : return -EINVAL;
1682 : : }
1683 : : }
1684 : : break;
1685 : 0 : case 2:
1686 : 0 : mtr = nix_get_mtr(eth_dev, cur_mtr_id);
1687 [ # # ]: 0 : if (mtr == NULL)
1688 : : return -EINVAL;
1689 [ # # ]: 0 : if (mtr->level == ROC_NIX_BPF_LEVEL_IDX_INVALID) {
1690 : 0 : nix_mtr_level_update(eth_dev, cur_mtr_id, 2);
1691 : 0 : prev_mtr_id = *prev_id;
1692 : 0 : nix_mtr_chain_update(eth_dev, cur_mtr_id,
1693 : : prev_mtr_id, -1);
1694 : : } else {
1695 [ # # ]: 0 : if (mtr->level == 2) {
1696 : 0 : mtr->prev_cnt++;
1697 : 0 : prev_mtr_id = *prev_id;
1698 : 0 : nix_mtr_chain_update(eth_dev,
1699 : : cur_mtr_id,
1700 : : prev_mtr_id, -1);
1701 : 0 : mtr->is_used = true;
1702 : : } else {
1703 : : return -EINVAL;
1704 : : }
1705 : : }
1706 : : break;
1707 : : }
1708 : 0 : *next_id = 0xffff;
1709 : : }
1710 : :
1711 : : return 0;
1712 : : }
1713 : :
1714 : : int
1715 : 0 : 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 : 0 : return cnxk_nix_mtr_capabilities_get(eth_dev, &capa, &error);
1721 : : }
|