tagging vde-2 version 2.3.2
[vde.git] / 2.3.2 / src / vde_l3 / tbf.c
bloba76f953ebb62822f8a25cb29812c7fa3e49db63b
1 /*
2 * tc token bucket module
3 * Usage: tc set <dev> tbf rate <speed>[K|M] limit <packets>
4 * Alternate usage: tc set <dev> tbf rate <speed>[K|M] latency <ms>
8 * */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <sys/time.h>
14 #include <time.h>
15 #include "vde_buff.h"
17 #include <config.h>
18 #include <vde.h>
19 #include <vdecommon.h>
20 #include "vde_l3.h"
22 struct timeval add_t(struct timeval x, struct timeval y)
24 struct timeval ret = {
25 .tv_sec = x.tv_sec + y.tv_sec + ((x.tv_usec + y.tv_usec) / 1000000),
26 .tv_usec = (x.tv_usec + y.tv_usec) % 1000000
28 return ret;
30 #define before(x,y) x.tv_sec < y.tv_sec || (x.tv_sec == y.tv_sec && x.tv_usec < y.tv_usec)
32 #define tbf_tcpriv(x) (struct tc_tbf*)(tcpriv(x))
34 /** Private per-interface structure
37 struct tc_tbf
39 uint32_t qlen; // Bytes.
40 uint32_t limit; // Bytes.
41 uint32_t latency; // ms
42 uint32_t rate; // bits/s
43 uint32_t dropped; //packets
44 uint32_t mtu;
45 uint32_t bytes_out;
46 struct timeval delta;
47 struct timeval last_out;
52 * Enqueue function. Try to add the packet 'vdb' to the output queue
53 * of the interface 'vif'
55 * return value: 1 = packet was enqueued, 0 = packet was rejected
57 int tbf_enqueue(struct vde_buff *vdb, struct vde_iface *vif)
59 struct tc_tbf *tbf = tbf_tcpriv(vif);
60 if (tbf->qlen < tbf->limit){
61 tbf->qlen+=vdb->len;
62 ufifo_enqueue(vdb,vif);
63 if(vdb->len > tbf->mtu){
64 tbf->mtu = vdb->len;
65 tbf->delta.tv_usec = (1000000*tbf->mtu) / tbf->rate;
66 if (tbf->latency){
67 tbf->limit = (tbf->rate/tbf->mtu) * tbf->latency;
70 return 1;
71 }else{
72 /* Queue Full: dropping. */
73 free(vdb);
74 tbf->dropped++;
75 return 0;
79 /* Dequeue function. Interface is ready to send the packet.
82 int tbf_dequeue(struct vde_iface *vif)
84 struct tc_tbf *tbf = tbf_tcpriv(vif);
85 struct timeval now;
86 struct timeval when;
87 gettimeofday(&now,NULL);
88 when = add_t (tbf->last_out, tbf->delta);
90 if (before(now, when))
91 return 0;
93 tbf->bytes_out = vif->q_out->len;
94 ufifo_dequeue(vif);
95 tbf->qlen -= tbf->bytes_out;
96 while (tbf->bytes_out >= tbf->mtu){
97 memcpy(&tbf->last_out,&now,sizeof(struct timeval));
98 tbf->bytes_out -= tbf->mtu;
100 return 1;
106 /* Function to initialize the queue on the given interface.
108 int tbf_init(struct vde_iface *vif, char *args)
110 struct tc_tbf *tbf=(struct tc_tbf *)malloc(sizeof(struct tc_tbf));
111 int arglen = strlen(args) - 1;
112 uint32_t latency=0;
113 char *rate;
114 if ((arglen < 5) || strncmp(args,"rate",4))
115 goto fail;
116 args=index(args,' ');
117 if(args) *(args++)=(char)0;
118 rate=args;
119 if(!args || sscanf(args, "%u",&(tbf->rate)) < 1)
120 goto fail;
121 args=index(args,' ');
122 if(args) *(args++)=(char)0;
123 if(index(rate,'K')) tbf->rate *=1000;
124 else if(index(rate,'M')) tbf->rate *=1000000;
125 if(tbf->rate < 5000)
126 goto fail;
127 tbf->rate = (tbf->rate >> 3); // from bits/s --> to Bytes/s
129 if(strncmp(args,"latency",7)==0){
130 args=index(args,' ');
131 if(args) *(args++)=(char)0;
132 if(!args || sscanf(args, "%u",&latency) < 1)
133 goto fail;
134 } else if (strncmp(args,"limit",5)==0){
135 args=index(args,' ');
136 if(args) *(args++)=(char)0;
137 if(!args || sscanf(args, "%u",&(tbf->limit)) < 1)
138 goto fail;
142 } else goto fail;
144 tbf->mtu=1000;
146 if(latency){
147 tbf->limit = (tbf->rate/tbf->mtu) * latency;
151 tbf->latency = latency;
152 gettimeofday(&tbf->last_out,NULL);
153 tbf->qlen = 0;
154 tbf->dropped = 0;
155 tbf->bytes_out = 0;
156 tbf->delta.tv_sec = 0;
157 tbf->delta.tv_usec = (1000000*tbf->mtu) / tbf->rate;
158 vif->policy_name="tbf";
159 memcpy(vif->tc_priv, tbf, sizeof(struct tc_tbf));
160 return 1;
162 fail:
163 return 0;
167 char *tbf_tc_stats(struct vde_iface *vif)
169 struct tc_tbf *tbf = tbf_tcpriv(vif);
170 char *statistics=(char*)malloc(256);
171 snprintf(statistics,255,"Shaping at Rate = %u Bytes/s, bucket limit: %u bytes. Overlimits: %u packets. MTU=%u", tbf->rate, tbf->limit, tbf->dropped, tbf->mtu);
172 return statistics;
178 * Module symbol to load into module list.
181 struct routing_policy module_routing_policy=
183 .name="tbf",
184 .help="Packet Fifo queue\nUsage: tc set <dev> tbf rate <speed>[K|M] ( limit <bytes> | latency <ms> )\n",
185 .policy_init = tbf_init,
186 .enqueue = tbf_enqueue,
187 .dequeue = tbf_dequeue,
188 .tc_stats = tbf_tc_stats
191 static void
192 __attribute__ ((constructor))
193 init (void)
195 fprintf(stderr,"Loading library: tbf.so\n");
199 static void
200 __attribute__ ((destructor))
201 fini (void)