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>
19 #include <vdecommon.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
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
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
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
){
62 ufifo_enqueue(vdb
,vif
);
63 if(vdb
->len
> tbf
->mtu
){
65 tbf
->delta
.tv_usec
= (1000000*tbf
->mtu
) / tbf
->rate
;
67 tbf
->limit
= (tbf
->rate
/tbf
->mtu
) * tbf
->latency
;
72 /* Queue Full: dropping. */
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
);
87 gettimeofday(&now
,NULL
);
88 when
= add_t (tbf
->last_out
, tbf
->delta
);
90 if (before(now
, when
))
93 tbf
->bytes_out
= vif
->q_out
->len
;
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
;
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;
114 if ((arglen
< 5) || strncmp(args
,"rate",4))
116 args
=index(args
,' ');
117 if(args
) *(args
++)=(char)0;
119 if(!args
|| sscanf(args
, "%u",&(tbf
->rate
)) < 1)
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;
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)
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)
147 tbf
->limit
= (tbf
->rate
/tbf
->mtu
) * latency
;
151 tbf
->latency
= latency
;
152 gettimeofday(&tbf
->last_out
,NULL
);
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
));
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
);
178 * Module symbol to load into module list.
181 struct routing_policy module_routing_policy
=
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
192 __attribute__ ((constructor
))
195 fprintf(stderr
,"Loading library: tbf.so\n");
200 __attribute__ ((destructor
))