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>
14 struct timeval
add_t(struct timeval x
, struct timeval y
)
16 struct timeval ret
= {
17 .tv_sec
= x
.tv_sec
+ y
.tv_sec
+ ((x
.tv_usec
+ y
.tv_usec
) / 1000000),
18 .tv_usec
= (x
.tv_usec
+ y
.tv_usec
) % 1000000
22 #define before(x,y) x.tv_sec < y.tv_sec || (x.tv_sec == y.tv_sec && x.tv_usec < y.tv_usec)
24 #define tbf_tcpriv(x) (struct tc_tbf*)(tcpriv(x))
26 /** Private per-interface structure
31 uint32_t qlen
; // Bytes.
32 uint32_t limit
; // Bytes.
33 uint32_t latency
; // ms
34 uint32_t rate
; // bits/s
35 uint32_t dropped
; //packets
39 struct timeval last_out
;
44 * Enqueue function. Try to add the packet 'vdb' to the output queue
45 * of the interface 'vif'
47 * return value: 1 = packet was enqueued, 0 = packet was rejected
49 int tbf_enqueue(struct vde_buff
*vdb
, struct vde_iface
*vif
)
51 struct tc_tbf
*tbf
= tbf_tcpriv(vif
);
52 if (tbf
->qlen
< tbf
->limit
){
54 ufifo_enqueue(vdb
,vif
);
55 if(vdb
->len
> tbf
->mtu
){
57 tbf
->delta
.tv_usec
= (1000000*tbf
->mtu
) / tbf
->rate
;
59 tbf
->limit
= (tbf
->rate
/tbf
->mtu
) * tbf
->latency
;
64 /* Queue Full: dropping. */
71 /* Dequeue function. Interface is ready to send the packet.
74 int tbf_dequeue(struct vde_iface
*vif
)
76 struct tc_tbf
*tbf
= tbf_tcpriv(vif
);
79 gettimeofday(&now
,NULL
);
80 when
= add_t (tbf
->last_out
, tbf
->delta
);
82 if (before(now
, when
))
85 tbf
->bytes_out
= vif
->q_out
->len
;
87 tbf
->qlen
-= tbf
->bytes_out
;
88 while (tbf
->bytes_out
>= tbf
->mtu
){
89 memcpy(&tbf
->last_out
,&now
,sizeof(struct timeval
));
90 tbf
->bytes_out
-= tbf
->mtu
;
98 /* Function to initialize the queue on the given interface.
100 int tbf_init(struct vde_iface
*vif
, char *args
)
102 struct tc_tbf
*tbf
=(struct tc_tbf
*)malloc(sizeof(struct tc_tbf
));
103 int arglen
= strlen(args
) - 1;
106 if ((arglen
< 5) || strncmp(args
,"rate",4))
108 args
=index(args
,' ');
109 if(args
) *(args
++)=(char)0;
111 if(!args
|| sscanf(args
, "%lu",&(tbf
->rate
)) < 1)
113 args
=index(args
,' ');
114 if(args
) *(args
++)=(char)0;
115 if(index(rate
,'K')) tbf
->rate
*=1000;
116 else if(index(rate
,'M')) tbf
->rate
*=1000000;
119 tbf
->rate
= (tbf
->rate
>> 3); // from bits/s --> to Bytes/s
121 if(strncmp(args
,"latency",7)==0){
122 args
=index(args
,' ');
123 if(args
) *(args
++)=(char)0;
124 if(!args
|| sscanf(args
, "%lu",&latency
) < 1)
126 } else if (strncmp(args
,"limit",5)==0){
127 args
=index(args
,' ');
128 if(args
) *(args
++)=(char)0;
129 if(!args
|| sscanf(args
, "%lu",&(tbf
->limit
)) < 1)
139 tbf
->limit
= (tbf
->rate
/tbf
->mtu
) * latency
;
143 tbf
->latency
= latency
;
144 gettimeofday(&tbf
->last_out
,NULL
);
148 tbf
->delta
.tv_sec
= 0;
149 tbf
->delta
.tv_usec
= (1000000*tbf
->mtu
) / tbf
->rate
;
150 vif
->policy_name
="tbf";
151 memcpy(vif
->tc_priv
, tbf
, sizeof(struct tc_tbf
));
159 char *tbf_tc_stats(struct vde_iface
*vif
)
161 struct tc_tbf
*tbf
= tbf_tcpriv(vif
);
162 char *statistics
=(char*)malloc(256);
163 snprintf(statistics
,255,"Shaping at Rate = %lu Bytes/s, bucket limit: %lu bytes. Overlimits: %lu packets. MTU=%lu", tbf
->rate
, tbf
->limit
, tbf
->dropped
, tbf
->mtu
);
170 * Module symbol to load into module list.
173 struct routing_policy module_routing_policy
=
176 .help
="Packet Fifo queue\nUsage: tc set <dev> tbf rate <speed>[K|M] ( limit <bytes> | latency <ms> )\n",
177 .policy_init
= tbf_init
,
178 .enqueue
= tbf_enqueue
,
179 .dequeue
= tbf_dequeue
,
180 .tc_stats
= tbf_tc_stats
184 __attribute__ ((constructor
))
187 fprintf(stderr
,"Loading library: tbf.so\n");
192 __attribute__ ((destructor
))