DPDK  17.05.2
rte_meter.h
Go to the documentation of this file.
1 /*-
2  * BSD LICENSE
3  *
4  * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  * * Neither the name of Intel Corporation nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifndef __INCLUDE_RTE_METER_H__
35 #define __INCLUDE_RTE_METER_H__
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
51 #include <stdint.h>
52 
53 /*
54  * Application Programmer's Interface (API)
55  *
56  ***/
57 
64 };
65 
70  uint64_t cir;
71  uint64_t cbs;
72  uint64_t ebs;
73 };
74 
79  uint64_t cir;
80  uint64_t pir;
81  uint64_t cbs;
82  uint64_t pbs;
83 };
84 
86 struct rte_meter_srtcm;
87 
89 struct rte_meter_trtcm;
90 
101 int
102 rte_meter_srtcm_config(struct rte_meter_srtcm *m,
103  struct rte_meter_srtcm_params *params);
104 
115 int
116 rte_meter_trtcm_config(struct rte_meter_trtcm *m,
117  struct rte_meter_trtcm_params *params);
118 
131 static inline enum rte_meter_color
132 rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m,
133  uint64_t time,
134  uint32_t pkt_len);
135 
150 static inline enum rte_meter_color
151 rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m,
152  uint64_t time,
153  uint32_t pkt_len,
154  enum rte_meter_color pkt_color);
155 
168 static inline enum rte_meter_color
169 rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m,
170  uint64_t time,
171  uint32_t pkt_len);
172 
187 static inline enum rte_meter_color
188 rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m,
189  uint64_t time,
190  uint32_t pkt_len,
191  enum rte_meter_color pkt_color);
192 
193 /*
194  * Inline implementation of run-time methods
195  *
196  ***/
197 
198 /* Internal data structure storing the srTCM run-time context per metered traffic flow. */
199 struct rte_meter_srtcm {
200  uint64_t time; /* Time of latest update of C and E token buckets */
201  uint64_t tc; /* Number of bytes currently available in the committed (C) token bucket */
202  uint64_t te; /* Number of bytes currently available in the excess (E) token bucket */
203  uint64_t cbs; /* Upper limit for C token bucket */
204  uint64_t ebs; /* Upper limit for E token bucket */
205  uint64_t cir_period; /* Number of CPU cycles for one update of C and E token buckets */
206  uint64_t cir_bytes_per_period; /* Number of bytes to add to C and E token buckets on each update */
207 };
208 
209 /* Internal data structure storing the trTCM run-time context per metered traffic flow. */
210 struct rte_meter_trtcm {
211  uint64_t time_tc; /* Time of latest update of C token bucket */
212  uint64_t time_tp; /* Time of latest update of E token bucket */
213  uint64_t tc; /* Number of bytes currently available in the committed (C) token bucket */
214  uint64_t tp; /* Number of bytes currently available in the peak (P) token bucket */
215  uint64_t cbs; /* Upper limit for C token bucket */
216  uint64_t pbs; /* Upper limit for P token bucket */
217  uint64_t cir_period; /* Number of CPU cycles for one update of C token bucket */
218  uint64_t cir_bytes_per_period; /* Number of bytes to add to C token bucket on each update */
219  uint64_t pir_period; /* Number of CPU cycles for one update of P token bucket */
220  uint64_t pir_bytes_per_period; /* Number of bytes to add to P token bucket on each update */
221 };
222 
223 static inline enum rte_meter_color
224 rte_meter_srtcm_color_blind_check(struct rte_meter_srtcm *m,
225  uint64_t time,
226  uint32_t pkt_len)
227 {
228  uint64_t time_diff, n_periods, tc, te;
229 
230  /* Bucket update */
231  time_diff = time - m->time;
232  n_periods = time_diff / m->cir_period;
233  m->time += n_periods * m->cir_period;
234 
235  /* Put the tokens overflowing from tc into te bucket */
236  tc = m->tc + n_periods * m->cir_bytes_per_period;
237  te = m->te;
238  if (tc > m->cbs) {
239  te += (tc - m->cbs);
240  if (te > m->ebs)
241  te = m->ebs;
242  tc = m->cbs;
243  }
244 
245  /* Color logic */
246  if (tc >= pkt_len) {
247  m->tc = tc - pkt_len;
248  m->te = te;
249  return e_RTE_METER_GREEN;
250  }
251 
252  if (te >= pkt_len) {
253  m->tc = tc;
254  m->te = te - pkt_len;
255  return e_RTE_METER_YELLOW;
256  }
257 
258  m->tc = tc;
259  m->te = te;
260  return e_RTE_METER_RED;
261 }
262 
263 static inline enum rte_meter_color
264 rte_meter_srtcm_color_aware_check(struct rte_meter_srtcm *m,
265  uint64_t time,
266  uint32_t pkt_len,
267  enum rte_meter_color pkt_color)
268 {
269  uint64_t time_diff, n_periods, tc, te;
270 
271  /* Bucket update */
272  time_diff = time - m->time;
273  n_periods = time_diff / m->cir_period;
274  m->time += n_periods * m->cir_period;
275 
276  /* Put the tokens overflowing from tc into te bucket */
277  tc = m->tc + n_periods * m->cir_bytes_per_period;
278  te = m->te;
279  if (tc > m->cbs) {
280  te += (tc - m->cbs);
281  if (te > m->ebs)
282  te = m->ebs;
283  tc = m->cbs;
284  }
285 
286  /* Color logic */
287  if ((pkt_color == e_RTE_METER_GREEN) && (tc >= pkt_len)) {
288  m->tc = tc - pkt_len;
289  m->te = te;
290  return e_RTE_METER_GREEN;
291  }
292 
293  if ((pkt_color != e_RTE_METER_RED) && (te >= pkt_len)) {
294  m->tc = tc;
295  m->te = te - pkt_len;
296  return e_RTE_METER_YELLOW;
297  }
298 
299  m->tc = tc;
300  m->te = te;
301  return e_RTE_METER_RED;
302 }
303 
304 static inline enum rte_meter_color
305 rte_meter_trtcm_color_blind_check(struct rte_meter_trtcm *m,
306  uint64_t time,
307  uint32_t pkt_len)
308 {
309  uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp;
310 
311  /* Bucket update */
312  time_diff_tc = time - m->time_tc;
313  time_diff_tp = time - m->time_tp;
314  n_periods_tc = time_diff_tc / m->cir_period;
315  n_periods_tp = time_diff_tp / m->pir_period;
316  m->time_tc += n_periods_tc * m->cir_period;
317  m->time_tp += n_periods_tp * m->pir_period;
318 
319  tc = m->tc + n_periods_tc * m->cir_bytes_per_period;
320  if (tc > m->cbs)
321  tc = m->cbs;
322 
323  tp = m->tp + n_periods_tp * m->pir_bytes_per_period;
324  if (tp > m->pbs)
325  tp = m->pbs;
326 
327  /* Color logic */
328  if (tp < pkt_len) {
329  m->tc = tc;
330  m->tp = tp;
331  return e_RTE_METER_RED;
332  }
333 
334  if (tc < pkt_len) {
335  m->tc = tc;
336  m->tp = tp - pkt_len;
337  return e_RTE_METER_YELLOW;
338  }
339 
340  m->tc = tc - pkt_len;
341  m->tp = tp - pkt_len;
342  return e_RTE_METER_GREEN;
343 }
344 
345 static inline enum rte_meter_color
346 rte_meter_trtcm_color_aware_check(struct rte_meter_trtcm *m,
347  uint64_t time,
348  uint32_t pkt_len,
349  enum rte_meter_color pkt_color)
350 {
351  uint64_t time_diff_tc, time_diff_tp, n_periods_tc, n_periods_tp, tc, tp;
352 
353  /* Bucket update */
354  time_diff_tc = time - m->time_tc;
355  time_diff_tp = time - m->time_tp;
356  n_periods_tc = time_diff_tc / m->cir_period;
357  n_periods_tp = time_diff_tp / m->pir_period;
358  m->time_tc += n_periods_tc * m->cir_period;
359  m->time_tp += n_periods_tp * m->pir_period;
360 
361  tc = m->tc + n_periods_tc * m->cir_bytes_per_period;
362  if (tc > m->cbs)
363  tc = m->cbs;
364 
365  tp = m->tp + n_periods_tp * m->pir_bytes_per_period;
366  if (tp > m->pbs)
367  tp = m->pbs;
368 
369  /* Color logic */
370  if ((pkt_color == e_RTE_METER_RED) || (tp < pkt_len)) {
371  m->tc = tc;
372  m->tp = tp;
373  return e_RTE_METER_RED;
374  }
375 
376  if ((pkt_color == e_RTE_METER_YELLOW) || (tc < pkt_len)) {
377  m->tc = tc;
378  m->tp = tp - pkt_len;
379  return e_RTE_METER_YELLOW;
380  }
381 
382  m->tc = tc - pkt_len;
383  m->tp = tp - pkt_len;
384  return e_RTE_METER_GREEN;
385 }
386 
387 #ifdef __cplusplus
388 }
389 #endif
390 
391 #endif /* __INCLUDE_RTE_METER_H__ */