diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm
index bff40da84..b1d276fe4 100644
--- a/Shorewall/Perl/Shorewall/Tc.pm
+++ b/Shorewall/Perl/Shorewall/Tc.pm
@@ -1031,6 +1031,18 @@ sub dev_by_number( $ ) {
( $dev , $devref );
}
+use constant { RED_INTEGER => 1, RED_FLOAT => 2, RED_NONE => 3 };
+
+my %validredoptions = ( min => RED_INTEGER,
+ max => RED_INTEGER,
+ limit => RED_INTEGER,
+ burst => RED_INTEGER,
+ avpkt => RED_INTEGER,
+ bandwidth => RED_INTEGER,
+ probability => RED_FLOAT,
+ ecn => RED_NONE,
+ );
+
sub validate_tc_class( ) {
my ( $devclass, $mark, $rate, $ceil, $prio, $options ) =
split_line 'tcclasses file', { interface => 0, mark => 1, rate => 2, ceil => 3, prio => 4, options => 5 };
@@ -1040,6 +1052,7 @@ sub validate_tc_class( ) {
my $occurs = 1;
my $parentclass = 1;
my $parentref;
+ my $lsceil = 0;
fatal_error 'INTERFACE must be specified' if $devclass eq '-';
fatal_error 'CEIL must be specified' if $ceil eq '-';
@@ -1116,7 +1129,9 @@ sub validate_tc_class( ) {
my $parentnum = in_hexp $parentclass;
fatal_error "Unknown Parent class ($parentnum)" unless $parentref && $parentref->{occurs} == 1;
fatal_error "The class ($parentnum) specifies UMAX and/or DMAX; it cannot serve as a parent" if $parentref->{dmax};
- fatal_error "The class ($parentnum) specifies flow; it cannot serve as a parent" if $parentref->{flow};
+ fatal_error "The class ($parentnum) specifies 'flow'; it cannot serve as a parent" if $parentref->{flow};
+ fatal_error "The class ($parentnum) specifies 'red'; it cannot serve as a parent " if $parentref->{red};
+ fatal_error "The class ($parentnum) has an 'ls' curve; it cannot serve as a parent " if $parentref->{lsceil};
fatal_error "The default class ($parentnum) may not have sub-classes" if ( $devref->{default} || 0 ) == $parentclass;
$parentref->{leaf} = 0;
$ratemax = $parentref->{rate};
@@ -1127,16 +1142,27 @@ sub validate_tc_class( ) {
my ( $umax, $dmax ) = ( '', '' );
+ if ( $ceil =~ /^(.+):(.+)/ ) {
+ fatal_error "An LS rate may only be specified for HFSC classes" unless $devref->{qdisc} eq 'hfsc';
+ $lsceil = $1;
+ $ceil = $2;
+ }
+
if ( $devref->{qdisc} eq 'hfsc' ) {
- ( my $trate , $dmax, $umax , my $rest ) = split ':', $rate , 4;
+ if ( $rate eq '-' ) {
+ fatal_error 'A RATE must be supplied' unless $lsceil;
+ $rate = 0;
+ } else {
+ ( my $trate , $dmax, $umax , my $rest ) = split ':', $rate , 4;
- fatal_error "Invalid RATE ($rate)" if defined $rest;
+ fatal_error "Invalid RATE ($rate)" if defined $rest;
- $rate = convert_rate ( $ratemax, $trate, 'RATE', $ratename );
- $dmax = convert_delay( $dmax );
- $umax = convert_size( $umax );
- fatal_error "DMAX must be specified when UMAX is specified" if $umax && ! $dmax;
- $parentclass ||= 1;
+ $rate = convert_rate ( $ratemax, $trate, 'RATE', $ratename );
+ $dmax = convert_delay( $dmax );
+ $umax = convert_size( $umax );
+ fatal_error "DMAX must be specified when UMAX is specified" if $umax && ! $dmax;
+ $parentclass ||= 1;
+ }
} else {
$rate = convert_rate ( $ratemax, $rate, 'RATE' , $ratename );
}
@@ -1154,6 +1180,7 @@ sub validate_tc_class( ) {
umax => $umax ,
dmax => $dmax ,
ceiling => convert_rate( $ceilmax, $ceil, 'CEIL' , $ceilname ) ,
+ lsceil => $lsceil ? convert_rate( $ceilmax, $lsceil, 'CEIL', 'LSCEIL' ) : 0,
priority => $prio eq '-' ? 1 : $prio ,
mark => $markval ,
flow => '' ,
@@ -1169,6 +1196,8 @@ sub validate_tc_class( ) {
fatal_error "RATE ($tcref->{rate}) exceeds CEIL ($tcref->{ceiling})" if $tcref->{rate} > $tcref->{ceiling};
+ my ( $red, %redopts ) = ( 0, ( avpkt => 1000 ) );
+
unless ( $options eq '-' ) {
for my $option ( split_list1 "\L$options", 'option' ) {
my $optval = $tosoptions{$option};
@@ -1192,9 +1221,11 @@ sub validate_tc_class( ) {
push @{$tcref->{tos}}, $option;
} elsif ( $option =~ /^flow=(.*)$/ ) {
fatal_error "The 'flow' option is not allowed with 'pfifo'" if $tcref->{pfifo};
+ fatal_error "The 'flow' option is not allowed with 'red'" if $tcref->{red};
$tcref->{flow} = process_flow $1;
} elsif ( $option eq 'pfifo' ) {
- fatal_error "The 'pfifo'' option is not allowed with 'flow='" if $tcref->{flow};
+ fatal_error "The 'pfifo' option is not allowed with 'flow='" if $tcref->{flow};
+ fatal_error "The 'pfifo' option is not allowed with 'red='" if $tcref->{red};
$tcref->{pfifo} = 1;
} elsif ( $option =~ /^occurs=(\d+)$/ ) {
my $val = $1;
@@ -1215,6 +1246,31 @@ sub validate_tc_class( ) {
warning_message "limit ignored with pfifo queuing" if $tcref->{pfifo};
fatal_error "Invalid limit ($1)" if $1 < 3 || $1 > 128;
$tcref->{limit} = $1;
+ } elsif ( $option =~ s/^red=// ) {
+ fatal_error "The 'red=' option is not allowed with 'flow='" if $tcref->{flow};
+ fatal_error "The 'red=' option is not allowed with 'pfifo'" if $tcref->{pfifo};
+ $tcref->{red} = 1;
+ my $opttype;
+ for my $redopt ( split_list( $option , q('red' option list) ) ) {
+ if ( $redopt =~ /^([a-z]+)(?:=((0?\.)?(\d{1,8})))?$/ ) {
+ fatal_error "Invalid 'red' option ($1)" unless $opttype = $validredoptions{$1};
+ fatal_error "The $1 option requires a value" unless $opttype == RED_NONE || $2;
+ fatal_error "The $1 option requires a value 0 < value < 1" if $opttype == RED_FLOAT && ! $3;
+ fatal_error "The $1 option requires an integer value" if $opttype == RED_INTEGER && $3;
+ $redopts{$1} = $2;
+ } else {
+ fatal_error "Invalid 'red' option specification ($redopt)";
+ }
+ }
+
+ for ( qw/ limit min max avpkt burst probability / ) {
+ fatal_error "The $_ 'red' option is required" unless $redopts{$_};
+ }
+
+ fatal_error "The 'max' red option must be at least 2 * 'min'" unless $redopts{max} >= 2 * $redopts{min};
+ fatal_error "The 'limit' red option must be at least 2 * 'max'" unless $redopts{limit} >= 2 * $redopts{min};
+ $redopts{ecn} = 1 if exists $redopts{ecn};
+ $tcref->{redopts} = \%redopts;
} else {
fatal_error "Unknown option ($option)";
}
@@ -1246,6 +1302,8 @@ sub validate_tc_class( ) {
occurs => 0,
parent => $parentclass,
limit => $tcref->{limit},
+ red => $tcref->{red},
+ redopts => $tcref->{redopts},
};
push @tcclasses, "$device:$classnumber";
};
@@ -1800,7 +1858,9 @@ sub process_traffic_shaping() {
my $mark = $tcref->{mark};
my $devicenumber = in_hexp $devref->{number};
my $classid = join( ':', $devicenumber, $classnum);
- my $rate = "$tcref->{rate}kbit";
+ my $rawrate = $tcref->{rate};
+ my $rate = "${rawrate}kbit";
+ my $lsceil = $tcref->{lsceil};
my $quantum = calculate_quantum $rate, calculate_r2q( $devref->{out_bandwidth} );
$classids{$classid}=$device;
@@ -1814,23 +1874,49 @@ sub process_traffic_shaping() {
emit ( "run_tc class add dev $device parent $devicenumber:$parent classid $classid htb rate $rate ceil $tcref->{ceiling}kbit prio $tcref->{priority} \$${dev}_mtu1 quantum \$quantum" );
} else {
my $dmax = $tcref->{dmax};
+ my $rule = "run_tc class add dev $device parent $devicenumber:$parent classid $classid hfsc";
if ( $dmax ) {
my $umax = $tcref->{umax} ? "$tcref->{umax}b" : "\${${dev}_mtu}b";
- emit ( "run_tc class add dev $device parent $devicenumber:$parent classid $classid hfsc sc umax $umax dmax ${dmax}ms rate $rate ul rate $tcref->{ceiling}kbit" );
+ $rule .= " sc umax $umax dmax ${dmax}ms";
+ $rule .= " rate $rate" if $rawrate;
} else {
- emit ( "run_tc class add dev $device parent $devicenumber:$parent classid $classid hfsc sc rate $rate ul rate $tcref->{ceiling}kbit" );
+ $rule .= " sc rate $rate" if $rawrate;
}
+
+ $rule .= " ls rate ${lsceil}kbit" if $lsceil;
+
+ emit ( "$rule ul rate $tcref->{ceiling}kbit" );
}
- if ( $tcref->{leaf} && ! $tcref->{pfifo} ) {
- 1 while $devnums[++$sfq];
+ if ( $tcref->{leaf} ) {
+ if ( $tcref->{red} ) {
+ 1 while $devnums[++$sfq];
+ $sfqinhex = in_hexp( $sfq);
- $sfqinhex = in_hexp( $sfq);
- if ( $devref->{qdisc} eq 'htb' ) {
- emit( "run_tc qdisc add dev $device parent $classid handle $sfqinhex: sfq quantum \$quantum limit $tcref->{limit} perturb 10" );
- } else {
- emit( "run_tc qdisc add dev $device parent $classid handle $sfqinhex: sfq limit $tcref->{limit} perturb 10" );
+ my ( $options, $redopts ) = ( '', $tcref->{redopts} );
+
+ while ( my ( $option, $type ) = each %validredoptions ) {
+ if ( my $value = $redopts->{$option} ) {
+ if ( $type == RED_NONE ) {
+ $options = join( ' ', $options, $option ) if $value;
+ } else {
+ $options = join( ' ', $options, $option, $value );
+ }
+ }
+ }
+
+ emit( "run_tc qdisc add dev $device parent $classid handle $sfqinhex: red${options}" );
+
+ } elsif ( $tcref->{leaf} && ! $tcref->{pfifo} ) {
+ 1 while $devnums[++$sfq];
+
+ $sfqinhex = in_hexp( $sfq);
+ if ( $devref->{qdisc} eq 'htb' ) {
+ emit( "run_tc qdisc add dev $device parent $classid handle $sfqinhex: sfq quantum \$quantum limit $tcref->{limit} perturb 10" );
+ } else {
+ emit( "run_tc qdisc add dev $device parent $classid handle $sfqinhex: sfq limit $tcref->{limit} perturb 10" );
+ }
}
}
#
diff --git a/Shorewall/manpages/shorewall-tcclasses.xml b/Shorewall/manpages/shorewall-tcclasses.xml
index f6c3b49e9..14b5a19de 100644
--- a/Shorewall/manpages/shorewall-tcclasses.xml
+++ b/Shorewall/manpages/shorewall-tcclasses.xml
@@ -175,7 +175,7 @@
RATE -
- rate[:dmax[:umax]]
+ {-|rate[:dmax[:umax]]}
The minimum bandwidth this class should get, when the traffic
@@ -185,11 +185,12 @@
class exceed the CEIL of the parent class, things don't work
well.
- When using the HFSC queuing discipline, leaf classes may
- specify dmax, the maximum delay in
- milliseconds that the first queued packet for this class should
- experience. May be expressed as an integer, optionally followed by
- 'ms' with no intervening white space (e.g., 10ms).
+ When using the HFSC queuing discipline, this column specify
+ the real-time (RT) service curve. leaf classes may specify
+ dmax, the maximum delay in milliseconds
+ that the first queued packet for this class should experience. May
+ be expressed as an integer, optionally followed by 'ms' with no
+ intervening white space (e.g., 10ms).HFSC leaf classes may also specify
umax, the largest packet expected in this
@@ -198,12 +199,18 @@
followed by 'b' with no intervening white space (e.g., 800b).
umax may only be given if
dmax is also given.
+
+ Beginning with Shorewall 4.5.6, HFSC classes may omit this
+ column (e.g, '-' in the column), provided that an
+ lsrate is specified (see CEIL below).
+ These rates are used to arbitrate between classes of the same
+ priority.CEIL -
- rate
+ [lsrate:]rateThe maximum bandwidth this class is allowed to use when the
@@ -214,6 +221,9 @@
here for setting the maximum bandwidth to the RATE of the parent
class, or the OUT-BANDWIDTH of the device if there is no parent
class.
+
+ Beginning with Shorewall 4.5.6, you can also specify an
+ lsrate (link sharing rate).
@@ -253,7 +263,7 @@
This is the default class for that interface where all
traffic should go, that is not classified otherwise.
-
+ You must define
-
+ This option is only valid for ONE class per
@@ -430,6 +440,119 @@
assumed.
+
+
+ red=(redoption=value,
+ ...)
+
+
+ Added in Shorewall 4.5.6. When specified on a leaf
+ class, causes the class to use the red queuing discipline
+ rather than SFQ. See tc-red (8) for additional
+ information.
+
+ Allowable redoptions are:
+
+
+
+ min
+
+
+ Average queue size at which marking becomes a
+ possibility.
+
+
+
+
+ max
+
+
+ At this average queue size, the marking
+ probability is maximal. Must be at least twice
+ min to prevent synchronous
+ retransmits, higher for low min.
+
+
+
+
+ probability
+
+
+ Maximum probability for marking, specified as a
+ floating point number from 0.0 to 1.0. Suggested values
+ are 0.01 or 0.02 (1 or 2%, respectively).
+
+
+
+
+ limit
+
+
+ Hard limit on the real (not average) queue size in
+ bytes. Further packets are dropped. Should be set higher
+ than
+ max+burst.
+ It is advised to set this a few times higher than
+ max. Shorewall requires that
+ max be at least twice
+ min.
+
+
+
+
+ burst
+
+
+ Used for determining how fast the average queue
+ size is influenced by the real queue size. Larger values
+ make the calculation more sluggish, allowing longer
+ bursts of traffic before marking starts. Real life
+ experiments support the following guide‐ line:
+ (min+min+max)/(3*avpkt).
+
+
+
+
+
+ avpkt
+
+
+ Optional. Specified in bytes. Used with burst to
+ determine the time constant for average queue size
+ calculations. 1000 is a good value and is the Shorewall
+ default.
+
+
+
+
+ bandwidth
+
+
+ Optional. This rate is used for calculating the
+ average queue size after some idle time. Should be set
+ to the bandwidth of your interface. Does not mean that
+ RED will shape for you!
+
+
+
+
+ ecn
+
+
+ RED can either 'mark' or 'drop'. Explicit
+ Congestion Notification allows RED to notify remote
+ hosts that their rate exceeds the amount of bandwidth
+ available. Non-ECN capable hosts can only be notified by
+ dropping a packet. If this parameter is specified,
+ packets which indicate that their hosts honor ECN will
+ only be marked and not dropped, unless the queue size
+ hits limit bytes. Needs a tc binary with RED support
+ compiled in. Recommended.
+
+
+
+
+
@@ -503,6 +626,8 @@
http://shorewall.net/configuration_file_basics.htm#Pairs
+ tc-hfsc (7)
+
shorewall(8), shorewall-accounting(5), shorewall-actions(5),
shorewall-blacklist(5), shorewall-hosts(5), shorewall_interfaces(5),
shorewall-ipsets(5), shorewall-maclist(5), shorewall-masq(5),
diff --git a/Shorewall/manpages/shorewall-tcdevices.xml b/Shorewall/manpages/shorewall-tcdevices.xml
index 125ac7b2f..36b1f8583 100644
--- a/Shorewall/manpages/shorewall-tcdevices.xml
+++ b/Shorewall/manpages/shorewall-tcdevices.xml
@@ -200,7 +200,8 @@
- Shorewall normally uses the
Hierarchical Token Bucket queuing discipline.
When is specified, the Hierarchical
- Fair Service Curves discipline is used instead.
+ Fair Service Curves discipline is used instead (see
+ tc-hfsc (7)).linklayer - Added in
Shorewall 4.5.6. Type of link (ethernet, atm, adsl). When specified,
@@ -276,6 +277,8 @@
See ALSO
+ tc-hfsc (7)
+
http://shorewall.net/traffic_shaping.htm
diff --git a/Shorewall6/manpages/shorewall6-tcclasses.xml b/Shorewall6/manpages/shorewall6-tcclasses.xml
index b63db67c1..6c15aa72e 100644
--- a/Shorewall6/manpages/shorewall6-tcclasses.xml
+++ b/Shorewall6/manpages/shorewall6-tcclasses.xml
@@ -171,7 +171,7 @@
RATE -
- rate[:dmax[:umax]]
+ {-|rate[:dmax[:umax]]}
The minimum bandwidth this class should get, when the traffic
@@ -181,11 +181,12 @@
class exceed the CEIL of the parent class, things don't work
well.
- When using the HFSC queuing discipline, leaf classes may
- specify dmax, the maximum delay in
- milliseconds that the first queued packet for this class should
- experience. May be expressed as an integer, optionally followed by
- 'ms' with no intervening white space (e.g., 10ms).
+ When using the HFSC queuing discipline, this column specify
+ the real-time (RT) service curve. leaf classes may specify
+ dmax, the maximum delay in milliseconds
+ that the first queued packet for this class should experience. May
+ be expressed as an integer, optionally followed by 'ms' with no
+ intervening white space (e.g., 10ms).HFSC leaf classes may also specify
umax, the largest packet expected in this
@@ -194,12 +195,18 @@
followed by 'b' with no intervening white space (e.g., 800b).
umax may only be given if
dmax is also given.
+
+ Beginning with Shorewall 4.5.6, HFSC classes may omit this
+ column (e.g, '-' in the column), provided that an
+ lsrate is specified (see CEIL below).
+ These rates are used to arbitrate between classes of the same
+ priority.CEIL -
- rate
+ [lsrate:]rateThe maximum bandwidth this class is allowed to use when the
@@ -210,6 +217,9 @@
here for setting the maximum bandwidth to the RATE of the parent
class, or the OUT-BANDWIDTH of the device if there is no parent
class.
+
+ Beginning with Shorewall 4.5.6, you can also specify an
+ lsrate (link sharing rate).
@@ -304,7 +314,7 @@
limited to 64 bytes because we want only packets WITHOUT
payload to match.
-
+ This option is only valid for ONE class per
@@ -381,6 +391,118 @@
assumed.
+
+
+ red=(redoption=value,
+ ...)
+
+
+ Added in Shorewall 4.5.6. When specified on a leaf
+ class, causes the class to use the red queuing discipline
+ rather than SFQ. See tc-red (8) for additional
+ information.
+
+ Allowable redoptions are:
+
+
+
+ min
+
+
+ Average queue size at which marking becomes a
+ possibility.
+
+
+
+
+ max
+
+
+ At this average queue size, the marking
+ probability is maximal. Must be at least twice
+ min to prevent synchronous
+ retransmits, higher for low min.
+
+
+
+
+ probability
+
+
+ Maximum probability for marking, specified as a
+ floating point number from 0.0 to 1.0. Suggested values
+ are 0.01 or 0.02 (1 or 2%, respectively).
+
+
+
+
+ limit
+
+
+ Hard limit on the real (not average) queue size in
+ bytes. Further packets are dropped. Should be set higher
+ than
+ max+burst.
+ It is advised to set this a few times higher than
+ max. Shorewall requires that
+ max be at least twice
+ min.
+
+
+
+
+ burst
+
+
+ Used for determining how fast the average queue
+ size is influenced by the real queue size. Larger values
+ make the calculation more sluggish, allowing longer
+ bursts of traffic before marking starts. Real life
+ experiments support the following guide‐ line:
+ (min+min+max)/(3*avpkt).
+
+
+
+
+ avpkt
+
+
+ Optional. Specified in bytes. Used with burst to
+ determine the time constant for average queue size
+ calculations. 1000 is a good value and is the Shorewall
+ default.
+
+
+
+
+ bandwidth
+
+
+ Optional. This rate is used for calculating the
+ average queue size after some idle time. Should be set
+ to the bandwidth of your interface. Does not mean that
+ RED will shape for you!
+
+
+
+
+ ecn
+
+
+ RED can either 'mark' or 'drop'. Explicit
+ Congestion Notification allows RED to notify remote
+ hosts that their rate exceeds the amount of bandwidth
+ available. Non-ECN capable hosts can only be notified by
+ dropping a packet. If this parameter is specified,
+ packets which indicate that their hosts honor ECN will
+ only be marked and not dropped, unless the queue size
+ hits limit bytes. Needs a tc binary with RED support
+ compiled in. Recommended.
+
+
+
+
+
@@ -448,6 +570,8 @@
See ALSO
+ tc-hfsc (7)
+
http://shorewall.net/traffic_shaping.htm
diff --git a/Shorewall6/manpages/shorewall6-tcdevices.xml b/Shorewall6/manpages/shorewall6-tcdevices.xml
index 8f0b0eb83..3dc2584a0 100644
--- a/Shorewall6/manpages/shorewall6-tcdevices.xml
+++ b/Shorewall6/manpages/shorewall6-tcdevices.xml
@@ -201,7 +201,8 @@
- Shorewall normally uses the
Hierarchical Token Bucket queuing discipline.
When is specified, the Hierarchical
- Fair Service Curves discipline is used instead.
+ Fair Service Curves discipline is used instead(see
+ tc-hfsc (7)).linklayer - Added in
Shorewall 4.5.6. Type of link (ethernet, atm, adsl). When specified,
@@ -278,6 +279,8 @@
See ALSO
+ tc-hfsc (7)
+
http://shorewall.net/traffic_shaping.htm
diff --git a/docs/traffic_shaping.xml b/docs/traffic_shaping.xml
index 7b0800e9e..fb466bc24 100644
--- a/docs/traffic_shaping.xml
+++ b/docs/traffic_shaping.xml
@@ -431,7 +431,7 @@
linklayer
- Added in Shorewall 4.5.6. Type of link (ethernet, atm,
+ Added in Shorewall 4.5.6. Type of link (ethernet, atm,
adsl). When specified, causes scheduler packet size
manipulation as described in tc-stab (8). When this option is
given, the following options may also be given after
@@ -792,6 +792,18 @@ ppp0 6000kbit 500kbit
number must be > 2 and less than 128. If
not specified, the value 127 is assumed
+
+
+ red=(redoption,...) - Added in
+ Shorewall 4.5.6. When specified on a leaf class, causes the
+ class to use the red queuing discipline rather than SFQ. See
+ tc-red (8) for additional information.
+
+ See shorewall-tcdevices
+ (5) for a description of the allowable
+ redoptions.
+