mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-08 00:34:04 +01:00
Generate load rules at runtime rather than at compile time.
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
364420c4eb
commit
58bf562747
@ -474,6 +474,7 @@ sub generate_script_3($) {
|
||||
fi
|
||||
EOF
|
||||
pop_indent;
|
||||
setup_load_distribution;
|
||||
setup_forwarding( $family , 1 );
|
||||
push_indent;
|
||||
|
||||
@ -494,6 +495,10 @@ EOF
|
||||
set_state Started $config_dir
|
||||
else
|
||||
setup_netfilter
|
||||
EOF
|
||||
setup_load_distribution;
|
||||
|
||||
emit<<"EOF";
|
||||
conditionally_flush_conntrack
|
||||
EOF
|
||||
setup_forwarding( $family , 0 );
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
|
||||
#
|
||||
# (c) 2007,2008,2009,2010,2011 - Tom Eastep (teastep@shorewall.net)
|
||||
# (c) 2007,2008,2009,2010,2011,2012 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
@ -984,10 +984,10 @@ sub emitstd {
|
||||
#
|
||||
# Write passed message to the script with newline but no indentation.
|
||||
#
|
||||
sub emit_unindented( $ ) {
|
||||
sub emit_unindented( $;$ ) {
|
||||
assert( $script_enabled );
|
||||
|
||||
print $script "$_[0]\n" if $script;
|
||||
print $script $_[1] ? "$_[0]" : "$_[0]\n" if $script;
|
||||
}
|
||||
|
||||
#
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
|
||||
#
|
||||
# (c) 2007,2008,2009,2010,2011 - Tom Eastep (teastep@shorewall.net)
|
||||
# (c) 2007,2008,2009,2010,2011,2012 - Tom Eastep (teastep@shorewall.net)
|
||||
#
|
||||
# Complete documentation is available at http://shorewall.net
|
||||
#
|
||||
@ -308,8 +308,7 @@ sub setup_interface_proc( $ ) {
|
||||
}
|
||||
|
||||
if ( @emitted ) {
|
||||
emit( '',
|
||||
'if [ $COMMAND = enable ]; then' );
|
||||
emit( 'if [ $COMMAND = enable ]; then' );
|
||||
push_indent;
|
||||
emit "$_" for @emitted;
|
||||
pop_indent;
|
||||
|
@ -38,7 +38,9 @@ our @EXPORT = qw( process_providers
|
||||
setup_providers
|
||||
@routemarked_interfaces
|
||||
handle_stickiness
|
||||
handle_optional_interfaces );
|
||||
handle_optional_interfaces
|
||||
setup_load_distribution
|
||||
);
|
||||
our @EXPORT_OK = qw( initialize lookup_provider );
|
||||
our $VERSION = '4.4_24';
|
||||
|
||||
@ -54,11 +56,13 @@ my %routemarked_interfaces;
|
||||
our @routemarked_interfaces;
|
||||
my %provider_interfaces;
|
||||
my @load_providers;
|
||||
my @load_interfaces;
|
||||
|
||||
my $balancing;
|
||||
my $fallback;
|
||||
my $first_default_route;
|
||||
my $first_fallback_route;
|
||||
my $maxload;
|
||||
|
||||
my %providers;
|
||||
|
||||
@ -88,10 +92,12 @@ sub initialize( $ ) {
|
||||
@routemarked_interfaces = ();
|
||||
%provider_interfaces = ();
|
||||
@load_providers = ();
|
||||
@load_interfaces = ();
|
||||
$balancing = 0;
|
||||
$fallback = 0;
|
||||
$first_default_route = 1;
|
||||
$first_fallback_route = 1;
|
||||
$maxload = 0;
|
||||
|
||||
%providers = ( local => { number => LOCAL_TABLE , mark => 0 , optional => 0 ,routes => [], rules => [] } ,
|
||||
main => { number => MAIN_TABLE , mark => 0 , optional => 0 ,routes => [], rules => [] } ,
|
||||
@ -143,36 +149,21 @@ sub setup_route_marking() {
|
||||
add_ijump $chainref, j => 'CONNMARK', targetopts => "--save-mark --mask $mask", mark => "! --mark 0/$mask";
|
||||
}
|
||||
|
||||
if ( @load_providers ) {
|
||||
if ( @load_interfaces ) {
|
||||
my $chainref1 = new_chain 'mangle', 'balance';
|
||||
my @match;
|
||||
|
||||
add_ijump $chainref, g => $chainref1, mark => "--mark 0/$mask";
|
||||
add_ijump $mangle_table->{OUTPUT}, j => $chainref1, state_imatch( 'NEW,RELATED' ), mark => "--mark 0/$mask";
|
||||
|
||||
for my $providerref ( @load_providers ) {
|
||||
for my $physical ( @load_interfaces ) {
|
||||
|
||||
my $chainref2 = new_chain( 'mangle', load_chain( $providerref->{physical} ) );
|
||||
my $chainref2 = new_chain( 'mangle', load_chain( $physical ) );
|
||||
|
||||
dont_optimize $chainref2;
|
||||
dont_move $chainref2;
|
||||
dont_delete $chainref2;
|
||||
|
||||
if ( $providerref->{optional} ) {
|
||||
my $dev = chain_base $providerref->{physical};
|
||||
my $base = uc $dev;
|
||||
|
||||
add_commands( $chainref2, qq(if [ -n "\$SW_${base}_IS_USABLE" ]; then) );
|
||||
incr_cmd_level $chainref2;
|
||||
}
|
||||
|
||||
add_ijump( $chainref2, j => 'MARK', targetopts => "--set-mark $providerref->{mark}/$globals{PROVIDER_MASK}", statistic => "--mode random --probability $providerref->{load}" );
|
||||
|
||||
if ( $providerref->{optional} ) {
|
||||
add_commands( $chainref2 , 'fi' );
|
||||
decr_cmd_level( $chainref2 );
|
||||
}
|
||||
|
||||
add_ijump ( $chainref1,
|
||||
j => $chainref2 ,
|
||||
mark => "--mark 0/$mask" );
|
||||
@ -463,6 +454,7 @@ sub process_a_provider() {
|
||||
if ( $load ) {
|
||||
fatal_error q(The 'balance=<weight>' and 'load=<load-factor>' options are mutually exclusive) if $balance > 1;
|
||||
fatal_error q(The 'fallback=<weight>' and 'load=<load-factor>' options are mutually exclusive) if $default > 1;
|
||||
$maxload += $load;
|
||||
}
|
||||
|
||||
if ( $local ) {
|
||||
@ -556,7 +548,7 @@ sub process_a_provider() {
|
||||
push @routemarked_providers, $providers{$table};
|
||||
}
|
||||
|
||||
push @load_providers, $providers{$table} if $load;
|
||||
push @load_interfaces, $physical if $load;
|
||||
|
||||
push @providers, $table;
|
||||
|
||||
@ -618,12 +610,22 @@ sub add_a_provider( $$ ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( $load ) {
|
||||
emit( qq(echo $load > \${VARDIR}/${physical}_load) );
|
||||
emit( qq(echo "rm -f \${VARDIR}/${physical}_load" >> \${VARDIR}/undo_${table}_routing) );
|
||||
}
|
||||
emit( qq(echo $load > \${VARDIR}/${physical}_load) ) if $load;
|
||||
|
||||
emit( qq(echo "rm -f \${VARDIR}/${physical}.status" >> \${VARDIR}/undo_${table}_routing) );
|
||||
emit( '',
|
||||
"cat <<EOF >> \${VARDIR}/undo_${table}_routing" );
|
||||
|
||||
emit_unindented 'case \$COMMAND in';
|
||||
emit_unindented ' enable|disable)';
|
||||
emit_unindented ' ;;';
|
||||
emit_unindented ' *)';
|
||||
emit_unindented " rm -f \${VARDIR}/${physical}_load" if $load;
|
||||
emit_unindented <<"CEOF", 1;
|
||||
rm -f \${VARDIR}/${physical}.status
|
||||
;;
|
||||
esac
|
||||
EOF
|
||||
CEOF
|
||||
#
|
||||
# /proc for this interface
|
||||
#
|
||||
@ -734,8 +736,11 @@ sub add_a_provider( $$ ) {
|
||||
|
||||
my ( $tbl, $weight );
|
||||
|
||||
emit( qq(echo 0 > \${VARDIR}/${physical}.status) );
|
||||
|
||||
if ( $optional ) {
|
||||
emit( 'if [ $COMMAND = enable ]; then' );
|
||||
emit( '',
|
||||
'if [ $COMMAND = enable ]; then' );
|
||||
|
||||
push_indent;
|
||||
|
||||
@ -759,12 +764,13 @@ sub add_a_provider( $$ ) {
|
||||
emit qq(add_gateway "nexthop dev $physical $realm" ) . $tbl;
|
||||
}
|
||||
}
|
||||
|
||||
emit '';
|
||||
} else {
|
||||
$weight = 1;
|
||||
}
|
||||
|
||||
emit( 'run_iptables -t mangle -A ' . load_chain( $physical ) . ' -m statistic --mode random --probability ' . $load,
|
||||
'' ) if $load;
|
||||
emit ( "distribute_load $maxload @load_interfaces" ) if $load;
|
||||
|
||||
unless ( $shared ) {
|
||||
emit( "setup_${dev}_tc" ) if $tcdevices->{$interface};
|
||||
@ -775,8 +781,7 @@ sub add_a_provider( $$ ) {
|
||||
pop_indent;
|
||||
|
||||
emit( 'else' );
|
||||
emit( qq( echo 0 > \${VARDIR}/${physical}.status) ,
|
||||
qq( echo $weight > \${VARDIR}/${physical}_weight) ,
|
||||
emit( qq( echo $weight > \${VARDIR}/${physical}_weight) ,
|
||||
qq( progress_message " Provider $table ($number) Started"),
|
||||
qq(fi\n)
|
||||
);
|
||||
@ -791,7 +796,7 @@ sub add_a_provider( $$ ) {
|
||||
|
||||
push_indent;
|
||||
|
||||
emit( qq(echo 0 > \${VARDIR}/${physical}.status) );
|
||||
emit( qq(echo 1 > \${VARDIR}/${physical}.status) );
|
||||
|
||||
if ( $optional ) {
|
||||
if ( $shared ) {
|
||||
@ -851,8 +856,8 @@ sub add_a_provider( $$ ) {
|
||||
emit (". $undo",
|
||||
"> $undo" );
|
||||
|
||||
emit( '',
|
||||
'run_iptables -t mangle -X ' . load_chain( $physical ) ) if $load;
|
||||
emit ( '',
|
||||
"distribute_load $maxload @load_interfaces" ) if $load;
|
||||
|
||||
unless ( $shared ) {
|
||||
emit( '',
|
||||
@ -1223,7 +1228,7 @@ EOF
|
||||
emit ( " if [ -z \"`\$IP -$family route ls table $providerref->{number}`\" ]; then",
|
||||
" start_provider_$provider",
|
||||
' else',
|
||||
' startup_error "Interface $g_interface is already enabled"',
|
||||
" startup_error \"Interface $providerref->{physical} is already enabled\"",
|
||||
' fi',
|
||||
' ;;'
|
||||
);
|
||||
@ -1259,7 +1264,7 @@ EOF
|
||||
" if [ -n \"`\$IP -$family route ls table $providerref->{number}`\" ]; then",
|
||||
" stop_provider_$provider",
|
||||
' else',
|
||||
' startup_error "Interface $g_interface is already disabled"',
|
||||
" startup_error \"Interface $providerref->{physical} is already disabled\"",
|
||||
' fi',
|
||||
' ;;'
|
||||
) if $providerref->{optional};
|
||||
@ -1302,7 +1307,7 @@ sub setup_providers() {
|
||||
pop_indent;
|
||||
emit "fi\n";
|
||||
|
||||
setup_route_marking if @routemarked_interfaces || @load_providers;
|
||||
setup_route_marking if @routemarked_interfaces || @load_interfaces;
|
||||
} else {
|
||||
emit "\nif [ -z \"\$g_noroutes\" ]; then";
|
||||
|
||||
@ -1574,10 +1579,17 @@ sub handle_stickiness( $ ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( @routemarked_providers || @load_providers ) {
|
||||
if ( @routemarked_providers || @load_interfaces ) {
|
||||
delete_jumps $mangle_table->{PREROUTING}, $setstickyref unless @{$setstickyref->{rules}};
|
||||
delete_jumps $mangle_table->{OUTPUT}, $setstickoref unless @{$setstickoref->{rules}};
|
||||
}
|
||||
}
|
||||
|
||||
sub setup_load_distribution() {
|
||||
emit ( '',
|
||||
" distribute_load $maxload @load_interfaces" ,
|
||||
''
|
||||
) if @load_interfaces;
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -563,3 +563,52 @@ debug_restore_input() {
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
interface_up() {
|
||||
return $(cat ${VARDIR}/$1.status)
|
||||
}
|
||||
|
||||
distribute_load() {
|
||||
local interface
|
||||
local totalload
|
||||
local load
|
||||
local maxload
|
||||
|
||||
maxload=$1
|
||||
shift
|
||||
|
||||
totalload=0
|
||||
|
||||
for interface in $@; do
|
||||
if interface_up $interface; then
|
||||
load=$(cat ${VARDIR}/${interface}_load)
|
||||
eval ${interface}_load=$load
|
||||
totalload=$( bc <<EOF
|
||||
scale=8
|
||||
$totalload + $load
|
||||
EOF
|
||||
)
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $totalload ]; then
|
||||
for interface in $@; do
|
||||
qt $g_tool -t mangle -F ~$interface
|
||||
eval load=\$${interface}_load
|
||||
|
||||
if [ -n "$load" ]; then
|
||||
load=$(bc <<EOF
|
||||
scale=8
|
||||
( $load / $totalload ) * $maxload
|
||||
EOF
|
||||
)
|
||||
totalload=$(bc <<EOF
|
||||
scale=8
|
||||
$totalload - $load
|
||||
EOF
|
||||
)
|
||||
run_iptables -t mangle -A ~$interface -m statistic --mode random --probability $load
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
@ -1345,7 +1345,7 @@ shorewall 2 2 - eth0 192.168.1.254 track,balance=2,optional<
|
||||
10001: from all fwmark 0x200 lookup ISP2</programlisting>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section id="load">
|
||||
<title>An alternative form of balancing</title>
|
||||
|
||||
<para>Beginning with Shorewall 4.5.0, an alternative to the
|
||||
@ -1357,8 +1357,33 @@ shorewall 2 2 - eth0 192.168.1.254 track,balance=2,optional<
|
||||
<firstterm>Statistic Match</firstterm> capability in your iptables and
|
||||
kernel.</para>
|
||||
|
||||
<para>This method works when there are two links to the same ISP where
|
||||
both links have the same default gateway.</para>
|
||||
<para>This method works when there are multiple links to the same ISP
|
||||
where both links have the same default gateway.</para>
|
||||
|
||||
<para>The key features of this method are:</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>Providers to be balanced are given a <replaceable>load
|
||||
factor</replaceable> using the <option>load</option>= option in
|
||||
<ulink
|
||||
url="manpages/shorewall-providers.html">shorewall-providers</ulink>
|
||||
(5).</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>A load factor is a number in the range 0 < number <= 1
|
||||
and specifies the probability that any particular new connection
|
||||
will be assigned to the associated provider.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>When one of the interfaces is disabled or enabled, the load
|
||||
factors of the currently-available interfaces are adjusted so that
|
||||
the sum of these remaining load factors totals to the sum of all
|
||||
interfaces that specify <option>load</option>=.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>Here's an example that sends 1/3 of the connections through
|
||||
provider ComcastC and the rest through ComastB.</para>
|
||||
@ -1384,7 +1409,7 @@ ZONE_BITS=4
|
||||
<para><filename>/etc/shorewall/providers</filename>:</para>
|
||||
|
||||
<programlisting>#NAME NUMBER MARK DUPLICATE INTERFACE GATEWAY OPTIONS
|
||||
ComcastB 1 - - eth1 70.90.191.126 loose,balance
|
||||
ComcastB 1 - - eth1 70.90.191.126 loose,balance,load=0.66666667
|
||||
ComcastC 2 - - eth0 detect loose,fallback,load=0.33333333</programlisting>
|
||||
|
||||
<note>
|
||||
@ -1411,26 +1436,6 @@ ComcastC 2 - - eth0 detect loose,fallback,load=0.33
|
||||
<para>Priority = 1000 means that these rules will come before rules
|
||||
that select a provider based on marks.</para>
|
||||
</note>
|
||||
|
||||
<para>As shown in the above example, this technique works best when
|
||||
there are two providers.</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>One is configured with <option>balance</option> and the other
|
||||
with <option>fallback</option>.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>The provider with the <option>fallback</option> option is
|
||||
configured whith load=<replaceable>number</replaceable> where the
|
||||
<replaceable>number</replaceable> has a value in the range 0 <
|
||||
<replaceable>number</replaceable> <= 1. This
|
||||
<replaceable>number</replaceable> defines the probability that each
|
||||
new connection will be sent to the fallback provider and may have up
|
||||
to 8 digits to the right of the decimal point.</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
|
||||
<section id="LinkMonitor">
|
||||
|
Loading…
Reference in New Issue
Block a user