Controlando UPLOAD com o CBQ
Amigos, não é um assunto novo, mas como eu tive muita dificuldade em fazer funcionar o UPLOAD usando o CBQ, resolvi então escrever este pequeno artigo, pois pode ser dúvida também de alguém na comunidade.
Criando os arquivos
Primeiramente, vamos criar o script que será utilizado na inicialização do CBQ.
# vi /sbin/script_cbq.sh
# vi /sbin/script_cbq.sh
#!/bin/sh
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
CBQ_PATH="/etc/cbq"
### Uncomment for debugging
#LOG_FILE="/var/run/cbq-$1"
if [ -n "$LOG_FILE" ]; then
### Initialize log file
echo "# `date`" > $LOG_FILE
### Logging equivalent of "ip" command
ip () {
[ -z "$LOG_FILE" ] && { /sbin/ip "$@"; return; }
echo -e " ip $@ " >> $LOG_FILE
/sbin/ip "$@" 2>&1 | tee -a $LOG_FILE
} # ip
### Logging equivalent of "tc" command
tc () {
[ -z "$LOG_FILE" ] && { /sbin/tc "$@"; return; }
echo -e " tc $@ " >> $LOG_FILE
/sbin/tc "$@" 2>&1 | tee -a $LOG_FILE
} # tc
fi # command logging
### Remove CBQ from all devices
cbq_off () {
# for dev in `ip link| sed -n '/^[0-9]/ { s/^[0-9]+:
#([a-z0-9]+)[:@].*/1/; p; }'`; do
# cbq_device_off $dev
for dev in `ifconfig |grep eth1 |awk {'print$1'}`; do
cbq_device_off $dev
done
return
} # cbq_off
### Remove root class from device $1
cbq_device_off () {
tc qdisc del dev $1 root &>/dev/null
return
} # cbq_device_off
### Display CBQ setup
cbq_show () {
for dev in $DEVICES; do
echo ---[ $dev: configured classes ]---------------------------
echo; tc $1 class show dev $dev; echo
echo ---[ $dev: queueing disciplines ]-------------------------
echo; tc $1 qdisc show dev $dev; echo
done
} # cbq_show
### Check configuration and load DEVFIELDS/CLASSLIST
cbq_init () {
### Check configuration in $CBQ_PATH directory and get CLASSLIST
CLASSLIST=`find $CBQ_PATH -name 'cbq-*' -maxdepth 1 -printf "%f "| sort`
if [ -z "$CLASSLIST" ]; then
echo "**CBQ: not configured in $CBQ_PATH!"
exit
fi
### Collect all DEVICE fields from $CBQ_PATH/cbq-*
DEVFIELDS=`find $CBQ_PATH -name 'cbq-*' -maxdepth 1 -exec sed -ne
's/#.*//; s/ //g; /^DEVICE=.*,.*,.*/ { s/.*=//; p; q; };
/^DEVICE=/ q' {} ;| sort -u`
### Check if there are any devices to set up
if [ -z "$DEVFIELDS" ]; then
echo "**CBQ: can't find any DEVICE field in $CBQ_PATH/cbq-*!"
exit
fi
### Extract all device names from DEVICE fields in $CBQ_PATH/cbq-*
DEVICES=`echo "$DEVFIELDS"| sed 's/,.*//'| sort -u`
### Check for multiple devices with different DEVICE fields
if [ `echo "$DEVICES"| wc -l` -ne `echo "$DEVFIELDS"| wc -l` ]; then
echo "**CBQ: multiple different DEVICE fields for one device found!"
echo "$DEVFIELDS"
exit
fi
} # cbq_init
### Load class configuration from file $1
cbq_load_class () {
CNAME="$CBQ_PATH/$1"
CFILE=`sed -e 's/#.*//; s/ //g; /^$/ d' $CNAME`
CLASS=`echo $1| sed 's/^cbq-0*//; s/..*//'`
if [ `/usr/bin/printf "%d" 0x$CLASS` -le 1 ]; then
echo "**CBQ: class ID of $1 must be > 1!"
cbq_off
exit
fi
### Device parameters
DEVICE=`echo "$CFILE"| sed -n '/^DEVICE=/ { s/.*=//; s/,.*//; p; q; }'`
BANDWIDTH=`echo "$DEVFIELDS"| sed -n "/^$DEVICE,/ { s/.*,(.*),.*/1/; p; q; }"`
### Class parameters
CLASSID="1:$CLASS"
PARENT=`echo "$CFILE"| sed -n '/^PARENT=/ { s/.*=0*//; p; q; }'`
[ -z "$PARENT" ] && PARENT="1:1" || PARENT="1:$PARENT"
LEAF=`echo "$CFILE"| sed -n '/^LEAF=/ { s/.*=//; p; q; }'`
[ -z "$LEAF" ] && LEAF="tbf"
BOUNDED=`echo "$CFILE"| sed -n '/^BOUNDED=/ { s/.*=//; p; q; }'`
[ "$BOUNDED" = "no" ] && BOUNDED="" || BOUNDED="bounded"
ISOLATED=`echo "$CFILE"| sed -n '/^ISOLATED=/ { s/.*=//; p; q; }'`
[ "$ISOLATED" = "yes" ] && ISOLATED="isolated" || ISOLATED=""
PRIO=`echo "$CFILE"| sed -n '/^PRIO=/ { s/.*=//; p; q; }'`
RATE=`echo "$CFILE"| sed -n '/^RATE=/ { s/.*=//; p; q; }'`
WEIGHT=`echo "$CFILE"| sed -n '/^WEIGHT=/ { s/.*=//; p; q; }'`
if [ -z "$RATE" -o -z "$WEIGHT" -o -z "$PRIO" ]; then
echo "**CBQ: missing RATE, WEIGHT or PRIO field(s) in $1!"
cbq_off
exit
fi
### Leaf qdisc parameters for TBF
if [ "$LEAF" = "tbf" ]; then
BUFFER=`echo "$CFILE"| sed -n '/^BUFFER=/ { s/.*=//; p; q; }'`
[ -z "$BUFFER" ] && BUFFER="10Kb/8"
LIMIT=`echo "$CFILE"| sed -n '/^LIMIT=/ { s/.*=//; p; q; }'`
[ -z "$LIMIT" ] && LIMIT="15Kb"
PEAK=`echo "$CFILE"| sed -n '/^PEAK=/ { s/.*=//; p; q; }'`
[ -n "$PEAK" ] && PEAK="peakrate $PEAK"
MTU=`echo "$CFILE"| sed -n '/^MTU=/ { s/.*=//; p; q; }'`
[ -z "$MTU" ] && MTU="1500"
elif [ "$LEAF" = "sfq" ]; then
PERTURB=`echo "$CFILE"| sed -n '/^PERTURB=/ { s/.*=//; p; q; }'`
[ -n "$PERTURB" ] && PERTURB="perturb $PERTURB"
QUANTUM=`echo "$CFILE"| sed -n '/^QUANTUM=/ { s/.*=//; p; q; }'`
[ -n "$QUANTUM" ] && QUANTUM="quantum $QUANTUM"
elif [ "$LEAF" = "cbq" ]; then
echo "**CBQ: class $1, leaf qdisc CBQ not yet supported!"
fi
return 0
} # cbq_load_class
### Check if ip-route is installed
if [ ! -f /sbin/tc -o ! -f /sbin/ip ]; then
echo "**CBQ: ip-route2 utilities not installed!"
exit
fi
###########################
# See how were we called #
###########################
case "$1" in
### START ###
start)
### If you have cbq, tbf and u32 compiled into kernel, comment it out
for module in sch_cbq sch_tbf sch_sfq sch_prio cls_u32; do
if ! modprobe $module; then
echo "**CBQ: could not load module $module"
exit
fi
done
###################################
# Get all devices from configuration files $CBQ_PATH/cbq-*#
# and setup CBQ root classes for them (if it is possible).#
###################################
### Load DEVICES, DEVFIELDS and CLASSLIST
cbq_init
### Try to discover interface bandwidth from DEVICE
### field and if OK - setup root class for this one
for dev in $DEVICES; do
### Retrieve device bandwidth and weight
DEVTEMP=`echo "$DEVFIELDS"| sed -n "/^$dev,/ { s/.*,(.*),(.*)/1,2/; p;
q; }"`
DEVBWDT=${DEVTEMP%%,*}
DEVWGHT=${DEVTEMP##*,}
### If correctly set and the device is up, setup root class
if [ -n "$DEVBWDT" -a -n "$DEVWGHT" ]; then
if ! ip link | grep -q "$dev[:@].*UP"; then
echo "**CBQ: could not find device $dev! CBQ turned off."
cbq_off
exit
fi
### Remove old root class from device
cbq_device_off $dev
### Setup root class (queueing discipline) for device
tc qdisc add dev $dev root handle 1:0 cbq
bandwidth $DEVBWDT avpkt 1000 cell 8
### Create parent class :1. Every shaper will use it as
### parent unless specified otherwise using PARENT=xxxx
tc class add dev $dev parent 1:0 classid 1:1 cbq
bandwidth $DEVBWDT rate $DEVBWDT weight $DEVWGHT
prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000
else
echo "**CBQ: could not determine bandwidth or weight for device $dev!"
echo "**CBQ: setup DEVICE field properly!"
exit
fi
done # device
##################################################
# Set up all classes described in $CBQ_PATH/cbq-*#
##################################################
for classfile in $CLASSLIST; do
cbq_load_class $classfile
### Create class and setup leaf qdisc
tc class add dev $DEVICE parent $PARENT classid $CLASSID cbq
bandwidth $BANDWIDTH rate $RATE weight $WEIGHT prio $PRIO
allot 1514 cell 8 maxburst 20 avpkt 1000 $BOUNDED $ISOLATED
### Setup leaf queueing discipline
if [ "$LEAF" = "tbf" ]; then
tc qdisc add dev $DEVICE parent $CLASSID tbf
rate $RATE buffer $BUFFER limit $LIMIT mtu $MTU $PEAK
elif [ "$LEAF" = "sfq" ]; then
tc qdisc add dev $DEVICE parent $CLASSID sfq
$PERTURB $QUANTUM
elif [ "$LEAF" = "cbq" ]; then
:
fi
### Create u32 filter for addresses specified by RULE fields
RULESET=`echo "$CFILE"| sed -n '/^RULE/ { s/.*=//; p; }'`
[ -z "$RULESET" ] && continue
### Rules present, parse them
for rule in $RULESET; do
u32_s=""; u32_d=""
SADDR=""; SPORT=""
### Split up destination
DST=${rule##*,}
DADDR=${DST%%:*}
[ "$DADDR" != "$DST" ] && DPORT=${DST##*:} || DPORT=""
[ "$DADDR" = "*" ] && DADDR=""
### Split up source (if specified)
if [ "$DST" != "$rule" ]; then
SRC=${rule%%,*}
SADDR=${SRC%%:*}
[ "$SADDR" != "$SRC" ] && SPORT=${SRC##*:}
[ "$SADDR" = "*" ] && SADDR=""
fi
### Compose the u32 filter rules
[ -n "$SPORT" ] && u32_s="match ip sport $SPORT 0xffff"
[ -n "$SADDR" ] && u32_s="match ip src $SADDR $u32_s"
[ -n "$DPORT" ] && u32_d="match ip dport $DPORT 0xffff"
[ -n "$DADDR" ] && u32_d="match ip dst $DADDR $u32_d"
### Uncomment the following if you want to see parsed rules
# echo "$rule: $u32_s $u32_d"
### Attach u32 filter to the appropriate class
tc filter add dev $DEVICE parent 1:0 protocol ip
prio 100 u32 $u32_s $u32_d flowid $CLASSID
done ### rule
done ### class file
;;
### TIMECHECK ###
timecheck)
### Load DEVICES, DEVFIELDS and CLASSLIST
cbq_init
### Current time in hh:mm format
TIME_NOW=`date +%k:%M`
TIME_ABS=$[${TIME_NOW%%:*}*60 + ${TIME_NOW##*:}]
### Check every config file for TIME parameter
for classfile in $CLASSLIST; do
TIMERATES=`sed -ne 's/#.*//; s/ //g; /^TIME/ { s/.*=//; p; }'
$CBQ_PATH/$classfile`
[ -z "$TIMERATES" ] && continue
MATCH=0; CHANGE=0;
for timerate in $TIMERATES; do
### Split up TIME parameter
INTERVAL=${timerate%%;*}; PARAMS=${timerate##*;}
BEG_TIME=${INTERVAL%%-*}; END_TIME=${INTERVAL##*-}
### Compute interval boundaries
BEG_ABS=$[${BEG_TIME%%:*}*60 + ${BEG_TIME##*:}]
END_ABS=$[${END_TIME%%:*}*60 + ${END_TIME##*:}]
### Midnight wrap fixup
if [ $BEG_ABS -gt $END_ABS ]; then
[ $TIME_ABS -le $END_ABS ] && TIME_ABS=$[TIME_ABS + 24*60]
END_ABS=$[END_ABS + 24*60]
fi
### If the time matches, remembers params and set flag
if [ $TIME_ABS -ge $BEG_ABS -a $TIME_ABS -lt $END_ABS ]; then
TMP_RATE=${PARAMS%%/*}
TMP_WGHT=${PARAMS#*/}
TMP_PEAK=${TMP_WGHT#*/}
[ "$TMP_PEAK" = "$TMP_WGHT" ] && TMP_PEAK="" || TMP_WGHT={$TMP_WGHT%%/*}
[ -n "$TMP_PEAK" ] && TMP_PEAK="peakrate $TMP_PEAK"
MATCH=1
fi
done ### timerate
cbq_load_class $classfile
### Get current RATE of CBQ class
RATE_NOW=`tc class show dev $DEVICE| sed -n
"/cbq $CLASSID / { s/.*rate //; s/ .*//; p; q; }"`
[ -z "$RATE_NOW" ] && continue
### Time interval match is found
if [ $MATCH -ne 0 ]; then
### Check if there is any change in class RATE
if [ "$RATE_NOW" != "$TMP_RATE" ]; then
NEW_RATE="$TMP_RATE"
NEW_WGHT="$TMP_WGHT"
NEW_PEAK="$TMP_PEAK"
CHANGE=1
fi
### Match not found, reset to default RATE if necessary
elif [ "$RATE_NOW" != "$RATE" ]; then
NEW_WGHT="$WEIGHT"
NEW_RATE="$RATE"
NEW_PEAK="$PEAK"
CHANGE=1
fi
### If there's a change, replace CBQ class and leaf qdisc
[ $CHANGE -ne 1 ] && continue
### Get leaf qdisc handle
LEAF_HND=`tc class show dev $DEVICE| sed -n
"/cbq $CLASSID .* leaf / { s/.*leaf //; s/ .*//; p; q; }"`
[ -z "$LEAF_HND" ] && continue
### Replace CBQ class
tc class replace dev $DEVICE classid $CLASSID cbq
bandwidth $BANDWIDTH rate $NEW_RATE weight $NEW_WGHT prio $PRIO
allot 1514 cell 8 maxburst 20 avpkt 1000 $BOUNDED $ISOLATED
### Replace leaf qdisc
if [ "$LEAF" = "tbf" ]; then
tc qdisc replace dev $DEVICE handle $LEAF_HND tbf
rate $NEW_RATE buffer $BUFFER limit $LIMIT mtu $MTU $NEW_PEAK
elif [ "$LEAF" = "sfq" ]; then
### SFQ does not support parameter changes
### yet so it does not need replacing
#tc qdisc replace dev $DEVICE handle $LEAF_HND sfq
#$PERTURB $QUANTUM
:
elif [ "$LEAF" = "cbq" ]; then
:
fi
echo "**CBQ: $TIME_NOW: class $CLASS on $DEVICE changed rate ($RATE_NOW ->
$NEW_RATE)"
done ### class file
5
;;
### STOP ###
stop)
cbq_off
;;
### RESTART ###
restart)
$0 stop
$0 start
;;
### LIST ###
list)
cbq_init
cbq_show
;;
### STATS ###
stats)
cbq_init
cbq_show -s
;;
### default ###
*)
echo "Usage: " `basename $0` "{start|stop|restart|timecheck|list|stats}"
esac
PATH="/bin:/sbin:/usr/bin:/usr/sbin"
CBQ_PATH="/etc/cbq"
### Uncomment for debugging
#LOG_FILE="/var/run/cbq-$1"
if [ -n "$LOG_FILE" ]; then
### Initialize log file
echo "# `date`" > $LOG_FILE
### Logging equivalent of "ip" command
ip () {
[ -z "$LOG_FILE" ] && { /sbin/ip "$@"; return; }
echo -e " ip $@ " >> $LOG_FILE
/sbin/ip "$@" 2>&1 | tee -a $LOG_FILE
} # ip
### Logging equivalent of "tc" command
tc () {
[ -z "$LOG_FILE" ] && { /sbin/tc "$@"; return; }
echo -e " tc $@ " >> $LOG_FILE
/sbin/tc "$@" 2>&1 | tee -a $LOG_FILE
} # tc
fi # command logging
### Remove CBQ from all devices
cbq_off () {
# for dev in `ip link| sed -n '/^[0-9]/ { s/^[0-9]+:
#([a-z0-9]+)[:@].*/1/; p; }'`; do
# cbq_device_off $dev
for dev in `ifconfig |grep eth1 |awk {'print$1'}`; do
cbq_device_off $dev
done
return
} # cbq_off
### Remove root class from device $1
cbq_device_off () {
tc qdisc del dev $1 root &>/dev/null
return
} # cbq_device_off
### Display CBQ setup
cbq_show () {
for dev in $DEVICES; do
echo ---[ $dev: configured classes ]---------------------------
echo; tc $1 class show dev $dev; echo
echo ---[ $dev: queueing disciplines ]-------------------------
echo; tc $1 qdisc show dev $dev; echo
done
} # cbq_show
### Check configuration and load DEVFIELDS/CLASSLIST
cbq_init () {
### Check configuration in $CBQ_PATH directory and get CLASSLIST
CLASSLIST=`find $CBQ_PATH -name 'cbq-*' -maxdepth 1 -printf "%f "| sort`
if [ -z "$CLASSLIST" ]; then
echo "**CBQ: not configured in $CBQ_PATH!"
exit
fi
### Collect all DEVICE fields from $CBQ_PATH/cbq-*
DEVFIELDS=`find $CBQ_PATH -name 'cbq-*' -maxdepth 1 -exec sed -ne
's/#.*//; s/ //g; /^DEVICE=.*,.*,.*/ { s/.*=//; p; q; };
/^DEVICE=/ q' {} ;| sort -u`
### Check if there are any devices to set up
if [ -z "$DEVFIELDS" ]; then
echo "**CBQ: can't find any DEVICE field in $CBQ_PATH/cbq-*!"
exit
fi
### Extract all device names from DEVICE fields in $CBQ_PATH/cbq-*
DEVICES=`echo "$DEVFIELDS"| sed 's/,.*//'| sort -u`
### Check for multiple devices with different DEVICE fields
if [ `echo "$DEVICES"| wc -l` -ne `echo "$DEVFIELDS"| wc -l` ]; then
echo "**CBQ: multiple different DEVICE fields for one device found!"
echo "$DEVFIELDS"
exit
fi
} # cbq_init
### Load class configuration from file $1
cbq_load_class () {
CNAME="$CBQ_PATH/$1"
CFILE=`sed -e 's/#.*//; s/ //g; /^$/ d' $CNAME`
CLASS=`echo $1| sed 's/^cbq-0*//; s/..*//'`
if [ `/usr/bin/printf "%d" 0x$CLASS` -le 1 ]; then
echo "**CBQ: class ID of $1 must be > 1!"
cbq_off
exit
fi
### Device parameters
DEVICE=`echo "$CFILE"| sed -n '/^DEVICE=/ { s/.*=//; s/,.*//; p; q; }'`
BANDWIDTH=`echo "$DEVFIELDS"| sed -n "/^$DEVICE,/ { s/.*,(.*),.*/1/; p; q; }"`
### Class parameters
CLASSID="1:$CLASS"
PARENT=`echo "$CFILE"| sed -n '/^PARENT=/ { s/.*=0*//; p; q; }'`
[ -z "$PARENT" ] && PARENT="1:1" || PARENT="1:$PARENT"
LEAF=`echo "$CFILE"| sed -n '/^LEAF=/ { s/.*=//; p; q; }'`
[ -z "$LEAF" ] && LEAF="tbf"
BOUNDED=`echo "$CFILE"| sed -n '/^BOUNDED=/ { s/.*=//; p; q; }'`
[ "$BOUNDED" = "no" ] && BOUNDED="" || BOUNDED="bounded"
ISOLATED=`echo "$CFILE"| sed -n '/^ISOLATED=/ { s/.*=//; p; q; }'`
[ "$ISOLATED" = "yes" ] && ISOLATED="isolated" || ISOLATED=""
PRIO=`echo "$CFILE"| sed -n '/^PRIO=/ { s/.*=//; p; q; }'`
RATE=`echo "$CFILE"| sed -n '/^RATE=/ { s/.*=//; p; q; }'`
WEIGHT=`echo "$CFILE"| sed -n '/^WEIGHT=/ { s/.*=//; p; q; }'`
if [ -z "$RATE" -o -z "$WEIGHT" -o -z "$PRIO" ]; then
echo "**CBQ: missing RATE, WEIGHT or PRIO field(s) in $1!"
cbq_off
exit
fi
### Leaf qdisc parameters for TBF
if [ "$LEAF" = "tbf" ]; then
BUFFER=`echo "$CFILE"| sed -n '/^BUFFER=/ { s/.*=//; p; q; }'`
[ -z "$BUFFER" ] && BUFFER="10Kb/8"
LIMIT=`echo "$CFILE"| sed -n '/^LIMIT=/ { s/.*=//; p; q; }'`
[ -z "$LIMIT" ] && LIMIT="15Kb"
PEAK=`echo "$CFILE"| sed -n '/^PEAK=/ { s/.*=//; p; q; }'`
[ -n "$PEAK" ] && PEAK="peakrate $PEAK"
MTU=`echo "$CFILE"| sed -n '/^MTU=/ { s/.*=//; p; q; }'`
[ -z "$MTU" ] && MTU="1500"
elif [ "$LEAF" = "sfq" ]; then
PERTURB=`echo "$CFILE"| sed -n '/^PERTURB=/ { s/.*=//; p; q; }'`
[ -n "$PERTURB" ] && PERTURB="perturb $PERTURB"
QUANTUM=`echo "$CFILE"| sed -n '/^QUANTUM=/ { s/.*=//; p; q; }'`
[ -n "$QUANTUM" ] && QUANTUM="quantum $QUANTUM"
elif [ "$LEAF" = "cbq" ]; then
echo "**CBQ: class $1, leaf qdisc CBQ not yet supported!"
fi
return 0
} # cbq_load_class
### Check if ip-route is installed
if [ ! -f /sbin/tc -o ! -f /sbin/ip ]; then
echo "**CBQ: ip-route2 utilities not installed!"
exit
fi
###########################
# See how were we called #
###########################
case "$1" in
### START ###
start)
### If you have cbq, tbf and u32 compiled into kernel, comment it out
for module in sch_cbq sch_tbf sch_sfq sch_prio cls_u32; do
if ! modprobe $module; then
echo "**CBQ: could not load module $module"
exit
fi
done
###################################
# Get all devices from configuration files $CBQ_PATH/cbq-*#
# and setup CBQ root classes for them (if it is possible).#
###################################
### Load DEVICES, DEVFIELDS and CLASSLIST
cbq_init
### Try to discover interface bandwidth from DEVICE
### field and if OK - setup root class for this one
for dev in $DEVICES; do
### Retrieve device bandwidth and weight
DEVTEMP=`echo "$DEVFIELDS"| sed -n "/^$dev,/ { s/.*,(.*),(.*)/1,2/; p;
q; }"`
DEVBWDT=${DEVTEMP%%,*}
DEVWGHT=${DEVTEMP##*,}
### If correctly set and the device is up, setup root class
if [ -n "$DEVBWDT" -a -n "$DEVWGHT" ]; then
if ! ip link | grep -q "$dev[:@].*UP"; then
echo "**CBQ: could not find device $dev! CBQ turned off."
cbq_off
exit
fi
### Remove old root class from device
cbq_device_off $dev
### Setup root class (queueing discipline) for device
tc qdisc add dev $dev root handle 1:0 cbq
bandwidth $DEVBWDT avpkt 1000 cell 8
### Create parent class :1. Every shaper will use it as
### parent unless specified otherwise using PARENT=xxxx
tc class add dev $dev parent 1:0 classid 1:1 cbq
bandwidth $DEVBWDT rate $DEVBWDT weight $DEVWGHT
prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000
else
echo "**CBQ: could not determine bandwidth or weight for device $dev!"
echo "**CBQ: setup DEVICE field properly!"
exit
fi
done # device
##################################################
# Set up all classes described in $CBQ_PATH/cbq-*#
##################################################
for classfile in $CLASSLIST; do
cbq_load_class $classfile
### Create class and setup leaf qdisc
tc class add dev $DEVICE parent $PARENT classid $CLASSID cbq
bandwidth $BANDWIDTH rate $RATE weight $WEIGHT prio $PRIO
allot 1514 cell 8 maxburst 20 avpkt 1000 $BOUNDED $ISOLATED
### Setup leaf queueing discipline
if [ "$LEAF" = "tbf" ]; then
tc qdisc add dev $DEVICE parent $CLASSID tbf
rate $RATE buffer $BUFFER limit $LIMIT mtu $MTU $PEAK
elif [ "$LEAF" = "sfq" ]; then
tc qdisc add dev $DEVICE parent $CLASSID sfq
$PERTURB $QUANTUM
elif [ "$LEAF" = "cbq" ]; then
:
fi
### Create u32 filter for addresses specified by RULE fields
RULESET=`echo "$CFILE"| sed -n '/^RULE/ { s/.*=//; p; }'`
[ -z "$RULESET" ] && continue
### Rules present, parse them
for rule in $RULESET; do
u32_s=""; u32_d=""
SADDR=""; SPORT=""
### Split up destination
DST=${rule##*,}
DADDR=${DST%%:*}
[ "$DADDR" != "$DST" ] && DPORT=${DST##*:} || DPORT=""
[ "$DADDR" = "*" ] && DADDR=""
### Split up source (if specified)
if [ "$DST" != "$rule" ]; then
SRC=${rule%%,*}
SADDR=${SRC%%:*}
[ "$SADDR" != "$SRC" ] && SPORT=${SRC##*:}
[ "$SADDR" = "*" ] && SADDR=""
fi
### Compose the u32 filter rules
[ -n "$SPORT" ] && u32_s="match ip sport $SPORT 0xffff"
[ -n "$SADDR" ] && u32_s="match ip src $SADDR $u32_s"
[ -n "$DPORT" ] && u32_d="match ip dport $DPORT 0xffff"
[ -n "$DADDR" ] && u32_d="match ip dst $DADDR $u32_d"
### Uncomment the following if you want to see parsed rules
# echo "$rule: $u32_s $u32_d"
### Attach u32 filter to the appropriate class
tc filter add dev $DEVICE parent 1:0 protocol ip
prio 100 u32 $u32_s $u32_d flowid $CLASSID
done ### rule
done ### class file
;;
### TIMECHECK ###
timecheck)
### Load DEVICES, DEVFIELDS and CLASSLIST
cbq_init
### Current time in hh:mm format
TIME_NOW=`date +%k:%M`
TIME_ABS=$[${TIME_NOW%%:*}*60 + ${TIME_NOW##*:}]
### Check every config file for TIME parameter
for classfile in $CLASSLIST; do
TIMERATES=`sed -ne 's/#.*//; s/ //g; /^TIME/ { s/.*=//; p; }'
$CBQ_PATH/$classfile`
[ -z "$TIMERATES" ] && continue
MATCH=0; CHANGE=0;
for timerate in $TIMERATES; do
### Split up TIME parameter
INTERVAL=${timerate%%;*}; PARAMS=${timerate##*;}
BEG_TIME=${INTERVAL%%-*}; END_TIME=${INTERVAL##*-}
### Compute interval boundaries
BEG_ABS=$[${BEG_TIME%%:*}*60 + ${BEG_TIME##*:}]
END_ABS=$[${END_TIME%%:*}*60 + ${END_TIME##*:}]
### Midnight wrap fixup
if [ $BEG_ABS -gt $END_ABS ]; then
[ $TIME_ABS -le $END_ABS ] && TIME_ABS=$[TIME_ABS + 24*60]
END_ABS=$[END_ABS + 24*60]
fi
### If the time matches, remembers params and set flag
if [ $TIME_ABS -ge $BEG_ABS -a $TIME_ABS -lt $END_ABS ]; then
TMP_RATE=${PARAMS%%/*}
TMP_WGHT=${PARAMS#*/}
TMP_PEAK=${TMP_WGHT#*/}
[ "$TMP_PEAK" = "$TMP_WGHT" ] && TMP_PEAK="" || TMP_WGHT={$TMP_WGHT%%/*}
[ -n "$TMP_PEAK" ] && TMP_PEAK="peakrate $TMP_PEAK"
MATCH=1
fi
done ### timerate
cbq_load_class $classfile
### Get current RATE of CBQ class
RATE_NOW=`tc class show dev $DEVICE| sed -n
"/cbq $CLASSID / { s/.*rate //; s/ .*//; p; q; }"`
[ -z "$RATE_NOW" ] && continue
### Time interval match is found
if [ $MATCH -ne 0 ]; then
### Check if there is any change in class RATE
if [ "$RATE_NOW" != "$TMP_RATE" ]; then
NEW_RATE="$TMP_RATE"
NEW_WGHT="$TMP_WGHT"
NEW_PEAK="$TMP_PEAK"
CHANGE=1
fi
### Match not found, reset to default RATE if necessary
elif [ "$RATE_NOW" != "$RATE" ]; then
NEW_WGHT="$WEIGHT"
NEW_RATE="$RATE"
NEW_PEAK="$PEAK"
CHANGE=1
fi
### If there's a change, replace CBQ class and leaf qdisc
[ $CHANGE -ne 1 ] && continue
### Get leaf qdisc handle
LEAF_HND=`tc class show dev $DEVICE| sed -n
"/cbq $CLASSID .* leaf / { s/.*leaf //; s/ .*//; p; q; }"`
[ -z "$LEAF_HND" ] && continue
### Replace CBQ class
tc class replace dev $DEVICE classid $CLASSID cbq
bandwidth $BANDWIDTH rate $NEW_RATE weight $NEW_WGHT prio $PRIO
allot 1514 cell 8 maxburst 20 avpkt 1000 $BOUNDED $ISOLATED
### Replace leaf qdisc
if [ "$LEAF" = "tbf" ]; then
tc qdisc replace dev $DEVICE handle $LEAF_HND tbf
rate $NEW_RATE buffer $BUFFER limit $LIMIT mtu $MTU $NEW_PEAK
elif [ "$LEAF" = "sfq" ]; then
### SFQ does not support parameter changes
### yet so it does not need replacing
#tc qdisc replace dev $DEVICE handle $LEAF_HND sfq
#$PERTURB $QUANTUM
:
elif [ "$LEAF" = "cbq" ]; then
:
fi
echo "**CBQ: $TIME_NOW: class $CLASS on $DEVICE changed rate ($RATE_NOW ->
$NEW_RATE)"
done ### class file
5
;;
### STOP ###
stop)
cbq_off
;;
### RESTART ###
restart)
$0 stop
$0 start
;;
### LIST ###
list)
cbq_init
cbq_show
;;
### STATS ###
stats)
cbq_init
cbq_show -s
;;
### default ###
*)
echo "Usage: " `basename $0` "{start|stop|restart|timecheck|list|stats}"
esac
Para que o CBQ funcione, é preciso criar os arquivos que serão lidos para verificar a banda. Faça assim:
# mkdir /etc/cbq
Dentro dele crie os seguintes arquivos que facilitarão a criação dos arquivos de banda:
# vi geracbq.sh
#!/bin/bash
# x = número da seqüência
x=1
for i in `cat rede.txt`; do
# Regra de Limite Interface Eth1 ( INTERNA )
x=`expr ${x} + 1`
#info="`echo "${i}" | sed -e 's///_/g'`_64Kbits_eth1"
info="`echo "${i}" | sed -e 's///_/g'`"
echo "DEVICE=eth1,10Mbit,1Mbit
RATE=64Kbit
WEIGHT=6Kbit
PRIO=5
RULE=${i}
BOUNDED=yes
ISOLATED=yes
" >> cbq-0${x}.${info}
# Regra de Limite Interface Eth1.out
x=`expr ${x} + 1`
info="`echo "${i}" | sed -e 's///_/g'`_out"
echo "DEVICE=eth0,10Mbit,1Mbit
RATE=64Kbit
WEIGHT=6Kbit
PRIO=5
MARK=${x}
BOUNDED=yes
ISOLATED=no
" >> cbq-0${x}.${info}
echo "iptables -t mangle -A FORWARD -s ${i} -j MARK --set-mark ${x}" >> /etc/cbq/mangle
echo "iptables -t mangle -A FORWARD -s ${i} -j ACCEPT" >> /etc/cbq/mangle
echo "iptables -t mangle -A FORWARD -d ${i} -j MARK --set-mark ${x}" >> /etc/cbq/mangle
echo "iptables -t mangle -A FORWARD -d ${i} -j ACCEPT" >> /etc/cbq/mangle
done
# x = número da seqüência
x=1
for i in `cat rede.txt`; do
# Regra de Limite Interface Eth1 ( INTERNA )
x=`expr ${x} + 1`
#info="`echo "${i}" | sed -e 's///_/g'`_64Kbits_eth1"
info="`echo "${i}" | sed -e 's///_/g'`"
echo "DEVICE=eth1,10Mbit,1Mbit
RATE=64Kbit
WEIGHT=6Kbit
PRIO=5
RULE=${i}
BOUNDED=yes
ISOLATED=yes
" >> cbq-0${x}.${info}
# Regra de Limite Interface Eth1.out
x=`expr ${x} + 1`
info="`echo "${i}" | sed -e 's///_/g'`_out"
echo "DEVICE=eth0,10Mbit,1Mbit
RATE=64Kbit
WEIGHT=6Kbit
PRIO=5
MARK=${x}
BOUNDED=yes
ISOLATED=no
" >> cbq-0${x}.${info}
echo "iptables -t mangle -A FORWARD -s ${i} -j MARK --set-mark ${x}" >> /etc/cbq/mangle
echo "iptables -t mangle -A FORWARD -s ${i} -j ACCEPT" >> /etc/cbq/mangle
echo "iptables -t mangle -A FORWARD -d ${i} -j MARK --set-mark ${x}" >> /etc/cbq/mangle
echo "iptables -t mangle -A FORWARD -d ${i} -j ACCEPT" >> /etc/cbq/mangle
done
Onde:
- eth0 - Rede externa
- eth1 - Rede interna
Crie o arquivo rede.txt (altere para sua estrutura)
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
No exemplo acima ele criará 20 arquivos, 10 para download e 10 para upload.
Feito isto, agora apague ou mova para outro diretório os arquivos rede.txt e o geracbq.sh.
Éra o q faltava para min o download ja estava funcionando legal! Só faltava o up!...
Sera q vocês tem alguma dica para min, para o cbq não limitar o cache do squid?
Meus parabens, otimo artigo....
Ats.