diff options
author | Seth Mos <seth.mos@xs4all.nl> | 2006-12-30 00:45:25 +0000 |
---|---|---|
committer | Seth Mos <seth.mos@xs4all.nl> | 2006-12-30 00:45:25 +0000 |
commit | 401452ec0cdf52246ce0c6623e97583f614576f9 (patch) | |
tree | add4578ddf1dc26e1e2d4be102d13b0d53389ad3 | |
parent | 1cea5083d5e51bb46509225c937f0114089af019 (diff) | |
download | pfsense-401452ec0cdf52246ce0c6623e97583f614576f9.zip pfsense-401452ec0cdf52246ce0c6623e97583f614576f9.tar.gz |
Merge in new (outbound) load balancing configuration code from HEAD.
* assign interfaces to pool instead of manual IP configuration
* Only show interfaces with a gateway
* Offer list of monitor IPs including interface gateways.
This code is tested for outbound load balancing on a carp cluster and
works for me (smos). The server side needs testing. Which I don't know
how to. Let's give it a run for a snapshot or 2.
-rw-r--r-- | etc/inc/filter.inc | 6 | ||||
-rw-r--r-- | etc/inc/vslb.inc | 10 | ||||
-rwxr-xr-x | etc/rc.newwanip | 6 | ||||
-rwxr-xr-x | usr/local/www/load_balancer_pool_edit.php | 264 | ||||
-rwxr-xr-x | usr/local/www/pool.js | 16 |
5 files changed, 254 insertions, 48 deletions
diff --git a/etc/inc/filter.inc b/etc/inc/filter.inc index 1163d7a..d53c21f 100644 --- a/etc/inc/filter.inc +++ b/etc/inc/filter.inc @@ -1410,13 +1410,13 @@ function generate_user_filter_rule($rule, $ngcounter) { foreach ($config['load_balancer']['lbpool'][$i]['servers'] as $lbsvr) { $lbsvr_split=split("\|", $lbsvr); if ($lbsvr_split[1] == $server) - $gateway = $lbsvr_split[0]; + /* deterimine interface gateway */ + $int = convert_friendly_interface_to_real_interface_name($lbsvr_split[0]); + $gateway = get_interface_gateway($int); } } if($foundlb == 1) $routeto .= ", "; - /* determine interface from gateway address */ - $int = guess_interface_from_ip($gateway); $routeto .= "( {$int} {$gateway} ) "; if($int == "") { $line = "# error resolving load balancing {$gateway}"; diff --git a/etc/inc/vslb.inc b/etc/inc/vslb.inc index dfd54f8..6dddff0 100644 --- a/etc/inc/vslb.inc +++ b/etc/inc/vslb.inc @@ -112,12 +112,12 @@ function slbd_configure() { $lbsvr_split=split("\|", $lbsvr); $svrtxt .= "\t:{$svrcnt}={$lbsvr_split[1]}:\\\n"; $svrcnt++; + /* Add static routes to the monitor IPs */ - $next_hop = exec_command("/sbin/route -n get {$lbsvr_split[1]} | /usr/bin/grep gateway |/usr/bin/awk '{ print \$2; };'"); - if ($next_hop != $lbsvr_split[0]) { - mwexec("/sbin/route delete -host {$lbsvr_split[1]} 1>/dev/null 2>&1"); - mwexec("/sbin/route add -host {$lbsvr_split[1]} {$lbsvr_split[0]} 1> /dev/null 2>&1"); - } + $int = convert_friendly_interface_to_real_interface_name($lbsvr_split[0]); + $gateway = get_interface_gateway($int); + mwexec("/sbin/route delete -host {$lbsvr_split[1]} 1>/dev/null 2>&1"); + mwexec("/sbin/route add -host {$lbsvr_split[1]} {$gateway} 1> /dev/null 2>&1"); } $slbdconf .= "\t:service-port=666:\\\n"; $slbdconf .= "\t:method=round-robin:\\\n"; diff --git a/etc/rc.newwanip b/etc/rc.newwanip index 90555a1..aa9b5ee 100755 --- a/etc/rc.newwanip +++ b/etc/rc.newwanip @@ -112,6 +112,12 @@ enable_rrd_graphing(); /* restart packages */ exec("/etc/rc.start_packages"); +/* reload slbd */ +/* if ($config['load_balancer']['lbpool']['type'] == "gateway") */ +slbd_configure(); +log_error("Configuring slbd"); + + return 0; ?>
\ No newline at end of file diff --git a/usr/local/www/load_balancer_pool_edit.php b/usr/local/www/load_balancer_pool_edit.php index 8baa151..2a1aa97 100755 --- a/usr/local/www/load_balancer_pool_edit.php +++ b/usr/local/www/load_balancer_pool_edit.php @@ -31,7 +31,7 @@ require("guiconfig.inc"); if (!is_array($config['load_balancer']['lbpool'])) { - $config['load_balancer']['lbpool'] = array(); + $config['load_balancer']['lbpool'] = array(); } $a_pool = &$config['load_balancer']['lbpool']; @@ -84,8 +84,8 @@ if ($_POST) { $input_errors[] = "{$svrent} is not a valid IP address."; } else { $split_ip = split("\|", $svrent); - if(!is_ipaddr($split_ip[0])) - $input_errors[] = "{$split_ip[0]} is not a valid IP address."; + /* if(!is_ipaddr($split_ip[0])) + $input_errors[] = "{$split_ip[0]} is not a valid IP address."; */ if(!is_ipaddr($split_ip[1])) $input_errors[] = "{$split_ip[1]} is not a valid IP address."; } @@ -99,12 +99,14 @@ if ($_POST) { for ($j = 1; isset ($config['interfaces']['opt' . $j]); $j++) { $ifdescrs['opt' . $j] = "opt" . $j; } - foreach($pconfig['servers'] as $svrent) { - $split_ip = split("\|", $svrent); - foreach($ifdescrs as $iface) { - if($config['interfaces'][$iface]['ipaddr'] <> "") - if($config['interfaces'][$iface]['ipaddr'] == $split_ip[0]) - $input_errors[] = "{$split_ip[0]} is currently being referenced by an interface ip address on {$iface}."; + if(is_array($pconfig['servers'])) { + foreach($pconfig['servers'] as $svrent) { + $split_ip = split("\|", $svrent); + foreach($ifdescrs as $iface) { + if($config['interfaces'][$iface]['ipaddr'] <> "") + if($config['interfaces'][$iface]['ipaddr'] == $split_ip[0]) + $input_errors[] = "{$split_ip[0]} is currently being referenced by an interface ip address on {$iface}."; + } } } } @@ -132,7 +134,7 @@ if ($_POST) { update_if_changed("port", $poolent['port'], $_POST['port']); update_if_changed("servers", $poolent['servers'], $_POST['servers']); update_if_changed("monitor", $poolent['monitor'], $_POST['monitor']); - + if (isset($id) && $a_pool[$id]) { /* modify all virtual servers with this name */ for ($i = 0; isset($config['load_balancer']['virtual_server'][$i]); $i++) { @@ -142,8 +144,7 @@ if ($_POST) { $a_pool[$id] = $poolent; } else $a_pool[] = $poolent; - - + if ($changecount > 0) { /* Mark pool dirty */ conf_mount_rw(); @@ -156,6 +157,116 @@ if ($_POST) { } } +function get_interface_info($ifdescr) { + + global $config, $linkinfo, $netstatrninfo; + + $ifinfo = array(); + + /* find out interface name */ + $ifinfo['hwif'] = $config['interfaces'][$ifdescr]['if']; + if ($ifdescr == "wan") + $ifinfo['if'] = get_real_wan_interface(); + else + $ifinfo['if'] = $ifinfo['hwif']; + + /* run netstat to determine link info */ + + unset($linkinfo); + exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo); + $linkinfo = preg_split("/\s+/", $linkinfo[1]); + if (preg_match("/\*$/", $linkinfo[0])) { + $ifinfo['status'] = "down"; + } else { + $ifinfo['status'] = "up"; + } + + /* PPPoE interface? -> get status from virtual interface */ + if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pppoe")) { + unset($linkinfo); + exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo); + $linkinfo = preg_split("/\s+/", $linkinfo[1]); + if (preg_match("/\*$/", $linkinfo[0])) { + $ifinfo['pppoelink'] = "down"; + } else { + /* get PPPoE link status for dial on demand */ + $ifconfiginfo = ""; + unset($ifconfiginfo); + exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo); + + $ifinfo['pppoelink'] = "up"; + + foreach ($ifconfiginfo as $ici) { + if (strpos($ici, 'LINK0') !== false) + $ifinfo['pppoelink'] = "down"; + } + } + } + + /* PPTP interface? -> get status from virtual interface */ + if (($ifdescr == "wan") && ($config['interfaces']['wan']['ipaddr'] == "pptp")) { + unset($linkinfo); + exec("/usr/bin/netstat -I " . $ifinfo['if'] . " -nWb -f link", $linkinfo); + $linkinfo = preg_split("/\s+/", $linkinfo[1]); + if (preg_match("/\*$/", $linkinfo[0])) { + $ifinfo['pptplink'] = "down"; + } else { + /* get PPTP link status for dial on demand */ + unset($ifconfiginfo); + exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo); + + $ifinfo['pptplink'] = "up"; + + foreach ($ifconfiginfo as $ici) { + if (strpos($ici, 'LINK0') !== false) + $ifinfo['pptplink'] = "down"; + } + } + } + + if ($ifinfo['status'] == "up") { + /* try to determine media with ifconfig */ + $matches = ""; + + if ($ifinfo['pppoelink'] != "down" && $ifinfo['pptplink'] != "down") { + /* try to determine IP address and netmask with ifconfig */ + unset($ifconfiginfo); + exec("/sbin/ifconfig " . $ifinfo['if'], $ifconfiginfo); + + foreach ($ifconfiginfo as $ici) { + if (preg_match("/inet (\S+)/", $ici, $matches)) { + $ifinfo['ipaddr'] = $matches[1]; + } + if (preg_match("/netmask (\S+)/", $ici, $matches)) { + if (preg_match("/^0x/", $matches[1])) + $ifinfo['subnet'] = long2ip(hexdec($matches[1])); + } + } + + if ($ifdescr == "wan") { + /* run netstat to determine the default gateway */ + unset($netstatrninfo); + exec("/usr/bin/netstat -rnf inet", $netstatrninfo); + + foreach ($netstatrninfo as $nsr) { + if (preg_match("/^default\s*(\S+)/", $nsr, $matches)) { + $ifinfo['gateway'] = $matches[1]; + } + } + } else { + /* deterimine interface gateway */ + $int = convert_friendly_interface_to_real_interface_name($ifdescr); + $gw = get_interface_gateway($int); + if($gw) + $ifinfo['gateway'] = $gw; + } + } + } + + return $ifinfo; +} + + $pgtitle = "Load Balancer: Pool: Edit"; include("head.inc"); @@ -165,40 +276,78 @@ include("head.inc"); <script type="text/javascript" language="javascript" src="pool.js"></script> <script language="javascript"> +function gateway_change() +{ + if (document.iform.gatewayip.options[document.iform.gatewayip.selectedIndex].value == "other") + { + //document.iform.monitorip.value = ""; + document.iform.monitorip.style.display = "block"; + } + else + { + document.iform.monitorip.value = document.iform.gatewayip.options[document.iform.gatewayip.selectedIndex].value; + document.iform.monitorip.style.display = "none"; + } + +} + function type_change(enable_change) { switch (document.iform.type.selectedIndex) { case 0: + // Server; //clearcombo(); + document.iform.gatewayip.disabled = 1; + document.iform.ipaddr.style.display = "block"; + document.iform.interface.style.display = "none"; document.iform.serversSelect.clear; document.iform.monitorip.disabled = 1; - monitorip_text = document.getElementById("monitorip_text"); + var monitorIpNote = document.getElementById("monitorIpNote"); + monitorIpNote.disabled = 1; + var monitorip_text = document.getElementById("monitorip_text"); monitorip_text.className = "vncell"; - monitorport_text = document.getElementById("monitorport_text"); + monitorip_text.disabled = 1; + var monitorport_text = document.getElementById("monitorport_text"); monitorport_text.className = "vncellreq"; - monitorport_desc = document.getElementById("monitorport_desc"); - monitorport_desc.innerHTML = "This is the port your servers are listening too."; + monitorport_text.disabled = 0; + document.getElementById("monitorport_desc").disabled = 0; document.iform.monitorip.value = ""; document.iform.port.disabled = 0; document.iform.monitor.selectedIndex = 0; document.iform.monitor.disabled = 0; + var interfacename_text = document.getElementById("interfacename_text"); + interfacename_text.innerHTML = "Server IP Address"; + var interfacename_desc = document.getElementById("interfacename_desc"); + interfacename_desc.innerHTML = "Enter the IP Address of the inbound load balanced server here."; break; case 1: + // Gateway; //clearcombo(); + document.iform.gatewayip.disabled = 0; + document.iform.ipaddr.style.display = "none"; + document.iform.interface.style.display = "block"; document.iform.monitorip.disabled = 0; document.iform.monitorip.value = ""; - monitorip_text = document.getElementById("monitorip_text"); + var monitorIpNote = document.getElementById("monitorIpNote"); + monitorIpNote.disabled = 0; + var monitorip_text = document.getElementById("monitorip_text"); monitorip_text.className = "vncellreq"; - monitorport_text = document.getElementById("monitorport_text"); + monitorip_text.disabled = 0; + var monitorport_text = document.getElementById("monitorport_text"); monitorport_text.className = "vncell"; - monitorport_desc = document.getElementById("monitorport_desc"); - monitorport_desc.innerHTML = ""; + monitorport_text.disabled = 1; + document.getElementById("monitorport_desc").disabled = 1; document.iform.port.disabled = 1; - /* set to ICMP */ + // set to ICMP document.iform.monitor.selectedIndex = 1; document.iform.monitor.disabled = 1; + var interfacename_text = document.getElementById("interfacename_text"); + interfacename_text.innerHTML = "Interface Name"; + var interfacename_desc = document.getElementById("interfacename_desc"); + interfacename_desc.innerHTML = "Select the Interface to be used for outbound load balancing."; break; } } + function clearcombo(){ for (var i=document.iform.serversSelect.options.length-1; i>=0; i--){ document.iform.serversSelect.options[i] = null; @@ -239,7 +388,8 @@ function clearcombo(){ <tr align="left"> <td width="22%" valign="top" id="monitorport_text" class="vncellreq">Port</td> <td width="78%" class="vtable" colspan="2"> - <input name="port" type="text" <?if(isset($pconfig['port'])) echo "value=\"{$pconfig['port']}\"";?> size="16" maxlength="16"><div id="monitorport_desc"></div> + <input name="port" type="text" <?if(isset($pconfig['port'])) echo "value=\"{$pconfig['port']}\"";?> size="16" maxlength="16"><br> + <div id="monitorport_desc">This is the port your servers are listening too.</div> </td> </tr> <tr align="left"> @@ -255,14 +405,56 @@ function clearcombo(){ <tr align="left"> <td width="22%" valign="top" id="monitorip_text" class="vncell">Monitor IP</td> <td width="78%" class="vtable" colspan="2"> - <input size="16" id="monitorip" name="monitorip" value="<?php echo $pconfig['monitorip']; ?>"> + <div style="float: none;"> + <select id="gatewayip" name="gatewayip" onchange="gateway_change();" style="float: left;"> +<?php + $interfaces = array('wan' => 'WAN'); + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) { + $interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr']; + } + foreach ($interfaces as $iface => $ifacename) { + $ifinfo = get_interface_info($iface); + if(isset($ifinfo['gateway'])) { ?> + <option value="<?=$ifinfo['gateway'];?>"><?=htmlspecialchars($ifacename);?>'s Gateway</option> +<?php } + } + $dns_servers = get_dns_servers(); + $iDns = 1; + foreach($dns_servers as $dns) { ?> + <option value="<?=$dns;?>">DNS Server <?=$iDns;?> (<?=$dns;?>)</option> +<?php $iDns++; + } + /* Would be really nice to actually ping to get these live each time, + as they mostly all support round-robin */?> + <option value="72.14.209.99">www.google.com</option> + <option value="209.191.93.52">www.yahoo.com</option> + <option value="69.147.83.33">www.freebsd.org</option> + <option value="other" selected>other</option> + </select> + <input size="16" id="monitorip" name="monitorip" value="<?php echo $pconfig['monitorip']; ?>" style="float: left;"> + </div><br><br> + <div id="monitorIpNote" style="float: none;">Note: Some gateways have ping capability disabled.</div> </td> - </tr> + </tr> <tr align="left"> - <td width="22%" valign="top" class="vncellreq">IP</td> - <td width="78%" class="vtable"> - <input name="ipaddr" type="text" size="16"> - <input class="formbtn" type="button" name="button1" value="Add to pool" onclick="AddServerToPool(document.iform);"> + <td width="22%" valign="top" class="vncellreq"><div id="interfacename_text"></div></td> + <td width="78%" class="vtable" colspan="2"> + <input name="ipaddr" type="text" size="16" style="float: left;"> + <select id="interface" name="interface" style="float: left; display: none;"> +<?php + $interfaces = array('wan' => 'WAN', 'lan' => 'LAN'); + for ($i = 1; isset($config['interfaces']['opt' . $i]); $i++) { + $interfaces['opt' . $i] = $config['interfaces']['opt' . $i]['descr']; + } + foreach ($interfaces as $iface => $ifacename) { + $ifinfo = get_interface_info($iface); + if(isset($ifinfo['gateway'])) { ?> + <option value="<?=$iface;?>"><?=htmlspecialchars($ifacename);?></option> +<?php } + } ?> + </select> + <input class="formbtn" type="button" name="button1" value="Add to pool" onclick="AddServerToPool(document.iform);"><br> + <div id="interfacename_desc"></div> </td> </tr> <tr> @@ -275,12 +467,12 @@ function clearcombo(){ <select id="serversSelect" name="servers[]" multiple="true" size="5"> <?php - if (is_array($pconfig['servers'])) { - foreach($pconfig['servers'] as $svrent) { - echo " <option value=\"{$svrent}\">{$svrent}</option>\n"; - } - } - echo "</select>"; +if (is_array($pconfig['servers'])) { + foreach($pconfig['servers'] as $svrent) { + echo " <option value=\"{$svrent}\">{$svrent}</option>\n"; + } +} +echo "</select>"; ?> </td> <td valign="top"> @@ -292,7 +484,8 @@ function clearcombo(){ </td> </tr> <tr align="left"> - <td colspan="2" align="center" align="left" valign="bottom"> + <td width="22%" valign="top"> </td> + <td width="78%"> <input name="Submit" type="submit" class="formbtn" value="Save" onClick="AllServers('serversSelect', true)"> <?php if (isset($id) && $a_pool[$id]): ?> <input name="id" type="hidden" value="<?=$id;?>"> @@ -304,6 +497,7 @@ function clearcombo(){ <br> <script language="javascript"> type_change(); + gateway_change(); </script> <?php include("fend.inc"); ?> </body> diff --git a/usr/local/www/pool.js b/usr/local/www/pool.js index e5eb8ee..07cb2aa 100755 --- a/usr/local/www/pool.js +++ b/usr/local/www/pool.js @@ -32,10 +32,16 @@ */ function AddServerToPool(form) { + var IntOrIp var theSel = form['servers[]']; - for(i=theSel.length-1; i>=0; i--) + if (form.type.selectedIndex == 0) + IntOrIp = form.ipaddr; + else + IntOrIp = form.interface; + + for(i = theSel.length - 1; i >= 0; i--) { - if(theSel.options[i].value == form.ipaddr.value) { + if(theSel.options[i].value == IntOrIp.value) { alert("IP Address Already In List"); return true; } @@ -48,11 +54,11 @@ function AddServerToPool(form) { } } - var ServerPort=form.ipaddr.value; + var ServerPort = IntOrIp.value; if(form.type.selectedIndex == 0) - var ServerPort=form.ipaddr.value; + var ServerPort = IntOrIp.value; else - var ServerPort=form.ipaddr.value + "|" + form.monitorip.value; + var ServerPort = IntOrIp.value + "|" + form.monitorip.value; form['servers[]'].options[form['servers[]'].options.length] = new Option(ServerPort,ServerPort); } |