net/softnic: destroy meter object
[dpdk.git] / drivers / net / softnic / rte_eth_softnic_meter.c
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
15 softnic_mtr_init(struct pmd_internals *p)
16 {
17         /* Initialize meter profiles list */
18         TAILQ_INIT(&p->mtr.meter_profiles);
19
20         /* Initialize MTR objects list */
21         TAILQ_INIT(&p->mtr.mtrs);
22
23         return 0;
24 }
25
26 void
27 softnic_mtr_free(struct pmd_internals *p)
28 {
29         /* Remove MTR objects */
30         for ( ; ; ) {
31                 struct softnic_mtr *m;
32
33                 m = TAILQ_FIRST(&p->mtr.mtrs);
34                 if (m == NULL)
35                         break;
36
37                 TAILQ_REMOVE(&p->mtr.mtrs, m, node);
38                 free(m);
39         }
40
41         /* Remove meter profiles */
42         for ( ; ; ) {
43                 struct softnic_mtr_meter_profile *mp;
44
45                 mp = TAILQ_FIRST(&p->mtr.meter_profiles);
46                 if (mp == NULL)
47                         break;
48
49                 TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
50                 free(mp);
51         }
52 }
53
54 struct softnic_mtr_meter_profile *
55 softnic_mtr_meter_profile_find(struct pmd_internals *p,
56         uint32_t meter_profile_id)
57 {
58         struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
59         struct softnic_mtr_meter_profile *mp;
60
61         TAILQ_FOREACH(mp, mpl, node)
62                 if (meter_profile_id == mp->meter_profile_id)
63                         return mp;
64
65         return NULL;
66 }
67
68 static int
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)
73 {
74         struct pmd_internals *p = dev->data->dev_private;
75         struct softnic_mtr_meter_profile *mp;
76
77         /* Meter profile ID must be valid. */
78         if (meter_profile_id == UINT32_MAX)
79                 return -rte_mtr_error_set(error,
80                         EINVAL,
81                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
82                         NULL,
83                         "Meter profile id not valid");
84
85         /* Meter profile must not exist. */
86         mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
87         if (mp)
88                 return -rte_mtr_error_set(error,
89                         EEXIST,
90                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
91                         NULL,
92                         "Meter prfile already exists");
93
94         /* Profile must not be NULL. */
95         if (profile == NULL)
96                 return -rte_mtr_error_set(error,
97                         EINVAL,
98                         RTE_MTR_ERROR_TYPE_METER_PROFILE,
99                         NULL,
100                         "profile null");
101
102         /* Traffic metering algorithm : TRTCM_RFC2698 */
103         if (profile->alg != RTE_MTR_TRTCM_RFC2698)
104                 return -rte_mtr_error_set(error,
105                         EINVAL,
106                         RTE_MTR_ERROR_TYPE_METER_PROFILE,
107                         NULL,
108                         "Metering alg not supported");
109
110         return 0;
111 }
112
113 /* MTR meter profile add */
114 static int
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)
119 {
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;
123         int status;
124
125         /* Check input params */
126         status = meter_profile_check(dev, meter_profile_id, profile, error);
127         if (status)
128                 return status;
129
130         /* Memory allocation */
131         mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
132         if (mp == NULL)
133                 return -rte_mtr_error_set(error,
134                         ENOMEM,
135                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
136                         NULL,
137                         "Memory alloc failed");
138
139         /* Fill in */
140         mp->meter_profile_id = meter_profile_id;
141         memcpy(&mp->params, profile, sizeof(mp->params));
142
143         /* Add to list */
144         TAILQ_INSERT_TAIL(mpl, mp, node);
145
146         return 0;
147 }
148
149 /* MTR meter profile delete */
150 static int
151 pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
152         uint32_t meter_profile_id,
153         struct rte_mtr_error *error)
154 {
155         struct pmd_internals *p = dev->data->dev_private;
156         struct softnic_mtr_meter_profile *mp;
157
158         /* Meter profile must exist */
159         mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
160         if (mp == NULL)
161                 return -rte_mtr_error_set(error,
162                         EINVAL,
163                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
164                         NULL,
165                         "Meter profile id invalid");
166
167         /* Check unused */
168         if (mp->n_users)
169                 return -rte_mtr_error_set(error,
170                         EBUSY,
171                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
172                         NULL,
173                         "Meter profile in use");
174
175         /* Remove from list */
176         TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
177         free(mp);
178
179         return 0;
180 }
181
182 struct softnic_mtr *
183 softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
184 {
185         struct softnic_mtr_list *ml = &p->mtr.mtrs;
186         struct softnic_mtr *m;
187
188         TAILQ_FOREACH(m, ml, node)
189                 if (m->mtr_id == mtr_id)
190                         return m;
191
192         return NULL;
193 }
194
195
196 static int
197 mtr_check(struct pmd_internals *p,
198         uint32_t mtr_id,
199         struct rte_mtr_params *params,
200         int shared,
201         struct rte_mtr_error *error)
202 {
203         /* MTR id valid  */
204         if (softnic_mtr_find(p, mtr_id))
205                 return -rte_mtr_error_set(error,
206                         EEXIST,
207                         RTE_MTR_ERROR_TYPE_MTR_ID,
208                         NULL,
209                         "MTR object already exists");
210
211         /* MTR params must not be NULL */
212         if (params == NULL)
213                 return -rte_mtr_error_set(error,
214                         EINVAL,
215                         RTE_MTR_ERROR_TYPE_MTR_PARAMS,
216                         NULL,
217                         "MTR object params null");
218
219         /* Previous meter color not supported */
220         if (params->use_prev_mtr_color)
221                 return -rte_mtr_error_set(error,
222                         EINVAL,
223                         RTE_MTR_ERROR_TYPE_MTR_PARAMS,
224                         NULL,
225                         "Previous meter color not supported");
226
227         /* Shared MTR object not supported */
228         if (shared)
229                 return -rte_mtr_error_set(error,
230                         EINVAL,
231                         RTE_MTR_ERROR_TYPE_SHARED,
232                         NULL,
233                         "Shared MTR object not supported");
234
235         return 0;
236 }
237
238 /* MTR object create */
239 static int
240 pmd_mtr_create(struct rte_eth_dev *dev,
241         uint32_t mtr_id,
242         struct rte_mtr_params *params,
243         int shared,
244         struct rte_mtr_error *error)
245 {
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;
250         int status;
251
252         /* Check parameters */
253         status = mtr_check(p, mtr_id, params, shared, error);
254         if (status)
255                 return status;
256
257         /* Meter profile must exist */
258         mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
259         if (mp == NULL)
260                 return -rte_mtr_error_set(error,
261                         EINVAL,
262                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
263                         NULL,
264                         "Meter profile id not valid");
265
266         /* Memory allocation */
267         m = calloc(1, sizeof(struct softnic_mtr));
268         if (m == NULL)
269                 return -rte_mtr_error_set(error,
270                         ENOMEM,
271                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
272                         NULL,
273                         "Memory alloc failed");
274
275         /* Fill in */
276         m->mtr_id = mtr_id;
277         memcpy(&m->params, params, sizeof(m->params));
278
279         /* Add to list */
280         TAILQ_INSERT_TAIL(ml, m, node);
281
282         /* Update dependencies */
283         mp->n_users++;
284
285         return 0;
286 }
287
288 /* MTR object destroy */
289 static int
290 pmd_mtr_destroy(struct rte_eth_dev *dev,
291         uint32_t mtr_id,
292         struct rte_mtr_error *error)
293 {
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;
298
299         /* MTR object must exist */
300         m = softnic_mtr_find(p, mtr_id);
301         if (m == NULL)
302                 return -rte_mtr_error_set(error,
303                         EEXIST,
304                         RTE_MTR_ERROR_TYPE_MTR_ID,
305                         NULL,
306                         "MTR object id not valid");
307
308         /* MTR object must not have any owner */
309         if (m->flow != NULL)
310                 return -rte_mtr_error_set(error,
311                         EINVAL,
312                         RTE_MTR_ERROR_TYPE_UNSPECIFIED,
313                         NULL,
314                         "MTR object is being used");
315
316         /* Get meter profile */
317         mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
318         if (mp == NULL)
319                 return -rte_mtr_error_set(error,
320                         EINVAL,
321                         RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
322                         NULL,
323                         "MTR object meter profile invalid");
324
325         /* Update dependencies */
326         mp->n_users--;
327
328         /* Remove from list */
329         TAILQ_REMOVE(ml, m, node);
330         free(m);
331
332         return 0;
333 }
334
335 const struct rte_mtr_ops pmd_mtr_ops = {
336         .capabilities_get = NULL,
337
338         .meter_profile_add = pmd_mtr_meter_profile_add,
339         .meter_profile_delete = pmd_mtr_meter_profile_delete,
340
341         .create = pmd_mtr_create,
342         .destroy = pmd_mtr_destroy,
343         .meter_enable = NULL,
344         .meter_disable = NULL,
345
346         .meter_profile_update = NULL,
347         .meter_dscp_table_update = NULL,
348         .policer_actions_update = NULL,
349         .stats_update = NULL,
350
351         .stats_read = NULL,
352 };