9127d9a888aabb99f65a1893c6ccec5a587a2b5d
[dpdk.git] / drivers / net / cnxk / cnxk_ethdev_mtr.c
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_MAX      73 /* 64(leaf) + 8(mid) + 1(top) */
9 #define NIX_MTR_COUNT_PER_FLOW 3  /* 1(leaf) + 1(mid) + 1(top) */
10
11 static struct rte_mtr_capabilities mtr_capa = {
12         .n_max = NIX_MTR_COUNT_MAX,
13         .n_shared_max = NIX_MTR_COUNT_PER_FLOW,
14         /* .identical = , */
15         .shared_identical = true,
16         /* .shared_n_flows_per_mtr_max = ,*/
17         .chaining_n_mtrs_per_flow_max = NIX_MTR_COUNT_PER_FLOW,
18         .chaining_use_prev_mtr_color_supported = true,
19         .chaining_use_prev_mtr_color_enforced = true,
20         .meter_srtcm_rfc2697_n_max = NIX_MTR_COUNT_MAX,
21         .meter_trtcm_rfc2698_n_max = NIX_MTR_COUNT_MAX,
22         .meter_trtcm_rfc4115_n_max = NIX_MTR_COUNT_MAX,
23         .meter_rate_max = NIX_BPF_RATE_MAX / 8, /* Bytes per second */
24         .meter_policy_n_max = NIX_MTR_COUNT_MAX,
25         .color_aware_srtcm_rfc2697_supported = true,
26         .color_aware_trtcm_rfc2698_supported = true,
27         .color_aware_trtcm_rfc4115_supported = true,
28         .srtcm_rfc2697_byte_mode_supported = true,
29         .srtcm_rfc2697_packet_mode_supported = true,
30         .trtcm_rfc2698_byte_mode_supported = true,
31         .trtcm_rfc2698_packet_mode_supported = true,
32         .trtcm_rfc4115_byte_mode_supported = true,
33         .trtcm_rfc4115_packet_mode_supported = true,
34         .stats_mask = RTE_MTR_STATS_N_PKTS_GREEN | RTE_MTR_STATS_N_PKTS_YELLOW |
35                       RTE_MTR_STATS_N_PKTS_RED | RTE_MTR_STATS_N_PKTS_DROPPED |
36                       RTE_MTR_STATS_N_BYTES_GREEN |
37                       RTE_MTR_STATS_N_BYTES_YELLOW | RTE_MTR_STATS_N_BYTES_RED |
38                       RTE_MTR_STATS_N_BYTES_DROPPED};
39
40 static struct cnxk_mtr_profile_node *
41 nix_mtr_profile_find(struct cnxk_eth_dev *dev, uint32_t profile_id)
42 {
43         struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
44         struct cnxk_mtr_profile_node *fmp;
45
46         TAILQ_FOREACH(fmp, fmps, next)
47                 if (profile_id == fmp->id)
48                         return fmp;
49
50         return NULL;
51 }
52
53 static int
54 nix_mtr_profile_validate(struct cnxk_eth_dev *dev, uint32_t profile_id,
55                          struct rte_mtr_meter_profile *profile,
56                          struct rte_mtr_error *error)
57 {
58         int rc = 0;
59
60         PLT_SET_USED(dev);
61
62         if (profile == NULL)
63                 return -rte_mtr_error_set(error, EINVAL,
64                                           RTE_MTR_ERROR_TYPE_METER_PROFILE,
65                                           NULL, "Meter profile is null.");
66
67         if (profile_id == UINT32_MAX)
68                 return -rte_mtr_error_set(error, EINVAL,
69                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
70                                           NULL, "Meter profile id not valid.");
71
72         switch (profile->alg) {
73         case RTE_MTR_SRTCM_RFC2697:
74                 if (profile->srtcm_rfc2697.cir > mtr_capa.meter_rate_max)
75                         rc = -rte_mtr_error_set(error, EINVAL,
76                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
77                                 "CIR exceeds max meter rate");
78
79                 if (profile->srtcm_rfc2697.cbs > NIX_BPF_BURST_MAX)
80                         rc = -rte_mtr_error_set(error, EINVAL,
81                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
82                                 "CBS exceeds max meter burst size");
83
84                 if (profile->srtcm_rfc2697.ebs > NIX_BPF_BURST_MAX)
85                         rc = -rte_mtr_error_set(error, EINVAL,
86                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
87                                 "EBS exceeds max meter burst size");
88                 break;
89
90         case RTE_MTR_TRTCM_RFC2698:
91                 if (profile->trtcm_rfc2698.cir > mtr_capa.meter_rate_max)
92                         rc = -rte_mtr_error_set(error, EINVAL,
93                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
94                                 "CIR exceeds max meter rate");
95
96                 if (profile->trtcm_rfc2698.pir > mtr_capa.meter_rate_max)
97                         rc = -rte_mtr_error_set(error, EINVAL,
98                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
99                                 "PIR exceeds max meter rate");
100
101                 if (profile->trtcm_rfc2698.cbs > NIX_BPF_BURST_MAX)
102                         rc = -rte_mtr_error_set(error, EINVAL,
103                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
104                                 "CBS exceeds max meter burst size");
105
106                 if (profile->trtcm_rfc2698.pbs > NIX_BPF_BURST_MAX)
107                         rc = -rte_mtr_error_set(error, EINVAL,
108                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
109                                 "PBS exceeds max meter burst size");
110                 break;
111
112         case RTE_MTR_TRTCM_RFC4115:
113                 if ((profile->trtcm_rfc4115.cir + profile->trtcm_rfc4115.eir) >
114                     mtr_capa.meter_rate_max)
115                         rc = -rte_mtr_error_set(error, EINVAL,
116                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
117                                 "PIR + EIR exceeds max rate");
118
119                 if (profile->trtcm_rfc4115.cbs > NIX_BPF_BURST_MAX)
120                         rc = -rte_mtr_error_set(error, EINVAL,
121                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
122                                 "CBS exceeds max meter burst size");
123
124                 if (profile->trtcm_rfc4115.ebs > NIX_BPF_BURST_MAX)
125                         rc = -rte_mtr_error_set(error, EINVAL,
126                                 RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
127                                 "PBS exceeds max meter burst size");
128                 break;
129
130         default:
131                 rc = -rte_mtr_error_set(error, EINVAL,
132                                         RTE_MTR_ERROR_TYPE_METER_PROFILE, NULL,
133                                         "alg is invalid");
134                 break;
135         }
136
137         return rc;
138 }
139
140 static int
141 cnxk_nix_mtr_capabilities_get(struct rte_eth_dev *dev,
142                               struct rte_mtr_capabilities *capa,
143                               struct rte_mtr_error *error)
144 {
145         RTE_SET_USED(dev);
146
147         if (!capa)
148                 return -rte_mtr_error_set(error, EINVAL,
149                                           RTE_MTR_ERROR_TYPE_MTR_PARAMS, NULL,
150                                           "NULL input parameter");
151         *capa = mtr_capa;
152         return 0;
153 }
154
155 static int
156 cnxk_nix_mtr_profile_add(struct rte_eth_dev *eth_dev, uint32_t profile_id,
157                          struct rte_mtr_meter_profile *profile,
158                          struct rte_mtr_error *error)
159 {
160         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
161         struct cnxk_mtr_profiles *fmps = &dev->mtr_profiles;
162         struct cnxk_mtr_profile_node *fmp;
163         int ret;
164
165         /* Check input params. */
166         ret = nix_mtr_profile_validate(dev, profile_id, profile, error);
167         if (ret)
168                 return ret;
169
170         fmp = nix_mtr_profile_find(dev, profile_id);
171         if (fmp) {
172                 return -rte_mtr_error_set(error, EEXIST,
173                                           RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
174                                           NULL, "Profile already exist");
175         }
176
177         fmp = plt_zmalloc(sizeof(struct cnxk_mtr_profile_node), ROC_ALIGN);
178         if (fmp == NULL)
179                 return -rte_mtr_error_set(error, ENOMEM,
180                                           RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
181                                           "Meter profile memory "
182                                           "alloc failed.");
183
184         fmp->id = profile_id;
185         fmp->profile = *profile;
186
187         TAILQ_INSERT_TAIL(fmps, fmp, next);
188
189         return 0;
190 }
191
192 const struct rte_mtr_ops nix_mtr_ops = {
193         .capabilities_get = cnxk_nix_mtr_capabilities_get,
194         .meter_profile_add = cnxk_nix_mtr_profile_add,
195 };
196
197 int
198 cnxk_nix_mtr_ops_get(struct rte_eth_dev *dev, void *ops)
199 {
200         RTE_SET_USED(dev);
201
202         *(const void **)ops = &nix_mtr_ops;
203         return 0;
204 }