在/etc/ftpaccess里面加上:
throughput /home/ftp * * 64000 0.5 *
意思是下载带宽对所有IP(最后那个*)限制在64K,每下一个文件速度减半(那个0
.5).
我用的是2.5.x,man page里面很全的.
用man ftpaccess就可以.:-)
◇ ProFTPD 流量控制
----------------------------------------------------------------------
----------发信人: charley.bbs@swallow.twbbs.org (喘气中...), 看板: Lin
ux
标 题: ProFTPD 流量控制
发信站: 临风小□ BBS 站 (Tue Mar 9 15:55:30 1999) @cyndi.cis.nctu.edu
.tw
转信站: Maxwell!bbs.ee.ntu!freebsd.ntu!news.cs.nthu!news.cis.nctu!Wind
这是自己改的 Proftpd 1.2.0pre2 流量控制的 patch.
需要原来 proftpd source!
相关程式可以在 ftp://swallow.twbbs.org/Linux/FTP/ 下找到
用法:
1. 如果你的 proftpd-1.2.0pre2.tar.gz 解在 proftpd-1.2.0pre2/
将本 patch 放跟 proftpd-1.2.0pre2/ 同一层目录, 打
patch < proftpd-1.2.0pre2-bandwidth.patch
如果放在 proftpd-1.2.0pre2/ 下
patch -p1 < proftpd-1.2.0pre2-bandwidth.patch
2. 重新 Make 你的 source!
系统设定:
1. 提供三个控制流量功能(只有下传)
可以设在 server config,,
BandWidth : 总频宽
MaxBandWidth : 每线最大频宽
MinBandWidth : 每线最小频宽
必需为整数,代表 位元组/秒(Bytes/second)
三个功能的关系: MinBandWidth > MaxBandWidth > BandWidth
2. □例1.
设定 BandWidth 4096
如果有4人在线上,每个人的流量为 4096B4 位元组/秒
□例2.
设定 BandWidth 4096
MaxBandWidth 3072
如果有1人在线上,每个人的流量为 3072 位元组/秒
如果有2人在线上,每个人的流量为 4096%2 48 位元组/秒
以下类推
□例3.
设定 BandWidth 3072
MinBandWidth 1024
如果有1人在线上,每个人的流量为 3072 位元组/秒
如果有2人在线上,每个人的流量为 3072#6 位元组/秒
如果有3人在线上,每个人的流量为 307224 位元组/秒
如果有4人在线上,每个人的流量为 1024 位元组/秒
以下类推
详细的说明请看 patch 过的 mod_xfer.c
--- start proftpd-1.2.0pre2-bandwidth.patch ---
--- proftpd-1.2.0pre2.orig/modules/mod_xfer.c Fri Feb 19 15:11:11 19
99
proftpd-1.2.0pre2/modules/mod_xfer.c Mon Feb 22 14:38:19 19
99
@@ -31,10 31,140 @@
*
*/
/********************************************************************
********
* Title : Bandwidth management
* File : mod_xfer.c (need orig source from proftpd-1.2.0pre2.
tar.gz)
* Author : Albert Chiu (albert@swallow.twbbs.org.tw)
* Date : 22 Feb 1999
* Version : 0.9p2
*
* Description :
* Provide bandwidth usage limitation on per connection.
*
* Revision :
* Ver 0.9p2
* - Add Bandwidth and MinBandWidth.
* Ver 0.9p1
* - Fix unpredictable disconnect bugs.
* - Port patch to proftpd-1.2.0pre2
* Ver 0.9
* - First patch version base on proftpd-1.2.0pre1.
* - Only include MaxBandWidth.
*
********************************************************************
*******
* Copyright (c)1999 Albert Chiu ( Chiu Yang-Li ). All rights reserve
d.
* Modify for the ProFTPD Group by :
*
* Albert Chiu
* albert@swallow.twbbs.org.tw
* http://swallow.twbbs.org.tw/~albert
*
* I get some idea and good function from Apache Module Collection. I
'd looked
* at mod_bandwidth, this one is almost what i want, so i use the ide
a and
* rewrite it for ProFTPD 1.2.0pre1.
* But i find the select() function which mod_bandwidth use is usuall
y bad
* performance, so i use setitimer() to replace it.
*
* you can get the collection from Apache Homepage (http://www.apache
.org/).
* mod_bandwidth 1.0 is written by Yann Stettler (stettler@cohprog.co
m).
*
********************************************************************
*******/
/*
* Instruction :
* -------------
*
* Note : this modify was writen for ProFTPD 1.2.0pre2 and tested on
it
*
* Installation :
*
* Just make all source again is enough. :>
*
*
* Server configuration directive :
* -----------------------------------
* - BandWidth
* Syntax : BandWidth
* Default : none
* Context : server config,,
*
* Limit the total bandwidth for file-transfer (retr only)
* Final each rate is depend of the number of connections.
*
* The is in Bytes/second.
* A of "0" means no bandwidth limit.
*
* Example :
* BandWidth 4096
*
* If there are 4 users online , this will limit the bandwith
* for file-transfer to 4096/4 □24Bytes/sec.
*
* Note : If transfer file size is lower than the "BandWidth"/"Users"
rate,
* it will ignore the limit.
*
* - MaxBandWidth
* Syntax : MaxBandWidth
* Default : none
* Context : server config,,
*
* Limit the bandwidth for file-transfer (retr only)
* This over-ride BandWidth rules as well as the calculated rate
* based on the number of connections.
*
* The is in Bytes/second.
* A of "0" means no bandwidth limit.
*
* Example :
* If BandWidth is set to "4096" (4KBytes/sec) and MaxBandWidth
* is set to "3072" (2KBytes/sec) that means :
* - if there is one connection, the file will be transfered
* at 3072 Bytes/sec. (Maximal of 3072 Bytes/sec).
* - if there is two connections, each files will be transfered
* at 2048 Bytes/sec.
* - if there is three or more connections, each files will be
* transfered at "4096/connections" Bytes/sec.
*
* Note : If transfer file size is lower than the "MaxBandWidth" rate
,
* it will ignore the limit.
*
* - MinBandWidth
* Syntax : MinBandWidth
* Default : none
* Context : server config,,
*
* Set a minimal bandwidth to use for file-transfer. (retr only)
* This over-ride both BandWidth and MaxBandWidth rules as well
* as the calculated rate based on the number of connections.
*
* The is in Bytes/second.
* A of "0" means no bandwidth limit.
*
* Example :
* If BandWidth is set to "3072" (2KBytes/sec) and MinBandWidth
* is set to "1024" (1KBytes/sec) that means :
* - if there is one connection, the file will be transfered
* at 3072 Bytes/sec.
* - if there is two connections, each files will be transfered
* at 1536 Bytes/sec.
* - if there is three or more connections, each files will be
* transfered at 1024 Bytes/sec. (Minimal of 1024 Bytes/sec).
*
* Note : If transfer file size is lower than the "MinBandWidth" rate
,
* it will ignore the limit.
*
*/
#include "conf.h"
#ifdef HAVE_REGEX_H
#include
#endif
#include
#undef timerisset
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_us
ec)
#undef timerclear
#define timerclear(tvp) ((tvp)->tv_sec tvp)->tv_usec □
extern module auth_module;
extern pid_t mpid;
@@ -51,6 181,7 @@
static int stor_fd;
static int retr_fd;
module xfer_module;
static void _log_transfer(char direction)
@@ -129,6 260,48 @@
retr_file ULL;
}
static struct timeval timediff(struct timeval *a, struct timeval *b)
{
struct timeval rslt, tmp;
tmp a;
if ((rslt.tv_usec mp.tv_usec - b->tv_usec) < 0) {
rslt.tv_usec □00000;
--(tmp.tv_sec);
}
if ((rslt.tv_sec mp.tv_sec - b->tv_sec) < 0) {
rslt.tv_usec □
rslt.tv_sec □
}
return (rslt);
}
void handler(int sig)
{
return;
}
int sleep_msec(struct timeval *a)
{
struct timeval tmp;
struct itimerval itimer;
void handler();
tmp a;
if (timerisset(&tmp)) {
signal(SIGALRM,handler);
timerclear(&itimer.it_interval);
itimer.it_value.tv_usecp.tv_usec;
itimer.it_value.tv_secp.tv_sec;
setitimer(ITIMER_REAL,&itimer,(struct itimerval *)0);
pause();
timerclear(&itimer.it_value);
setitimer(ITIMER_REAL,&itimer,(struct itimerval *)0);
}
}
/* cmd_pre_stor is a PRE_CMD handler which checks security, etc, and
* places the full filename to receive in cmd->private [note that we
CANNOT
* use cmd->tmp_pool for this, as tmp_pool only lasts for the duratio
n
@@ -384,9 557,11 @@
struct stat sbuf;
char *lbuf;
int bufsize,len;
long cur_rate □max_rate □min_rate □cur_user □
unsigned long respos □cnt □cnt_steps □cnt_next □
privdata_t *p;
-
struct timeval opt_time, last_time, now, timespent, timeout;
p od_privdata_find(cmd,"retr_filename",NULL);
if(!p) {
@@ -433,10 608,53 @@
cnt espos;
log_add_run(mpid,NULL,session.user,NULL,0,session.xfer.file_size,
0,NULL);
/* Calculate bandwidth transfer time
*
* if "BandWidth" , "MaxBandWidth" or "MinBandWidth" not be defin
ed or
* be defined error. i will turn off bandwidth limit.
*/
cur_user long)get_param_int(cmd->server->conf,"CURRENT-CLIENTS",F
ALSE) 1;
cur_rate long)get_param_int(cmd->server->conf,"Bandwidth",FALSE);
max_rate long)get_param_int(cmd->server->conf,"MaxBandwidth",FALS
E);
min_rate long)get_param_int(cmd->server->conf,"MinBandwidth",FALS
E);
cur_rate □r_rate / cur_user;
if(max_rate <□)
max_rate □;
if(min_rate <□)
min_rate □;
if(cur_rate <□)
{
if(max_rate > 0L)
cur_rate ax_rate;
else if(min_rate > 0L)
cur_rate in_rate;
else
cur_rate □;
}
if((cur_rate > max_rate) && (max_rate > 0L))
cur_rate ax_rate;
if(min_rate > cur_rate)
cur_rate in_rate;
if(cur_rate > 0L) {
opt_time.tv_sec long int) bufsize / cur_rate;
opt_time.tv_usec long int) ((float) bufsize * 1000000 / cur_rat
e - opt_time.tv_sec * 1000000);
log_debug(DEBUG1, "Current Bandwidth : %ld bytes/sec",cur_rate)
;
}
while((len s_read(retr_file,retr_fd,lbuf,bufsize)) > 0) {
if(XFER_ABORTED)
break;
/* record transfer start time */
if(cur_rate > 0L) {
gettimeofday(&last_time, (struct timezone *) 0);
}
len □ta_xfer(lbuf,len);
if(len < 0) {
_retr_abort();
@@ -450,6 668,21 @@
log_add_run(mpid,NULL,session.user,NULL,0,session.xfer.file_
size,cnt,NULL);
}
}
/* calculate spent time and set up timer */
if((cur_rate > 0L) && (session.xfer.file_size > cur_rate)) {
gettimeofday(&now, (struct timezone *) 0);
timespent imediff(&now, &last_time);
timeout imediff(&opt_time, ×pent);
log_debug(DEBUG5, "bandwidth : Sleep : %ld/%ld (Op time : %ld
/%ld Spent : %ld/%ld)",
timeout.tv_sec, timeout.tv_usec, opt_time.tv_sec,
opt_time.tv_usec,
timespent.tv_sec, timespent.tv_usec);
/* We sleep... */
sleep_msec(&timeout);
if(TimeoutIdle)
reset_timer(TIMER_IDLE,ANY_MODULE);
}
}
if(XFER_ABORTED) {
@@ -519,6 752,57 @@
return DECLINED(cmd);
}
MODRET set_bandwidth(cmd_rec *cmd)
{
long s_cur_rate
CHECK_ARGS(cmd,1);
CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
s_cur_rate □oi(cmd->argv[1]);
if(s_cur_rate < 0)
CONF_ERROR(cmd,"value must be lager then 0");
add_config_param_set(&cmd->server->conf,"Bandwidth",1,(void*)s_cur_
rate);
return HANDLED(cmd);
}
MODRET set_maximumbandwidth(cmd_rec *cmd)
{
long s_cur_rate
CHECK_ARGS(cmd,1);
CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
s_cur_rate □oi(cmd->argv[1]);
if(s_cur_rate < 0)
CONF_ERROR(cmd,"value must be lager then 0");
add_config_param_set(&cmd->server->conf,"MaxBandwidth",1,(void*)s_c
ur_rate);
return HANDLED(cmd);
}
MODRET set_minimumbandwidth(cmd_rec *cmd)
{
long s_cur_rate
CHECK_ARGS(cmd,1);
CHECK_CONF(cmd,CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
s_cur_rate □oi(cmd->argv[1]);
if(s_cur_rate < 0)
CONF_ERROR(cmd,"value must be lager then 0");
add_config_param_set(&cmd->server->conf,"MinBandwidth",1,(void*)s_c
ur_rate);
return HANDLED(cmd);
}
static int _noxfer_timeout(CALLBACK_FRAME)
{
if(session.flags & SF_XFER)
@@ -542,6 826,13 @@
return 0;
}
static conftable xfer_config[]
{ "BandWidth", set_bandwidth, NULL }
,
{ "MaxBandWidth", set_maximumbandwidth, NULL }
,
{ "MinBandWidth", set_minimumbandwidth, NULL }
,
{ NULL, NULL, NULL }
};
cmdtable xfer_commands[]
{ CMD, C_TYPE, G_NONE, cmd_type, TRUE, FALSE, CL_MISC
},
{ PRE_CMD, C_RETR, G_READ, pre_cmd_retr, TRUE, FALSE },
@@ -562,7 853,7 @@
NULL,NULL, /* Always NULL */
0x20, /* API Version */
"xfer", /* Module name */
- NULL, /* No config */
xfer_config, /* Config name */
xfer_commands,
NULL,
NULL,xfer_init_child
--- end proftpd-1.2.0pre2-bandwidth.patch ---
www.itfly.org