ebdc453fc9d863905da94a448112f2dd0a657471
[dpdk.git] / rte_meter.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #ifndef __INCLUDE_RTE_METER_H__
6 #define __INCLUDE_RTE_METER_H__
7
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11
12 /**
13  * @file
14  * RTE Traffic Metering
15  *
16  * Traffic metering algorithms:
17  *    1. Single Rate Three Color Marker (srTCM): defined by IETF RFC 2697
18  *    2. Two Rate Three Color Marker (trTCM): defined by IETF RFC 2698
19  *
20  ***/
21
22 #include <stdint.h>
23
24 /*
25  * Application Programmer's Interface (API)
26  *
27  ***/
28
29 /** Packet Color Set */
30 enum rte_meter_color {
31         e_RTE_METER_GREEN = 0, /**< Green */
32         e_RTE_METER_YELLOW,    /**< Yellow */
33         e_RTE_METER_RED,       /**< Red */
34         e_RTE_METER_COLORS     /**< Number of available colors */
35 };
36
37 /** srTCM parameters per metered traffic flow. The CIR, CBS and EBS parameters only
38 count bytes of IP packets and do not include link specific headers. At least one of
39 the CBS or EBS parameters has to be greater than zero. */
40 struct rte_meter_srtcm_params {
41         uint64_t cir; /**< Committed Information Rate (CIR). Measured in bytes per second. */
42         uint64_t cbs; /**< Committed Burst Size (CBS).  Measured in bytes. */
43         uint64_t ebs; /**< Excess Burst Size (EBS).  Measured in bytes. */
44 };
45
46 /** trTCM parameters per metered traffic flow. The CIR, PIR, CBS and PBS parameters
47 only count bytes of IP packets and do not include link specific headers. PIR has to
48 be greater than or equal to CIR. Both CBS or EBS have to be greater than zero. */
49 struct rte_meter_trtcm_params {
50         uint64_t cir; /**< Committed Information Rate (CIR). Measured in bytes per second. */
51         uint64_t pir; /**< Peak Information Rate (PIR). Measured in bytes per second. */
52         uint64_t cbs; /**< Committed Burst Size (CBS). Measured in byes. */
53         uint64_t pbs; /**< Peak Burst Size (PBS). Measured in bytes. */
54 };
55
56 /** Internal data structure storing the srTCM run-time context per metered traffic flow. */
57 struct rte_meter_srtcm;
58
59 /** Internal data structure storing the trTCM run-time context per metered traffic flow. */
60 struct rte_meter_trtcm;
61
62 /**
63  * srTCM configuration per metered traffic flow
64  *
65  * @param m
66  *    Pointer to pre-allocated srTCM data structure
67  * @param params
68  *    User parameters per srTCM metered traffic flow
69  * @return
70  *    0 upon success, error code otherwise
71  */
72 int
73 rte_meter_srtcm_config(struct rte_meter_srtcm *m,
74         struct rte_meter_srtcm_params *params);
75
76 /**
77  * trTCM configuration per metered traffic flow
78  *
79  * @param m
80  *    Pointer to pre-allocated trTCM data structure
81  * @param params
82  *    User parameters per trTCM metered traffic flow
83  * @return
84  *    0 upon success, error code otherwise
85  */
86 int
87 rte_meter_trtcm_config(struct rte_meter_trtcm *m,
88         struct rte_meter_trtcm_params *params);
89
90 /**
91  * srTCM color blind traffic metering
92  *
93  * @param m
94  *    Handle to srTCM instance
95  * @param time
96  *    Current CPU time stamp (measured in CPU cycles)
97  * @param pkt_len
98  *    Length of the current IP packet (measured in bytes)
99  * @return
100  *    Color assigned to the current IP packet
101  */
102 static inline enum rte_meter_color
103 rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m,
104         uint64_t time,
105         uint32_t pkt_len);
106
107 /**
108  * srTCM color aware traffic metering
109  *
110  * @param m
111  *    Handle to srTCM instance
112  * @param time
113  *    Current CPU time stamp (measured in CPU cycles)
114  * @param pkt_len
115  *    Length of the current IP packet (measured in bytes)
116  * @param pkt_color
117  *    Input color of the current IP packet
118  * @return
119  *    Color assigned to the current IP packet
120  */
121 static inline enum rte_meter_color
122 rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m,
123         uint64_t time,
124         uint32_t pkt_len,
125         enum rte_meter_color pkt_color);
126
127 /**
128  * trTCM color blind traffic metering
129  *
130  * @param m
131  *    Handle to trTCM instance
132  * @param time
133  *    Current CPU time stamp (measured in CPU cycles)
134  * @param pkt_len
135  *    Length of the current IP packet (measured in bytes)
136  * @return
137  *    Color assigned to the current IP packet
138  */
139 static inline enum rte_meter_color
140 rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m,
141         uint64_t time,
142         uint32_t pkt_len);
143
144 /**
145  * trTCM color aware traffic metering
146  *
147  * @param m
148  *    Handle to trTCM instance
149  * @param time
150  *    Current CPU time stamp (measured in CPU cycles)
151  * @param pkt_len
152  *    Length of the current IP packet (measured in bytes)
153  * @param pkt_color
154  *    Input color of the current IP packet
155  * @return
156  *    Color assigned to the current IP packet
157  */
158 static inline enum rte_meter_color
159 rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m,
160         uint64_t time,
161         uint32_t pkt_len,
162         enum rte_meter_color pkt_color);
163
164 /*
165  * Inline implementation of run-time methods
166  *
167  ***/
168
169 /* Internal data structure storing the srTCM run-time context per metered traffic flow. */
170 struct rte_meter_srtcm {
171         uint64_t time; /* Time of latest update of C and E token buckets */
172         uint64_t tc;   /* Number of bytes currently available in the committed (C) token bucket */
173         uint64_t te;   /* Number of bytes currently available in the excess (E) token bucket */
174         uint64_t cbs;  /* Upper limit for C token bucket */
175         uint64_t ebs;  /* Upper limit for E token bucket */
176         uint64_t cir_period; /* Number of CPU cycles for one update of C and E token buckets */
177         uint64_t cir_bytes_per_period; /* Number of bytes to add to C and E token buckets on each update */
178 };
179
180 /* Internal data structure storing the trTCM run-time context per metered traffic flow. */
181 struct rte_meter_trtcm {
182         uint64_t time_tc; /* Time of latest update of C token bucket */
183         uint64_t time_tp; /* Time of latest update of E token bucket */
184         uint64_t tc;      /* Number of bytes currently available in the committed (C) token bucket */
185         uint64_t tp;      /* Number of bytes currently available in the peak (P) token bucket */
186         uint64_t cbs;     /* Upper limit for C token bucket */
187         uint64_t pbs;     /* Upper limit for P token bucket */
188         uint64_t cir_period; /* Number of CPU cycles for one update of C token bucket */
189         uint64_t cir_bytes_per_period; /* Number of bytes to add to C token bucket on each update */
190         uint64_t pir_period; /* Number of CPU cycles for one update of P token bucket */
191         uint64_t pir_bytes_per_period; /* Number of bytes to add to P token bucket on each update */
192 };
193
194 static inline enum rte_meter_color
195 rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m,
196         uint64_t time,
197         uint32_t pkt_len)
198 {
199         uint64_t time_diff, n_periods, tc, te;
200
201         /* Bucket update */
202         time_diff = time - m->time;
203         n_periods = time_diff / m->cir_period;
204         m->time += n_periods * m->cir_period;
205
206         /* Put the tokens overflowing from tc into te bucket */
207         tc = m->tc + n_periods * m->cir_bytes_per_period;
208         te = m->te;
209         if (tc > m->cbs) {
210                 te += (tc - m->cbs);
211                 if (te > m->ebs)
212                         te = m->ebs;
213                 tc = m->cbs;
214         }
215
216         /* Color logic */
217         if (tc >= pkt_len) {
218                 m->tc = tc - pkt_len;
219                 m->te = te;
220                 return e_RTE_METER_GREEN;
221         }
222
223         if (te >= pkt_len) {
224                 m->tc = tc;
225                 m->te = te - pkt_len;
226                 return e_RTE_METER_YELLOW;
227         }
228
229         m->tc = tc;
230         m->te = te;
231         return e_RTE_METER_RED;
232 }
233
234 static inline enum rte_meter_color
235 rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m,
236         uint64_t time,
237         uint32_t pkt_len,
238         enum rte_meter_color pkt_color)
239 {
240         uint64_t time_diff, n_periods, tc, te;
241
242         /* Bucket update */
243         time_diff = time - m->time;
244         n_periods = time_diff / m->cir_period;
245         m->time += n_periods * m->cir_period;
246
247         /* Put the tokens overflowing from tc into te bucket */
248         tc = m->tc + n_periods * m->cir_bytes_per_period;
249         te = m->te;
250         if (tc > m->cbs) {
251                 te += (tc - m->cbs);
252                 if (te > m->ebs)
253                         te = m->ebs;
254                 tc = m->cbs;
255         }
256
257         /* Color logic */
258         if ((pkt_color == e_RTE_METER_GREEN) && (tc >= pkt_len)) {
259                 m->tc = tc - pkt_len;
260                 m->te = te;
261                 return e_RTE_METER_GREEN;
262         }
263
264         if ((pkt_color != e_RTE_METER_RED) && (te >= pkt_len)) {
265                 m->tc = tc;
266                 m->te = te - pkt_len;
267                 return e_RTE_METER_YELLOW;
268         }
269
270         m->tc = tc;
271         m->te = te;
272         return e_RTE_METER_RED;
273 }
274
275 static inline enum rte_meter_color
276 rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m,
277         uint64_t time,
278         uint32_t pkt_len)
279 {
280         uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp;
281
282         /* Bucket update */
283         time_diff_tc = time - m->time_tc;
284         time_diff_tp = time - m->time_tp;
285         n_periods_tc = time_diff_tc / m->cir_period;
286         n_periods_tp = time_diff_tp / m->pir_period;
287         m->time_tc += n_periods_tc * m->cir_period;
288         m->time_tp += n_periods_tp * m->pir_period;
289
290         tc = m->tc + n_periods_tc * m->cir_bytes_per_period;
291         if (tc > m->cbs)
292                 tc = m->cbs;
293
294         tp = m->tp + n_periods_tp * m->pir_bytes_per_period;
295         if (tp > m->pbs)
296                 tp = m->pbs;
297
298         /* Color logic */
299         if (tp < pkt_len) {
300                 m->tc = tc;
301                 m->tp = tp;
302                 return e_RTE_METER_RED;
303         }
304
305         if (tc < pkt_len) {
306                 m->tc = tc;
307                 m->tp = tp - pkt_len;
308                 return e_RTE_METER_YELLOW;
309         }
310
311         m->tc = tc - pkt_len;
312         m->tp = tp - pkt_len;
313         return e_RTE_METER_GREEN;
314 }
315
316 static inline enum rte_meter_color
317 rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m,
318         uint64_t time,
319         uint32_t pkt_len,
320         enum rte_meter_color pkt_color)
321 {
322         uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp;
323
324         /* Bucket update */
325         time_diff_tc = time - m->time_tc;
326         time_diff_tp = time - m->time_tp;
327         n_periods_tc = time_diff_tc / m->cir_period;
328         n_periods_tp = time_diff_tp / m->pir_period;
329         m->time_tc += n_periods_tc * m->cir_period;
330         m->time_tp += n_periods_tp * m->pir_period;
331
332         tc = m->tc + n_periods_tc * m->cir_bytes_per_period;
333         if (tc > m->cbs)
334                 tc = m->cbs;
335
336         tp = m->tp + n_periods_tp * m->pir_bytes_per_period;
337         if (tp > m->pbs)
338                 tp = m->pbs;
339
340         /* Color logic */
341         if ((pkt_color == e_RTE_METER_RED) || (tp < pkt_len)) {
342                 m->tc = tc;
343                 m->tp = tp;
344                 return e_RTE_METER_RED;
345         }
346
347         if ((pkt_color == e_RTE_METER_YELLOW) || (tc < pkt_len)) {
348                 m->tc = tc;
349                 m->tp = tp - pkt_len;
350                 return e_RTE_METER_YELLOW;
351         }
352
353         m->tc = tc - pkt_len;
354         m->tp = tp - pkt_len;
355         return e_RTE_METER_GREEN;
356 }
357
358 #ifdef __cplusplus
359 }
360 #endif
361
362 #endif /* __INCLUDE_RTE_METER_H__ */