summaryrefslogtreecommitdiff
path: root/src/tsg_leaky_bucket.cpp
blob: 41b6a9348709267e1ce3a7274c09aa73b9a1b0cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include<stdio.h>
#include<sys/time.h>
#include<stdlib.h>
#include <time.h>

#include <MESA/stream.h>

enum BUCKET_UNIT
{
	BUCKET_UNIT_S=0,
	BUCKET_UNIT_MS,
	BUCKET_UNIT_US,
	BUCKET_UNIT_MAX,
};

struct leaky_bucket
{
    double rate;
    int used_size;
    int bucket_size;
	enum BUCKET_UNIT unit;
	struct timespec refresh_time;
};

#define	BUCKET_UNIT_S_LIMIT_MAX_BIT		32*8*1024
#define	BUCKET_UNIT_MS_LIMIT_MAX_BIT	64*8*1024

void refresh_bucket(struct leaky_bucket * bucket, int thread_seq)
{
	long interval_us=0;
	struct timespec end;
	clock_gettime(CLOCK_MONOTONIC, &end);

	switch(bucket->unit)
	{
		case	BUCKET_UNIT_S:			
			interval_us=(end.tv_sec-bucket->refresh_time.tv_sec)+(end.tv_nsec-bucket->refresh_time.tv_nsec)/1000000000;
			break;
		case	BUCKET_UNIT_MS:			
			interval_us=(end.tv_sec-bucket->refresh_time.tv_sec)*1000 + (end.tv_nsec-bucket->refresh_time.tv_nsec)/1000000;
			break;
		case	BUCKET_UNIT_US:			
			interval_us=(end.tv_sec-bucket->refresh_time.tv_sec)*1000000 + (end.tv_nsec-bucket->refresh_time.tv_nsec)/1000;
			break;
		default:
			bucket->used_size=bucket->bucket_size;
			return ;
	}
	

    bucket->used_size=bucket->used_size-interval_us*(bucket->rate);
    bucket->used_size=(bucket->used_size<0) ? 0 : bucket->used_size;

	if(interval_us>=1)
	{				
		bucket->refresh_time=end;
	}
	
	return ;
}

int is_permit_pass(int pkt_size, struct leaky_bucket * bucket, int thread_seq)
{
    refresh_bucket(bucket, thread_seq);
    if ((bucket->used_size+pkt_size) < bucket->bucket_size)
    {
        bucket->used_size += pkt_size;
        return 1;
    }
   
	return 0;
}

struct leaky_bucket * create_bucket(int bucket_size, int thread_seq)
{
	if(bucket_size<0)
	{
		return NULL;
	}
	
    struct leaky_bucket * bucket = (struct leaky_bucket *)dictator_malloc(thread_seq, sizeof(struct leaky_bucket));

	if(bucket_size<BUCKET_UNIT_S_LIMIT_MAX_BIT)
	{
	    bucket->rate=(double)bucket_size;		
		bucket->unit=BUCKET_UNIT_S;
	}
	else if(bucket_size<BUCKET_UNIT_MS_LIMIT_MAX_BIT)
	{
		bucket->rate=(double)bucket_size/(double)1000;		
		bucket->unit=BUCKET_UNIT_MS;
	}
	else
	{
		bucket->rate=(double)bucket_size/(double)1000000;		
		bucket->unit=BUCKET_UNIT_US;
	}
	
    bucket->used_size = 0;
    bucket->bucket_size = bucket_size;

	clock_gettime(CLOCK_MONOTONIC, &(bucket->refresh_time));

    return bucket;
}

void destroy_bucket(struct leaky_bucket **bucket, int thread_seq)
{
	if(*bucket!=NULL)
	{
    	dictator_free(thread_seq, *bucket);
    	bucket = NULL;
	}

	return ;
}