forked from extern/shorewall_code
First implementation of HFSC queuing discipline
This commit is contained in:
parent
4cf2c1b59f
commit
787caa7f32
@ -157,6 +157,7 @@ our @deferred_rules;
|
||||
# redirected => [ <dev1>, <dev2>, ... ]
|
||||
# nextclass => <number>
|
||||
# occurs => Has one or more occurring classes
|
||||
# qdisc => htb|hfsc
|
||||
# }
|
||||
#
|
||||
our @tcdevices;
|
||||
@ -173,6 +174,8 @@ our $sticky;
|
||||
# mark => <mark> ,
|
||||
# number => <number> ,
|
||||
# rate => <rate> ,
|
||||
# umax => <umax> ,
|
||||
# dmax => <dmax> ,
|
||||
# ceiling => <ceiling> ,
|
||||
# priority => <priority> ,
|
||||
# occurs => <number> # 0 means that this is a class generated by another class with occurs > 1
|
||||
@ -472,7 +475,7 @@ sub validate_tc_device( ) {
|
||||
fatal_error "Duplicate INTERFACE ($device)" if $tcdevices{$device};
|
||||
fatal_error "Invalid INTERFACE name ($device)" if $device =~ /[:+]/;
|
||||
|
||||
my ( $classify, $pfifo, $flow) = (0, 0, '' );
|
||||
my ( $classify, $pfifo, $flow, $qdisc ) = (0, 0, '', 'htb' );
|
||||
|
||||
if ( $options ne '-' ) {
|
||||
for my $option ( split_list1 $options, 'option' ) {
|
||||
@ -484,6 +487,10 @@ sub validate_tc_device( ) {
|
||||
} elsif ( $option eq 'pfifo' ) {
|
||||
fatal_error "The 'pfifo'' option is not allowed with 'flow='" if $flow;
|
||||
$pfifo = 1;
|
||||
} elsif ( $option eq 'hfsc' ) {
|
||||
$qdisc = 'hfsc';
|
||||
} elsif ( $option eq 'htb' ) {
|
||||
$qdisc = 'htb';
|
||||
} else {
|
||||
fatal_error "Unknown device option ($option)";
|
||||
}
|
||||
@ -506,16 +513,17 @@ sub validate_tc_device( ) {
|
||||
fatal_error "IN-BANDWIDTH must be zero for REDIRECTED devices" if $rdevref->{in_bandwidth} ne '0kbit';
|
||||
}
|
||||
|
||||
$tcdevices{$device} = { in_bandwidth => rate_to_kbit( $inband ) . 'kbit' ,
|
||||
out_bandwidth => rate_to_kbit( $outband ) . 'kbit' ,
|
||||
$tcdevices{$device} = { in_bandwidth => rate_to_kbit( $inband ) . 'kbit',
|
||||
out_bandwidth => rate_to_kbit( $outband ) . 'kbit',
|
||||
number => $devnumber,
|
||||
classify => $classify ,
|
||||
flow => $flow ,
|
||||
pfifo => $pfifo ,
|
||||
classify => $classify,
|
||||
flow => $flow,
|
||||
pfifo => $pfifo,
|
||||
tablenumber => 1 ,
|
||||
redirected => \@redirected ,
|
||||
redirected => \@redirected,
|
||||
default => 0,
|
||||
nextclass => 2,
|
||||
qdisc => $qdisc,
|
||||
} ,
|
||||
|
||||
push @tcdevices, $device;
|
||||
@ -545,6 +553,21 @@ sub convert_rate( $$$ ) {
|
||||
$rate;
|
||||
}
|
||||
|
||||
sub convert_delay( $ ) {
|
||||
my $delay = shift;
|
||||
|
||||
return 0 unless $delay;
|
||||
return $1 if $delay =~ /^(\d+)(ms)?$/;
|
||||
fatal_error "Invalid Delay ($delay)";
|
||||
}
|
||||
|
||||
sub convert_size( $ ) {
|
||||
my $size = shift;
|
||||
return '' unless $size;
|
||||
return $1 if $size =~ /^(\d+)b?$/;
|
||||
fatal_error "Invalid Size ($size)";
|
||||
}
|
||||
|
||||
sub dev_by_number( $ ) {
|
||||
my $dev = $_[0];
|
||||
my $devnum = uc $dev;
|
||||
@ -644,8 +667,25 @@ sub validate_tc_class( ) {
|
||||
$parentref->{leaf} = 0;
|
||||
}
|
||||
|
||||
my ( $umax, $dmax ) = ( '', '' );
|
||||
|
||||
if ( $devref->{qdisc} eq 'hfsc' ) {
|
||||
( my $trate , $dmax, $umax , my $rest ) = split ':', $rate , 4;
|
||||
|
||||
fatal_error "Invalid RATE ($rate)" if defined $rest;
|
||||
|
||||
$rate = convert_rate ( $full, $trate, 'RATE' );
|
||||
$dmax = convert_delay( $dmax );
|
||||
$umax = convert_size( $umax );
|
||||
fatal_error "A umax or dmax value must be specified for an hfsc class" unless $umax || $dmax;
|
||||
} else {
|
||||
$rate = convert_rate ( $full, $rate, 'RATE' );
|
||||
}
|
||||
|
||||
$tcref->{$classnumber} = { tos => [] ,
|
||||
rate => convert_rate( $full, $rate, 'RATE' ) ,
|
||||
rate => $rate ,
|
||||
umax => $umax ,
|
||||
dmax => $dmax ,
|
||||
ceiling => convert_rate( $full, $ceil, 'CEIL' ) ,
|
||||
priority => $prio eq '-' ? 1 : $prio ,
|
||||
mark => $markval ,
|
||||
@ -960,11 +1000,17 @@ sub setup_traffic_shaping() {
|
||||
emit ( "${dev}_exists=Yes",
|
||||
"qt \$TC qdisc del dev $device root",
|
||||
"qt \$TC qdisc del dev $device ingress",
|
||||
"run_tc qdisc add dev $device root handle $devnum: htb default $defmark r2q $r2q",
|
||||
"${dev}_mtu=\$(get_device_mtu $device)",
|
||||
"${dev}_mtu1=\$(get_device_mtu1 $device)",
|
||||
"run_tc class add dev $device parent $devnum: classid $devnum:1 htb rate $devref->{out_bandwidth} \$${dev}_mtu1"
|
||||
);
|
||||
"${dev}_mtu1=\$(get_device_mtu1 $device)"
|
||||
);
|
||||
|
||||
if ( $devref->{qdisc} eq 'htb' ) {
|
||||
emit ( "run_tc qdisc add dev $device root handle $devnum: htb default $defmark r2q $r2q" ,
|
||||
"run_tc class add dev $device parent $devnum: classid $devnum:1 htb rate $devref->{out_bandwidth} \$${dev}_mtu1" );
|
||||
} else {
|
||||
emit ( "run_tc qdisc add dev $device root handle $devnum: hfsc default $defmark" ,
|
||||
"run_tc class add dev $device parent $devnum: classid $devnum:1 hfsc sc rate $devref->{out_bandwidth} ul rate $devref->{out_bandwidth}" );
|
||||
}
|
||||
|
||||
if ( $devref->{occurs} ) {
|
||||
#
|
||||
@ -1046,9 +1092,36 @@ sub setup_traffic_shaping() {
|
||||
$lastdevice = $device;
|
||||
}
|
||||
|
||||
emit ( "[ \$${dev}_mtu -gt $quantum ] && quantum=\$${dev}_mtu || quantum=$quantum",
|
||||
"run_tc class add dev $device parent $devref->{number}:$parent classid $classid htb rate $rate ceil $tcref->{ceiling}kbit prio $tcref->{priority} \$${dev}_mtu1 quantum \$quantum" );
|
||||
emit ( "[ \$${dev}_mtu -gt $quantum ] && quantum=\$${dev}_mtu || quantum=$quantum" );
|
||||
|
||||
if ( $devref->{qdisc} eq 'htb' ) {
|
||||
emit ( "run_tc class add dev $device parent $devref->{number}:$parent classid $classid htb rate $rate ceil $tcref->{ceiling}kbit prio $tcref->{priority} \$${dev}_mtu1 quantum \$quantum" );
|
||||
} else {
|
||||
my $umax = $tcref->{umax};
|
||||
my $dmax = $tcref->{dmax};
|
||||
|
||||
unless ( $dmax ) {
|
||||
#
|
||||
# We must calculate the dmax but we know that umax has been specified
|
||||
#
|
||||
my $packetbits = 8 * $umax;
|
||||
my $rateinbits = 1000 * $tcref->{rate};
|
||||
my $fullinbytes = $devref->{out_bandwidth};
|
||||
$fullinbytes =~ s/kbit//;
|
||||
my $fullinbits = 1000 * $fullinbytes;
|
||||
my $packetspersecond = $rateinbits / $packetbits;
|
||||
my $totaldelayinms = 1000 * ( 1 - ( $rateinbits / $fullinbits ) );
|
||||
#
|
||||
# In this calculation, '3' is a magic number. We can adjust it as necessary as we learn about this QDISC
|
||||
#
|
||||
$dmax = int( 3 * $totaldelayinms / $packetspersecond );
|
||||
}
|
||||
|
||||
$umax = $umax ? "${umax}b" : "\$${dev}_mtu";
|
||||
|
||||
emit ( "run_tc class add dev $device parent $devref->{number}:$parent classid $classid hfsc sc umax $umax dmax ${dmax}ms rate $rate ul rate $tcref->{ceiling}kbit" );
|
||||
}
|
||||
|
||||
emit( "run_tc qdisc add dev $device parent $classid handle ${classnum}: sfq quantum \$quantum limit 127 perturb 10" ) if $tcref->{leaf} && ! $tcref->{pfifo};
|
||||
#
|
||||
# add filters
|
||||
|
Loading…
Reference in New Issue
Block a user