1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
3 */
4
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include <rte_mtr.h>
10 #include <rte_mtr_driver.h>
11
12 #include "rte_eth_softnic_internals.h"
13
14 int
softnic_mtr_init(struct pmd_internals * p)15 softnic_mtr_init(struct pmd_internals *p)
16 {
17 /* Initialize meter profiles list */
18 TAILQ_INIT(&p->mtr.meter_profiles);
19
20 /* Initialize meter policies list */
21 TAILQ_INIT(&p->mtr.meter_policies);
22
23 /* Initialize MTR objects list */
24 TAILQ_INIT(&p->mtr.mtrs);
25
26 return 0;
27 }
28
29 void
softnic_mtr_free(struct pmd_internals * p)30 softnic_mtr_free(struct pmd_internals *p)
31 {
32 /* Remove MTR objects */
33 for ( ; ; ) {
34 struct softnic_mtr *m;
35
36 m = TAILQ_FIRST(&p->mtr.mtrs);
37 if (m == NULL)
38 break;
39
40 TAILQ_REMOVE(&p->mtr.mtrs, m, node);
41 free(m);
42 }
43
44 /* Remove meter profiles */
45 for ( ; ; ) {
46 struct softnic_mtr_meter_profile *mp;
47
48 mp = TAILQ_FIRST(&p->mtr.meter_profiles);
49 if (mp == NULL)
50 break;
51
52 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
53 free(mp);
54 }
55
56 /* Remove meter policies */
57 for ( ; ; ) {
58 struct softnic_mtr_meter_policy *mp;
59
60 mp = TAILQ_FIRST(&p->mtr.meter_policies);
61 if (mp == NULL)
62 break;
63
64 TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
65 free(mp);
66 }
67 }
68
69 struct softnic_mtr_meter_profile *
softnic_mtr_meter_profile_find(struct pmd_internals * p,uint32_t meter_profile_id)70 softnic_mtr_meter_profile_find(struct pmd_internals *p,
71 uint32_t meter_profile_id)
72 {
73 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
74 struct softnic_mtr_meter_profile *mp;
75
76 TAILQ_FOREACH(mp, mpl, node)
77 if (meter_profile_id == mp->meter_profile_id)
78 return mp;
79
80 return NULL;
81 }
82
83 static int
meter_profile_check(struct rte_eth_dev * dev,uint32_t meter_profile_id,struct rte_mtr_meter_profile * profile,struct rte_mtr_error * error)84 meter_profile_check(struct rte_eth_dev *dev,
85 uint32_t meter_profile_id,
86 struct rte_mtr_meter_profile *profile,
87 struct rte_mtr_error *error)
88 {
89 struct pmd_internals *p = dev->data->dev_private;
90 struct softnic_mtr_meter_profile *mp;
91
92 /* Meter profile ID must be valid. */
93 if (meter_profile_id == UINT32_MAX)
94 return -rte_mtr_error_set(error,
95 EINVAL,
96 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
97 NULL,
98 "Meter profile id not valid");
99
100 /* Meter profile must not exist. */
101 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
102 if (mp)
103 return -rte_mtr_error_set(error,
104 EEXIST,
105 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
106 NULL,
107 "Meter prfile already exists");
108
109 /* Profile must not be NULL. */
110 if (profile == NULL)
111 return -rte_mtr_error_set(error,
112 EINVAL,
113 RTE_MTR_ERROR_TYPE_METER_PROFILE,
114 NULL,
115 "profile null");
116
117 /* Traffic metering algorithm : TRTCM_RFC2698 */
118 if (profile->alg != RTE_MTR_TRTCM_RFC2698)
119 return -rte_mtr_error_set(error,
120 EINVAL,
121 RTE_MTR_ERROR_TYPE_METER_PROFILE,
122 NULL,
123 "Metering alg not supported");
124
125 /* Not support packet mode, just support byte mode. */
126 if (profile->packet_mode)
127 return -rte_mtr_error_set(error,
128 EINVAL,
129 RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
130 NULL,
131 "Meter packet mode not supported");
132
133 return 0;
134 }
135
136 /* MTR meter profile add */
137 static int
pmd_mtr_meter_profile_add(struct rte_eth_dev * dev,uint32_t meter_profile_id,struct rte_mtr_meter_profile * profile,struct rte_mtr_error * error)138 pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
139 uint32_t meter_profile_id,
140 struct rte_mtr_meter_profile *profile,
141 struct rte_mtr_error *error)
142 {
143 struct pmd_internals *p = dev->data->dev_private;
144 struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
145 struct softnic_mtr_meter_profile *mp;
146 int status;
147
148 /* Check input params */
149 status = meter_profile_check(dev, meter_profile_id, profile, error);
150 if (status)
151 return status;
152
153 /* Memory allocation */
154 mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
155 if (mp == NULL)
156 return -rte_mtr_error_set(error,
157 ENOMEM,
158 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
159 NULL,
160 "Memory alloc failed");
161
162 /* Fill in */
163 mp->meter_profile_id = meter_profile_id;
164 memcpy(&mp->params, profile, sizeof(mp->params));
165
166 /* Add to list */
167 TAILQ_INSERT_TAIL(mpl, mp, node);
168
169 return 0;
170 }
171
172 /* MTR meter profile delete */
173 static int
pmd_mtr_meter_profile_delete(struct rte_eth_dev * dev,uint32_t meter_profile_id,struct rte_mtr_error * error)174 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
175 uint32_t meter_profile_id,
176 struct rte_mtr_error *error)
177 {
178 struct pmd_internals *p = dev->data->dev_private;
179 struct softnic_mtr_meter_profile *mp;
180
181 /* Meter profile must exist */
182 mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
183 if (mp == NULL)
184 return -rte_mtr_error_set(error,
185 EINVAL,
186 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
187 NULL,
188 "Meter profile id invalid");
189
190 /* Check unused */
191 if (mp->n_users)
192 return -rte_mtr_error_set(error,
193 EBUSY,
194 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
195 NULL,
196 "Meter profile in use");
197
198 /* Remove from list */
199 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
200 free(mp);
201
202 return 0;
203 }
204
205 struct softnic_mtr_meter_policy *
softnic_mtr_meter_policy_find(struct pmd_internals * p,uint32_t meter_policy_id)206 softnic_mtr_meter_policy_find(struct pmd_internals *p,
207 uint32_t meter_policy_id)
208 {
209 struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
210 struct softnic_mtr_meter_policy *mp;
211
212 TAILQ_FOREACH(mp, mpl, node)
213 if (meter_policy_id == mp->meter_policy_id)
214 return mp;
215
216 return NULL;
217 }
218
219 /* MTR meter policy add */
220 static int
pmd_mtr_meter_policy_add(struct rte_eth_dev * dev,uint32_t meter_policy_id,struct rte_mtr_meter_policy_params * policy,struct rte_mtr_error * error)221 pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
222 uint32_t meter_policy_id,
223 struct rte_mtr_meter_policy_params *policy,
224 struct rte_mtr_error *error)
225 {
226 struct pmd_internals *p = dev->data->dev_private;
227 struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
228 struct softnic_mtr_meter_policy *mp;
229 const struct rte_flow_action *act;
230 const struct rte_flow_action_meter_color *recolor;
231 uint32_t i;
232 bool valid_act_found;
233
234 if (policy == NULL)
235 return -rte_mtr_error_set(error,
236 EINVAL,
237 RTE_MTR_ERROR_TYPE_METER_POLICY,
238 NULL,
239 "Null meter policy invalid");
240
241 /* Meter policy must not exist. */
242 mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
243 if (mp != NULL)
244 return -rte_mtr_error_set(error,
245 EINVAL,
246 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
247 NULL,
248 "Meter policy already exists");
249
250 for (i = 0; i < RTE_COLORS; i++) {
251 if (policy->actions[i] == NULL)
252 return -rte_mtr_error_set(error,
253 EINVAL,
254 RTE_MTR_ERROR_TYPE_METER_POLICY,
255 NULL,
256 "Null action list");
257 for (act = policy->actions[i], valid_act_found = false;
258 act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
259 if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
260 continue;
261 /*
262 * Support one (and one only) of
263 * METER_COLOR or DROP action.
264 */
265 if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
266 act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
267 valid_act_found)
268 return -rte_mtr_error_set(error,
269 EINVAL,
270 RTE_MTR_ERROR_TYPE_METER_POLICY,
271 NULL,
272 "Action invalid");
273 valid_act_found = true;
274 }
275 if (!valid_act_found)
276 return -rte_mtr_error_set(error,
277 EINVAL,
278 RTE_MTR_ERROR_TYPE_METER_POLICY,
279 NULL,
280 "No valid action found");
281 }
282
283 /* Memory allocation */
284 mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
285 if (mp == NULL)
286 return -rte_mtr_error_set(error,
287 ENOMEM,
288 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
289 NULL,
290 "Memory alloc failed");
291
292 /* Fill in */
293 mp->meter_policy_id = meter_policy_id;
294 for (i = 0; i < RTE_COLORS; i++) {
295 mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
296 act = policy->actions[i];
297 if (!act)
298 continue;
299 if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
300 recolor = act->conf;
301 switch (recolor->color) {
302 case RTE_COLOR_GREEN:
303 mp->policer[i] =
304 RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
305 break;
306 case RTE_COLOR_YELLOW:
307 mp->policer[i] =
308 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
309 break;
310 case RTE_COLOR_RED:
311 mp->policer[i] =
312 RTE_TABLE_ACTION_POLICER_COLOR_RED;
313 break;
314 default:
315 break;
316 }
317 }
318 }
319
320 /* Add to list */
321 TAILQ_INSERT_TAIL(mpl, mp, node);
322
323 return 0;
324 }
325
326 /* MTR meter policy delete */
327 static int
pmd_mtr_meter_policy_delete(struct rte_eth_dev * dev,uint32_t meter_policy_id,struct rte_mtr_error * error)328 pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
329 uint32_t meter_policy_id,
330 struct rte_mtr_error *error)
331 {
332 struct pmd_internals *p = dev->data->dev_private;
333 struct softnic_mtr_meter_policy *mp;
334
335 /* Meter policy must exist */
336 mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
337 if (mp == NULL)
338 return -rte_mtr_error_set(error,
339 EINVAL,
340 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
341 NULL,
342 "Meter policy id invalid");
343
344 /* Check unused */
345 if (mp->n_users)
346 return -rte_mtr_error_set(error,
347 EBUSY,
348 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
349 NULL,
350 "Meter policy in use");
351
352 /* Remove from list */
353 TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
354 free(mp);
355
356 return 0;
357 }
358
359 struct softnic_mtr *
softnic_mtr_find(struct pmd_internals * p,uint32_t mtr_id)360 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
361 {
362 struct softnic_mtr_list *ml = &p->mtr.mtrs;
363 struct softnic_mtr *m;
364
365 TAILQ_FOREACH(m, ml, node)
366 if (m->mtr_id == mtr_id)
367 return m;
368
369 return NULL;
370 }
371
372
373 static int
mtr_check(struct pmd_internals * p,uint32_t mtr_id,struct rte_mtr_params * params,int shared,struct rte_mtr_error * error)374 mtr_check(struct pmd_internals *p,
375 uint32_t mtr_id,
376 struct rte_mtr_params *params,
377 int shared,
378 struct rte_mtr_error *error)
379 {
380 /* MTR id valid */
381 if (softnic_mtr_find(p, mtr_id))
382 return -rte_mtr_error_set(error,
383 EEXIST,
384 RTE_MTR_ERROR_TYPE_MTR_ID,
385 NULL,
386 "MTR object already exists");
387
388 /* MTR params must not be NULL */
389 if (params == NULL)
390 return -rte_mtr_error_set(error,
391 EINVAL,
392 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
393 NULL,
394 "MTR object params null");
395
396 /* Previous meter color not supported */
397 if (params->use_prev_mtr_color)
398 return -rte_mtr_error_set(error,
399 EINVAL,
400 RTE_MTR_ERROR_TYPE_MTR_PARAMS,
401 NULL,
402 "Previous meter color not supported");
403
404 /* Shared MTR object not supported */
405 if (shared)
406 return -rte_mtr_error_set(error,
407 EINVAL,
408 RTE_MTR_ERROR_TYPE_SHARED,
409 NULL,
410 "Shared MTR object not supported");
411
412 return 0;
413 }
414
415 /* MTR object create */
416 static int
pmd_mtr_create(struct rte_eth_dev * dev,uint32_t mtr_id,struct rte_mtr_params * params,int shared,struct rte_mtr_error * error)417 pmd_mtr_create(struct rte_eth_dev *dev,
418 uint32_t mtr_id,
419 struct rte_mtr_params *params,
420 int shared,
421 struct rte_mtr_error *error)
422 {
423 struct pmd_internals *p = dev->data->dev_private;
424 struct softnic_mtr_list *ml = &p->mtr.mtrs;
425 struct softnic_mtr_meter_profile *mp;
426 struct softnic_mtr_meter_policy *policy;
427 struct softnic_mtr *m;
428 int status;
429
430 /* Check parameters */
431 status = mtr_check(p, mtr_id, params, shared, error);
432 if (status)
433 return status;
434
435 /* Meter profile must exist */
436 mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
437 if (mp == NULL)
438 return -rte_mtr_error_set(error,
439 EINVAL,
440 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
441 NULL,
442 "Meter profile id not valid");
443
444 /* Meter policy must exist */
445 policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
446 if (policy == NULL) {
447 return -rte_mtr_error_set(error,
448 EINVAL,
449 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
450 NULL,
451 "Meter policy id invalid");
452 }
453
454 /* Memory allocation */
455 m = calloc(1, sizeof(struct softnic_mtr));
456 if (m == NULL)
457 return -rte_mtr_error_set(error,
458 ENOMEM,
459 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
460 NULL,
461 "Memory alloc failed");
462
463 /* Fill in */
464 m->mtr_id = mtr_id;
465 memcpy(&m->params, params, sizeof(m->params));
466
467 /* Add to list */
468 TAILQ_INSERT_TAIL(ml, m, node);
469
470 /* Update dependencies */
471 mp->n_users++;
472 policy->n_users++;
473
474 return 0;
475 }
476
477 /* MTR object destroy */
478 static int
pmd_mtr_destroy(struct rte_eth_dev * dev,uint32_t mtr_id,struct rte_mtr_error * error)479 pmd_mtr_destroy(struct rte_eth_dev *dev,
480 uint32_t mtr_id,
481 struct rte_mtr_error *error)
482 {
483 struct pmd_internals *p = dev->data->dev_private;
484 struct softnic_mtr_list *ml = &p->mtr.mtrs;
485 struct softnic_mtr_meter_profile *mp;
486 struct softnic_mtr *m;
487 struct softnic_mtr_meter_policy *policy;
488
489 /* MTR object must exist */
490 m = softnic_mtr_find(p, mtr_id);
491 if (m == NULL)
492 return -rte_mtr_error_set(error,
493 EEXIST,
494 RTE_MTR_ERROR_TYPE_MTR_ID,
495 NULL,
496 "MTR object id not valid");
497
498 /* MTR object must not have any owner */
499 if (m->flow != NULL)
500 return -rte_mtr_error_set(error,
501 EINVAL,
502 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
503 NULL,
504 "MTR object is being used");
505
506 /* Get meter profile */
507 mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
508 if (mp == NULL)
509 return -rte_mtr_error_set(error,
510 EINVAL,
511 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
512 NULL,
513 "MTR object meter profile invalid");
514
515 /* Meter policy must exist */
516 policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
517 if (policy == NULL)
518 return -rte_mtr_error_set(error,
519 EINVAL,
520 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
521 NULL,
522 "MTR object meter policy invalid");
523
524 /* Update dependencies */
525 mp->n_users--;
526 policy->n_users--;
527
528 /* Remove from list */
529 TAILQ_REMOVE(ml, m, node);
530 free(m);
531
532 return 0;
533 }
534
535 /* MTR object meter profile update */
536 static int
pmd_mtr_meter_profile_update(struct rte_eth_dev * dev,uint32_t mtr_id,uint32_t meter_profile_id,struct rte_mtr_error * error)537 pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
538 uint32_t mtr_id,
539 uint32_t meter_profile_id,
540 struct rte_mtr_error *error)
541 {
542 struct pmd_internals *p = dev->data->dev_private;
543 struct softnic_mtr_meter_profile *mp_new, *mp_old;
544 struct softnic_mtr *m;
545 int status;
546
547 /* MTR object id must be valid */
548 m = softnic_mtr_find(p, mtr_id);
549 if (m == NULL)
550 return -rte_mtr_error_set(error,
551 EEXIST,
552 RTE_MTR_ERROR_TYPE_MTR_ID,
553 NULL,
554 "MTR object id not valid");
555
556 /* Meter profile id must be valid */
557 mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
558 if (mp_new == NULL)
559 return -rte_mtr_error_set(error,
560 EINVAL,
561 RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
562 NULL,
563 "Meter profile not valid");
564
565 /* MTR object already set to meter profile id */
566 if (m->params.meter_profile_id == meter_profile_id)
567 return 0;
568
569 /* MTR object owner table update */
570 if (m->flow) {
571 uint32_t table_id = m->flow->table_id;
572 struct softnic_table *table = &m->flow->pipeline->table[table_id];
573 struct softnic_table_rule_action action;
574
575 if (!softnic_pipeline_table_meter_profile_find(table,
576 meter_profile_id)) {
577 struct rte_table_action_meter_profile profile;
578
579 memset(&profile, 0, sizeof(profile));
580
581 profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
582 profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
583 profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
584 profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
585 profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
586
587 /* Add meter profile to pipeline table */
588 status = softnic_pipeline_table_mtr_profile_add(p,
589 m->flow->pipeline->name,
590 table_id,
591 meter_profile_id,
592 &profile);
593 if (status)
594 return -rte_mtr_error_set(error,
595 EINVAL,
596 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
597 NULL,
598 "Table meter profile add failed");
599 }
600
601 /* Set meter action */
602 memcpy(&action, &m->flow->action, sizeof(action));
603
604 action.mtr.mtr[0].meter_profile_id = meter_profile_id;
605
606 /* Re-add rule */
607 status = softnic_pipeline_table_rule_add(p,
608 m->flow->pipeline->name,
609 table_id,
610 &m->flow->match,
611 &action,
612 &m->flow->data);
613 if (status)
614 return -rte_mtr_error_set(error,
615 EINVAL,
616 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
617 NULL,
618 "Pipeline table rule add failed");
619
620 /* Flow: update meter action */
621 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
622 }
623
624 mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
625
626 /* Meter: Set meter profile */
627 m->params.meter_profile_id = meter_profile_id;
628
629 /* Update dependencies*/
630 mp_old->n_users--;
631 mp_new->n_users++;
632
633 return 0;
634 }
635
636 /* MTR object meter DSCP table update */
637 static int
pmd_mtr_meter_dscp_table_update(struct rte_eth_dev * dev,uint32_t mtr_id,enum rte_color * dscp_table,struct rte_mtr_error * error)638 pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
639 uint32_t mtr_id,
640 enum rte_color *dscp_table,
641 struct rte_mtr_error *error)
642 {
643 struct pmd_internals *p = dev->data->dev_private;
644 struct rte_table_action_dscp_table dt;
645 struct pipeline *pipeline;
646 struct softnic_table *table;
647 struct softnic_mtr *m;
648 uint32_t table_id, i;
649 int status;
650
651 /* MTR object id must be valid */
652 m = softnic_mtr_find(p, mtr_id);
653 if (m == NULL)
654 return -rte_mtr_error_set(error,
655 EEXIST,
656 RTE_MTR_ERROR_TYPE_MTR_ID,
657 NULL,
658 "MTR object id not valid");
659
660 /* MTR object owner valid? */
661 if (m->flow == NULL)
662 return 0;
663
664 pipeline = m->flow->pipeline;
665 table_id = m->flow->table_id;
666 table = &pipeline->table[table_id];
667
668 memcpy(&dt, &table->dscp_table, sizeof(dt));
669 for (i = 0; i < RTE_DIM(dt.entry); i++)
670 dt.entry[i].color = (enum rte_color)dscp_table[i];
671
672 /* Update table */
673 status = softnic_pipeline_table_dscp_table_update(p,
674 pipeline->name,
675 table_id,
676 UINT64_MAX,
677 &dt);
678 if (status)
679 return -rte_mtr_error_set(error,
680 EINVAL,
681 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
682 NULL,
683 "Table action dscp table update failed");
684
685 return 0;
686 }
687
688 /* MTR object policy update */
689 static int
pmd_mtr_meter_policy_update(struct rte_eth_dev * dev,uint32_t mtr_id,uint32_t meter_policy_id,struct rte_mtr_error * error)690 pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
691 uint32_t mtr_id,
692 uint32_t meter_policy_id,
693 struct rte_mtr_error *error)
694 {
695 struct pmd_internals *p = dev->data->dev_private;
696 struct softnic_mtr *m;
697 uint32_t i;
698 int status;
699 struct softnic_mtr_meter_policy *mp_new, *mp_old;
700
701 /* MTR object id must be valid */
702 m = softnic_mtr_find(p, mtr_id);
703 if (m == NULL)
704 return -rte_mtr_error_set(error,
705 EEXIST,
706 RTE_MTR_ERROR_TYPE_MTR_ID,
707 NULL,
708 "MTR object id not valid");
709
710 if (m->params.meter_policy_id == meter_policy_id)
711 return 0;
712
713 /* Meter policy must exist */
714 mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
715 if (mp_new == NULL)
716 return -rte_mtr_error_set(error,
717 EINVAL,
718 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
719 NULL,
720 "Meter policy id invalid");
721
722 /* MTR object owner valid? */
723 if (m->flow) {
724 struct pipeline *pipeline = m->flow->pipeline;
725 struct softnic_table *table = &pipeline->table[m->flow->table_id];
726 struct softnic_table_rule_action action;
727
728 memcpy(&action, &m->flow->action, sizeof(action));
729
730 /* Set action */
731 for (i = 0; i < RTE_COLORS; i++)
732 action.mtr.mtr[0].policer[i] = mp_new->policer[i];
733
734 /* Re-add the rule */
735 status = softnic_pipeline_table_rule_add(p,
736 pipeline->name,
737 m->flow->table_id,
738 &m->flow->match,
739 &action,
740 &m->flow->data);
741 if (status)
742 return -rte_mtr_error_set(error,
743 EINVAL,
744 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
745 NULL,
746 "Pipeline table rule re-add failed");
747
748 /* Flow: Update meter action */
749 memcpy(&m->flow->action, &action, sizeof(m->flow->action));
750
751 /* Reset the meter stats */
752 rte_table_action_meter_read(table->a, m->flow->data,
753 1, NULL, 1);
754 }
755
756 mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
757 if (mp_old == NULL)
758 return -rte_mtr_error_set(error,
759 EINVAL,
760 RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
761 NULL,
762 "Old meter policy id invalid");
763
764 /* Meter: Set meter profile */
765 m->params.meter_policy_id = meter_policy_id;
766
767 /* Update dependencies*/
768 mp_old->n_users--;
769 mp_new->n_users++;
770
771 return 0;
772 }
773
774 #define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
775 RTE_MTR_STATS_N_PKTS_YELLOW | \
776 RTE_MTR_STATS_N_PKTS_RED | \
777 RTE_MTR_STATS_N_PKTS_DROPPED)
778
779 #define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
780 RTE_MTR_STATS_N_BYTES_YELLOW | \
781 RTE_MTR_STATS_N_BYTES_RED | \
782 RTE_MTR_STATS_N_BYTES_DROPPED)
783
784 /* MTR object stats read */
785 static void
mtr_stats_convert(struct pmd_internals * p,struct softnic_mtr * m,struct rte_table_action_mtr_counters_tc * in,struct rte_mtr_stats * out,uint64_t * out_mask)786 mtr_stats_convert(struct pmd_internals *p,
787 struct softnic_mtr *m,
788 struct rte_table_action_mtr_counters_tc *in,
789 struct rte_mtr_stats *out,
790 uint64_t *out_mask)
791 {
792 struct softnic_mtr_meter_policy *mp;
793
794 memset(&out, 0, sizeof(out));
795 *out_mask = 0;
796
797 /* Meter policy must exist */
798 mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
799 if (mp == NULL)
800 return;
801
802 if (in->n_packets_valid) {
803 uint32_t i;
804
805 for (i = 0; i < RTE_COLORS; i++) {
806 if (mp->policer[i] ==
807 RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
808 out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
809
810 if (mp->policer[i] ==
811 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
812 out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
813
814 if (mp->policer[i] ==
815 RTE_TABLE_ACTION_POLICER_COLOR_RED)
816 out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
817
818 if (mp->policer[i] ==
819 RTE_TABLE_ACTION_POLICER_DROP)
820 out->n_pkts_dropped += in->n_packets[i];
821 }
822
823 *out_mask |= MTR_STATS_PKTS_DEFAULT;
824 }
825
826 if (in->n_bytes_valid) {
827 uint32_t i;
828
829 for (i = 0; i < RTE_COLORS; i++) {
830 if (mp->policer[i] ==
831 RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
832 out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
833
834 if (mp->policer[i] ==
835 RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
836 out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
837
838 if (mp->policer[i] ==
839 RTE_TABLE_ACTION_POLICER_COLOR_RED)
840 out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
841
842 if (mp->policer[i] ==
843 RTE_TABLE_ACTION_POLICER_DROP)
844 out->n_bytes_dropped += in->n_bytes[i];
845 }
846
847 *out_mask |= MTR_STATS_BYTES_DEFAULT;
848 }
849 }
850
851 /* MTR object stats read */
852 static int
pmd_mtr_stats_read(struct rte_eth_dev * dev,uint32_t mtr_id,struct rte_mtr_stats * stats,uint64_t * stats_mask,int clear,struct rte_mtr_error * error)853 pmd_mtr_stats_read(struct rte_eth_dev *dev,
854 uint32_t mtr_id,
855 struct rte_mtr_stats *stats,
856 uint64_t *stats_mask,
857 int clear,
858 struct rte_mtr_error *error)
859 {
860 struct pmd_internals *p = dev->data->dev_private;
861 struct rte_table_action_mtr_counters counters;
862 struct pipeline *pipeline;
863 struct softnic_table *table;
864 struct softnic_mtr *m;
865 int status;
866
867 /* MTR object id must be valid */
868 m = softnic_mtr_find(p, mtr_id);
869 if (m == NULL)
870 return -rte_mtr_error_set(error,
871 EEXIST,
872 RTE_MTR_ERROR_TYPE_MTR_ID,
873 NULL,
874 "MTR object id not valid");
875
876 /* MTR meter object owner valid? */
877 if (m->flow == NULL) {
878 if (stats != NULL)
879 memset(stats, 0, sizeof(*stats));
880
881 if (stats_mask)
882 *stats_mask = MTR_STATS_PKTS_DEFAULT |
883 MTR_STATS_BYTES_DEFAULT;
884
885 return 0;
886 }
887
888 pipeline = m->flow->pipeline;
889 table = &pipeline->table[m->flow->table_id];
890
891 /* Meter stats read. */
892 status = rte_table_action_meter_read(table->a,
893 m->flow->data,
894 1,
895 &counters,
896 clear);
897 if (status)
898 return -rte_mtr_error_set(error,
899 EINVAL,
900 RTE_MTR_ERROR_TYPE_UNSPECIFIED,
901 NULL,
902 "Meter stats read failed");
903
904 /* Stats format conversion. */
905 if (stats || stats_mask) {
906 struct rte_mtr_stats s;
907 uint64_t s_mask = 0;
908
909 mtr_stats_convert(p,
910 m,
911 &counters.stats[0],
912 &s,
913 &s_mask);
914
915 if (stats)
916 memcpy(stats, &s, sizeof(*stats));
917
918 if (stats_mask)
919 *stats_mask = s_mask;
920 }
921
922 return 0;
923 }
924
925 const struct rte_mtr_ops pmd_mtr_ops = {
926 .capabilities_get = NULL,
927
928 .meter_profile_add = pmd_mtr_meter_profile_add,
929 .meter_profile_delete = pmd_mtr_meter_profile_delete,
930
931 .meter_policy_add = pmd_mtr_meter_policy_add,
932 .meter_policy_delete = pmd_mtr_meter_policy_delete,
933
934 .create = pmd_mtr_create,
935 .destroy = pmd_mtr_destroy,
936 .meter_enable = NULL,
937 .meter_disable = NULL,
938
939 .meter_profile_update = pmd_mtr_meter_profile_update,
940 .meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
941 .meter_policy_update = pmd_mtr_meter_policy_update,
942 .stats_update = NULL,
943
944 .stats_read = pmd_mtr_stats_read,
945 };
946