1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
10 #include <rte_mtr_driver.h>
12 #include "rte_eth_softnic_internals.h"
15 softnic_mtr_init(struct pmd_internals *p)
17 /* Initialize meter profiles list */
18 TAILQ_INIT(&p->mtr.meter_profiles);
20 /* Initialize MTR objects list */
21 TAILQ_INIT(&p->mtr.mtrs);
27 softnic_mtr_free(struct pmd_internals *p)
29 /* Remove MTR objects */
31 struct softnic_mtr *m;
33 m = TAILQ_FIRST(&p->mtr.mtrs);
37 TAILQ_REMOVE(&p->mtr.mtrs, m, node);
41 /* Remove meter profiles */
43 struct softnic_mtr_meter_profile *mp;
45 mp = TAILQ_FIRST(&p->mtr.meter_profiles);
49 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
54 struct softnic_mtr_meter_profile *
55 softnic_mtr_meter_profile_find(struct pmd_internals *p,
56 uint32_t meter_profile_id)
58 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
59 struct softnic_mtr_meter_profile *mp;
61 TAILQ_FOREACH(mp, mpl, node)
62 if (meter_profile_id == mp->meter_profile_id)
69 meter_profile_check(struct rte_eth_dev *dev,
70 uint32_t meter_profile_id,
71 struct rte_mtr_meter_profile *profile,
72 struct rte_mtr_error *error)
74 struct pmd_internals *p = dev->data->dev_private;
75 struct softnic_mtr_meter_profile *mp;
77 /* Meter profile ID must be valid. */
78 if (meter_profile_id == UINT32_MAX)
79 return -rte_mtr_error_set(error,
81 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
83 "Meter profile id not valid");
85 /* Meter profile must not exist. */
86 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
88 return -rte_mtr_error_set(error,
90 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
92 "Meter prfile already exists");
94 /* Profile must not be NULL. */
96 return -rte_mtr_error_set(error,
98 RTE_MTR_ERROR_TYPE_METER_PROFILE,
102 /* Traffic metering algorithm : TRTCM_RFC2698 */
103 if (profile->alg != RTE_MTR_TRTCM_RFC2698)
104 return -rte_mtr_error_set(error,
106 RTE_MTR_ERROR_TYPE_METER_PROFILE,
108 "Metering alg not supported");
113 /* MTR meter profile add */
115 pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
116 uint32_t meter_profile_id,
117 struct rte_mtr_meter_profile *profile,
118 struct rte_mtr_error *error)
120 struct pmd_internals *p = dev->data->dev_private;
121 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
122 struct softnic_mtr_meter_profile *mp;
125 /* Check input params */
126 status = meter_profile_check(dev, meter_profile_id, profile, error);
130 /* Memory allocation */
131 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
133 return -rte_mtr_error_set(error,
135 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
137 "Memory alloc failed");
140 mp->meter_profile_id = meter_profile_id;
141 memcpy(&mp->params, profile, sizeof(mp->params));
144 TAILQ_INSERT_TAIL(mpl, mp, node);
149 /* MTR meter profile delete */
151 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
152 uint32_t meter_profile_id,
153 struct rte_mtr_error *error)
155 struct pmd_internals *p = dev->data->dev_private;
156 struct softnic_mtr_meter_profile *mp;
158 /* Meter profile must exist */
159 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
161 return -rte_mtr_error_set(error,
163 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
165 "Meter profile id invalid");
169 return -rte_mtr_error_set(error,
171 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
173 "Meter profile in use");
175 /* Remove from list */
176 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
183 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
185 struct softnic_mtr_list *ml = &p->mtr.mtrs;
186 struct softnic_mtr *m;
188 TAILQ_FOREACH(m, ml, node)
189 if (m->mtr_id == mtr_id)
197 mtr_check(struct pmd_internals *p,
199 struct rte_mtr_params *params,
201 struct rte_mtr_error *error)
204 if (softnic_mtr_find(p, mtr_id))
205 return -rte_mtr_error_set(error,
207 RTE_MTR_ERROR_TYPE_MTR_ID,
209 "MTR object already exists");
211 /* MTR params must not be NULL */
213 return -rte_mtr_error_set(error,
215 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
217 "MTR object params null");
219 /* Previous meter color not supported */
220 if (params->use_prev_mtr_color)
221 return -rte_mtr_error_set(error,
223 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
225 "Previous meter color not supported");
227 /* Shared MTR object not supported */
229 return -rte_mtr_error_set(error,
231 RTE_MTR_ERROR_TYPE_SHARED,
233 "Shared MTR object not supported");
238 /* MTR object create */
240 pmd_mtr_create(struct rte_eth_dev *dev,
242 struct rte_mtr_params *params,
244 struct rte_mtr_error *error)
246 struct pmd_internals *p = dev->data->dev_private;
247 struct softnic_mtr_list *ml = &p->mtr.mtrs;
248 struct softnic_mtr_meter_profile *mp;
249 struct softnic_mtr *m;
252 /* Check parameters */
253 status = mtr_check(p, mtr_id, params, shared, error);
257 /* Meter profile must exist */
258 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
260 return -rte_mtr_error_set(error,
262 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
264 "Meter profile id not valid");
266 /* Memory allocation */
267 m = calloc(1, sizeof(struct softnic_mtr));
269 return -rte_mtr_error_set(error,
271 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
273 "Memory alloc failed");
277 memcpy(&m->params, params, sizeof(m->params));
280 TAILQ_INSERT_TAIL(ml, m, node);
282 /* Update dependencies */
288 /* MTR object destroy */
290 pmd_mtr_destroy(struct rte_eth_dev *dev,
292 struct rte_mtr_error *error)
294 struct pmd_internals *p = dev->data->dev_private;
295 struct softnic_mtr_list *ml = &p->mtr.mtrs;
296 struct softnic_mtr_meter_profile *mp;
297 struct softnic_mtr *m;
299 /* MTR object must exist */
300 m = softnic_mtr_find(p, mtr_id);
302 return -rte_mtr_error_set(error,
304 RTE_MTR_ERROR_TYPE_MTR_ID,
306 "MTR object id not valid");
308 /* MTR object must not have any owner */
310 return -rte_mtr_error_set(error,
312 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
314 "MTR object is being used");
316 /* Get meter profile */
317 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
319 return -rte_mtr_error_set(error,
321 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
323 "MTR object meter profile invalid");
325 /* Update dependencies */
328 /* Remove from list */
329 TAILQ_REMOVE(ml, m, node);
335 /* MTR object meter profile update */
337 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
339 uint32_t meter_profile_id,
340 struct rte_mtr_error *error)
342 struct pmd_internals *p = dev->data->dev_private;
343 struct softnic_mtr_meter_profile *mp_new, *mp_old;
344 struct softnic_mtr *m;
347 /* MTR object id must be valid */
348 m = softnic_mtr_find(p, mtr_id);
350 return -rte_mtr_error_set(error,
352 RTE_MTR_ERROR_TYPE_MTR_ID,
354 "MTR object id not valid");
356 /* Meter profile id must be valid */
357 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
359 return -rte_mtr_error_set(error,
361 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
363 "Meter profile not valid");
365 /* MTR object already set to meter profile id */
366 if (m->params.meter_profile_id == meter_profile_id)
369 /* MTR object owner table update */
371 uint32_t table_id = m->flow->table_id;
372 struct softnic_table *table = &m->flow->pipeline->table[table_id];
373 struct softnic_table_rule_action action;
375 if (!softnic_pipeline_table_meter_profile_find(table,
377 struct rte_table_action_meter_profile profile;
379 memset(&profile, 0, sizeof(profile));
381 profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
382 profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
383 profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
384 profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
385 profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
387 /* Add meter profile to pipeline table */
388 status = softnic_pipeline_table_mtr_profile_add(p,
389 m->flow->pipeline->name,
394 return -rte_mtr_error_set(error,
396 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
398 "Table meter profile add failed");
401 /* Set meter action */
402 memcpy(&action, &m->flow->action, sizeof(action));
404 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
407 status = softnic_pipeline_table_rule_add(p,
408 m->flow->pipeline->name,
414 return -rte_mtr_error_set(error,
416 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
418 "Pipeline table rule add failed");
420 /* Flow: update meter action */
421 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
424 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
426 /* Meter: Set meter profile */
427 m->params.meter_profile_id = meter_profile_id;
429 /* Update dependencies*/
436 /* MTR object meter DSCP table update */
438 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
440 enum rte_mtr_color *dscp_table,
441 struct rte_mtr_error *error)
443 struct pmd_internals *p = dev->data->dev_private;
444 struct rte_table_action_dscp_table dt;
445 struct pipeline *pipeline;
446 struct softnic_table *table;
447 struct softnic_mtr *m;
448 uint32_t table_id, i;
451 /* MTR object id must be valid */
452 m = softnic_mtr_find(p, mtr_id);
454 return -rte_mtr_error_set(error,
456 RTE_MTR_ERROR_TYPE_MTR_ID,
458 "MTR object id not valid");
460 /* MTR object owner valid? */
464 pipeline = m->flow->pipeline;
465 table_id = m->flow->table_id;
466 table = &pipeline->table[table_id];
468 memcpy(&dt, &table->dscp_table, sizeof(dt));
469 for (i = 0; i < RTE_DIM(dt.entry); i++)
470 dt.entry[i].color = (enum rte_meter_color)dscp_table[i];
473 status = softnic_pipeline_table_dscp_table_update(p,
479 return -rte_mtr_error_set(error,
481 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
483 "Table action dscp table update failed");
488 const struct rte_mtr_ops pmd_mtr_ops = {
489 .capabilities_get = NULL,
491 .meter_profile_add = pmd_mtr_meter_profile_add,
492 .meter_profile_delete = pmd_mtr_meter_profile_delete,
494 .create = pmd_mtr_create,
495 .destroy = pmd_mtr_destroy,
496 .meter_enable = NULL,
497 .meter_disable = NULL,
499 .meter_profile_update = pmd_mtr_meter_profile_update,
500 .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
501 .policer_actions_update = NULL,
502 .stats_update = NULL,