mirror of
https://github.com/unraid/webgui.git
synced 2026-01-24 18:49:17 -06:00
Enhanced network settings - allow multiple interfaces in bridge
This commit is contained in:
@@ -65,8 +65,7 @@ refresh(); // automatically include new ethernet ports
|
||||
Array.prototype.dups = function(){return this.sort().filter(function(v,i,o){return i&&v===o[i-1]?v:0;}).length;}
|
||||
|
||||
function prepareSettings(form) {
|
||||
var bonding = form.BONDING !== undefined;
|
||||
if (bonding) {
|
||||
if (form.BONDING !== undefined) {
|
||||
var member = '';
|
||||
for (var i=0,item; item=form.BONDNICS.options[i]; i++) {
|
||||
if (item.selected) {
|
||||
@@ -79,8 +78,19 @@ function prepareSettings(form) {
|
||||
item.value = member;
|
||||
item.selected = true;
|
||||
item.disabled = false;
|
||||
form.BONDNICS.disabled = false;
|
||||
if (form.BONDING.value=='yes') form.BRNICS.value = form.BONDNAME.value;
|
||||
var member = '';
|
||||
for (var i=0,item; item=form.BRNICS.options[i]; i++) {
|
||||
if (item.selected) {
|
||||
if (member.length) member += ',';
|
||||
member += item.value;
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
item = form.BRNICS.options[0];
|
||||
item.value = form.BONDING.value=='yes' ? form.BONDNAME.value : member;
|
||||
item.selected = true;
|
||||
item.disabled = false;
|
||||
if (member.indexOf(',')>0) form.BRSTP.value = 'yes';
|
||||
}
|
||||
if (form.TYPE.value == 'access') {
|
||||
$(form).find('input[name^="VLANID:"]').prop('disabled',true);
|
||||
@@ -143,13 +153,27 @@ function checkDNSSettings(form) {
|
||||
function checkBondingSettings(form,ctrl) {
|
||||
var disabled = form.BONDING.value=='no';
|
||||
var mode = form.BONDING_MODE.value;
|
||||
if (ctrl) {
|
||||
form.BONDING_MODE.disabled = disabled;
|
||||
form.BONDNICS.disabled = disabled;
|
||||
$('#bond0').dropdownchecklist(disabled?'disable':'enable');
|
||||
if (ctrl>=0) {
|
||||
var me = ctrl==0 ? null : 'slow';
|
||||
if (disabled) {
|
||||
$('#bond-members').hide(me);
|
||||
} else {
|
||||
$('#bond-members').show(me);
|
||||
$('#bond0').dropdownchecklist('destroy').dropdownchecklist({emptyText:'None', width:131});
|
||||
}
|
||||
if (ctrl==1) checkBridgingSettings(form,1);
|
||||
}
|
||||
if (mode==1 || mode>4 || disabled) {$('#attention0').hide();} else {$('#attention0').show();}
|
||||
}
|
||||
function checkBridgingSettings(form,ctrl) {
|
||||
var me = ctrl==0 ? null : 'slow';
|
||||
if (form.BRIDGING.value=='yes' && form.BONDING.value=='no') {
|
||||
$('#bridge-members').show(me);
|
||||
$('#bridge0').dropdownchecklist('destroy').dropdownchecklist({emptyText:'None', width:131});
|
||||
} else {
|
||||
$('#bridge-members').hide(me);
|
||||
}
|
||||
}
|
||||
function checkNetworkAccess(form,port) {
|
||||
if (form.TYPE.value=='access') {
|
||||
$('.access-'+port).hide();
|
||||
@@ -190,23 +214,26 @@ function exitCode(form,key) {
|
||||
}
|
||||
}
|
||||
$(function() {
|
||||
var ctrl = "<span id='wait_eth0' class='status red' style='display:none;font-size:small;font-style:italic'>Please wait... configuring interfaces</span>";
|
||||
var form = document.eth0_settings;
|
||||
<?if ($tabbed && !$disabled):?>
|
||||
$('#tab1').bind({click:function(){
|
||||
$('#bond0').dropdownchecklist('destroy').dropdownchecklist({emptyText:'None', width:131});
|
||||
checkBondingSettings(form,true);
|
||||
}});
|
||||
<?endif;?>
|
||||
$('#bond0').dropdownchecklist({emptyText:'None', width:130});
|
||||
checkBondingSettings(form,true);
|
||||
$('#bridge0').dropdownchecklist({emptyText:'None', width:130});
|
||||
checkBondingSettings(form,0);
|
||||
checkBridgingSettings(form,0);
|
||||
checkNetworkAccess(form,'eth0');
|
||||
checkNetworkSettings(form);
|
||||
<?if ($disabled):?>
|
||||
disableForm(form);
|
||||
$('#bond0').dropdownchecklist('disable');
|
||||
$('#bridge0').dropdownchecklist('disable');
|
||||
<?else:?>
|
||||
checkDNSSettings(form);
|
||||
<?endif;?>
|
||||
<?if ($tabbed):?>
|
||||
$('.tabs').append(ctrl);
|
||||
<?else:?>
|
||||
$('div[id=title]').append(ctrl);
|
||||
<?endif;?>
|
||||
});
|
||||
</script>
|
||||
<form markdown="1" name="eth0_settings" method="POST" action="/update.php" target="progressFrame" onchange="exitCode(this,false)" onsubmit="return prepareSettings(this)">
|
||||
@@ -218,7 +245,6 @@ $(function() {
|
||||
<input type="hidden" name="BONDNAME" value="bond0">
|
||||
<input type="hidden" name="BONDING_MIIMON" value="100">
|
||||
<input type="hidden" name="BRNAME" value="">
|
||||
<input type="hidden" name="BRNICS" value="eth0">
|
||||
<input type="hidden" name="BRSTP" value="no">
|
||||
<input type="hidden" name="BRFD" value="0">
|
||||
<?foreach ($vlan_eth0 as $i):?>
|
||||
@@ -231,7 +257,7 @@ MAC address:
|
||||
> When tagging is enabled all VLANs on this interface will share the same hardware address.
|
||||
|
||||
Enable bonding:
|
||||
: <select name="BONDING" size="1" onchange="checkBondingSettings(this.form,true)">
|
||||
: <select name="BONDING" size="1" onchange="checkBondingSettings(this.form,1)">
|
||||
<?=mk_option($eth0['BONDING'], "no", "No");?>
|
||||
<?=mk_option($eth0['BONDING'], "yes", "Yes");?>
|
||||
</select>
|
||||
@@ -240,8 +266,9 @@ Enable bonding:
|
||||
> This can be used to improve the connection redundancy and/or throughput of the system.
|
||||
> Different bonding modes are supported (see below), but some modes require proper switch support.
|
||||
|
||||
<div id="bond-members" style="display:none" markdown="1">
|
||||
Bonding mode:
|
||||
: <select name="BONDING_MODE" size="1" onchange="checkBondingSettings(this.form,false)">
|
||||
: <select name="BONDING_MODE" size="1" onchange="checkBondingSettings(this.form,-1)">
|
||||
<?=mk_option($eth0['BONDING_MODE'], "0", "balance-rr (0)");?>
|
||||
<?=mk_option($eth0['BONDING_MODE'], "1", "active-backup (1)",isset($eth0['BONDING_MODE'])?'':'selected');?>
|
||||
<?=mk_option($eth0['BONDING_MODE'], "2", "balance-xor (2)");?>
|
||||
@@ -264,8 +291,9 @@ Bonding members:
|
||||
|
||||
> Select which interfaces are member of the *bonded* interface. By default eth0 is a member, while other interfaces are optional.
|
||||
|
||||
</div>
|
||||
Enable bridging:
|
||||
: <select name="BRIDGING" size="1">
|
||||
: <select name="BRIDGING" size="1" onchange="checkBridgingSettings(this.form,1)">
|
||||
<?=mk_option($eth0['BRIDGING'], "no", "No");?>
|
||||
<?=mk_option($eth0['BRIDGING'], "yes", "Yes");?>
|
||||
</select>
|
||||
@@ -273,6 +301,18 @@ Enable bridging:
|
||||
> Bridging is a feature which creates a virtual bridge and allows VMs to communicate directly with the physical Ethernet port.
|
||||
> Both bonding and bridging can be combined to let VMs communicate over a *bonded* interface.
|
||||
|
||||
<div id="bridge-members" style="display:none" markdown="1">
|
||||
Bridging members:
|
||||
: <select id="bridge0" name="BRNICS" size="1" multiple="multiple" style="display:none">
|
||||
<?=mk_option($eth0['BRNICS'],'eth0','Eth0','selected disabled')?>
|
||||
<?foreach ($ports as $port):?>
|
||||
<?=mk_option_check($eth0['BRNICS'],strtolower($port),$port)?>
|
||||
<?endforeach;?>
|
||||
</select>
|
||||
|
||||
> Select which interfaces are member of the *bridged* interface. By default eth0 is a member, while other interfaces are optional.
|
||||
|
||||
</div>
|
||||
Type of access:
|
||||
: <select name="TYPE" size="1" onchange="checkNetworkAccess(this.form,'eth0')">
|
||||
<?=mk_option($eth0['TYPE'], 'access', 'Untagged');?>
|
||||
@@ -407,5 +447,5 @@ Network mask:
|
||||
</script>
|
||||
|
||||
|
||||
: <input type="submit" value="Apply"><input type="button" value="Done" onclick="done()"><?=$disabled ? "VMs must be <b>Stopped</b> to change" : ""?>
|
||||
: <input type="submit" value="Apply" onclick="$('#wait_eth0').show()"><input type="button" value="Done" onclick="done()"><?=$disabled ? "VMs must be <b>Stopped</b> to change" : ""?>
|
||||
</form>
|
||||
|
||||
@@ -24,15 +24,37 @@ if (isset($ethX)) foreach ($ethX as $key => $val) if (substr($key,0,6)=='VLANID'
|
||||
|
||||
// get bond membership
|
||||
$bond_ethX = $eth0['BONDING']=='yes' ? in_array('ethX',explode(',',$eth0['BONDNICS'])) : false;
|
||||
|
||||
// get bridge membership
|
||||
$bridge_ethX = $eth0['BRIDGING']=='yes' ? in_array('ethX',explode(',',$eth0['BRNICS'])) : false;
|
||||
|
||||
if ($disabled)
|
||||
$locked = "VMs must be <b>STOPPED</b> to change";
|
||||
elseif ($bond_ethX)
|
||||
$locked = "Interface must be <i>removed</i> as <b>Bonding member</b> to change";
|
||||
elseif ($bridge_ethX)
|
||||
$locked = "Interface must be <i>removed</i> as <b>Bridging member</b> to change";
|
||||
else
|
||||
$locked = "";
|
||||
?>
|
||||
<script>
|
||||
<?if ($tabbed):?>
|
||||
var waitid = '#wait_eth0';
|
||||
<?else:?>
|
||||
var waitid = '#wait_ethX';
|
||||
<?endif;?>
|
||||
$(function() {
|
||||
var form = document.ethX_settings;
|
||||
checkNetworkAccess(form,'ethX');
|
||||
checkNetworkSettings(form);
|
||||
<?if ($disabled || $bond_ethX):?>
|
||||
<?if ($locked):?>
|
||||
disableForm(form);
|
||||
<?endif;?>
|
||||
<?if (!$tabbed):?>
|
||||
$('div[id=title]').each(function(){
|
||||
if ($(this).text().indexOf('Interface ethX')==0) $(this).append("<span id='wait_ethX' class='status red' style='display:none;font-size:small;font-style:italic'>Please wait... configuring interfaces</span>");
|
||||
});
|
||||
<?endif;?>
|
||||
});
|
||||
</script>
|
||||
<form markdown="1" name="ethX_settings" method="POST" action="/update.php" target="progressFrame" onchange="exitCode(this,false)" onsubmit="return prepareSettings(this)">
|
||||
@@ -161,5 +183,5 @@ Network mask:
|
||||
</script>
|
||||
|
||||
|
||||
: <input type="submit" value="Apply"><input type="button" value="Done" onclick="done()"><?=$bond_ethX ? "Interface must be <b>Unbonded</b> to change" : ($disabled ? "VMs must be <b>Stopped</b> to change" : "")?>
|
||||
: <input type="submit" value="Apply" onclick="$(waitid).show()"><input type="button" value="Done" onclick="done()"><?=$locked?>
|
||||
</form>
|
||||
|
||||
@@ -17,12 +17,20 @@ $run = $set != 'none';
|
||||
$ini = parse_ini_file('/var/local/emhttp/network.ini',true); ksort($ini,SORT_NATURAL);
|
||||
$cfg = '/boot/config/network.cfg';
|
||||
|
||||
function ifname($name) {
|
||||
global $old;
|
||||
for ($i=0; $i<$old['SYSNICS']; $i++) {
|
||||
$nics = $old['BONDNICS'][$i] ?: $old['BRNICS'][$i];
|
||||
if (strpos("$nics ","$name ")!==false) return $old['IFNAME'][$i];
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
if ($run && file_exists($cfg)) {
|
||||
$old = parse_ini_file($cfg);
|
||||
$i = preg_replace('/[^\d]/','',$set);
|
||||
if (isset($old['SYSNICS'])) {
|
||||
// new syntax
|
||||
$ifname = isset($old['IFNAME'][$i]) ? $old['IFNAME'][$i] : $set;
|
||||
$ifname = ifname($set);
|
||||
} else {
|
||||
// legacy syntax
|
||||
if ($i==0) $ifname = $old['BRIDGING']=='yes' ? $old['BRNAME'] : ($old['BONDING']=='yes' ? $old['BONDNAME'] : $set);
|
||||
@@ -33,25 +41,41 @@ if ($run && file_exists($cfg)) {
|
||||
// don't execute when only interface description has changed
|
||||
if ($run) exec("/etc/rc.d/rc.inet1 {$ifname}_stop >/dev/null");
|
||||
|
||||
if ($bonding = isset($ini['eth0']) && $ini['eth0']['BONDING']=='yes') {
|
||||
if ($bonding = $ini['eth0']['BONDING']=='yes') {
|
||||
$ini['eth0']['BONDNICS'] = str_replace(',',' ',$ini['eth0']['BONDNICS']);
|
||||
$members = explode(' ',trim(str_replace('eth0','',$ini['eth0']['BONDNICS'])));
|
||||
$bond0 = explode(' ',trim(str_replace('eth0','',$ini['eth0']['BONDNICS'])));
|
||||
// ensure additional NICs in bond are set free
|
||||
if ($run && $set=='eth0') foreach ($bond0 as $nic) {
|
||||
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
||||
exec("/etc/rc.d/rc.inet1 {$nic}_stop >/dev/null");
|
||||
}
|
||||
}
|
||||
|
||||
if ($bridging = $ini['eth0']['BRIDGING']=='yes') {
|
||||
$ini['eth0']['BRNICS'] = str_replace(',',' ',$ini['eth0']['BRNICS']);
|
||||
$br0 = explode(' ',trim(str_replace('eth0','',$ini['eth0']['BRNICS'])));
|
||||
// ensure additional NICs in bridge are set free
|
||||
if ($run && $set=='eth0') foreach ($br0 as $nic) {
|
||||
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
||||
exec("/etc/rc.d/rc.inet1 {$nic}_stop >/dev/null");
|
||||
}
|
||||
}
|
||||
|
||||
// create configuration file for all available interfaces
|
||||
$i = 0; $new = []; $new[] = "# Generated settings:";
|
||||
foreach ($ini as $name => $port) {
|
||||
if ($bonding && in_array($name,$members)) continue;
|
||||
$bridging = $port['BRIDGING']=='yes';
|
||||
if ($bonding && in_array($name,$bond0)) continue;
|
||||
if ($bridging && in_array($name,$br0)) continue;
|
||||
$bridge = $port['BRIDGING']=='yes';
|
||||
$trunk = $port['TYPE']=='trunk';
|
||||
$j = 0; $x0 = 0;
|
||||
$iface = $bridging ? $port['BRNAME'] : ($bonding && $name=='eth0' ? $port['BONDNAME'] : $name);
|
||||
$iface = $bridge ? $port['BRNAME'] : ($bonding && $name=='eth0' ? $port['BONDNAME'] : $name);
|
||||
$new[] = "IFNAME[$i]=\"$iface\"";
|
||||
if ($set==$name) $ifname = $iface;
|
||||
foreach ($port as $key => $val) {
|
||||
if (preg_match('/^(TYPE|BONDING$|BRIDGING)/',$key)) continue;
|
||||
if (!$bonding && preg_match('/^(BONDING_MODE|BONDING_MIIMON|BONDNICS|BONDNAME)/',$key)) continue;
|
||||
if (!$bridging && preg_match('/^(BRSTP|BRFD|BRNICS|BRNAME)/',$key)) continue;
|
||||
if (!$bridge && preg_match('/^(BRSTP|BRFD|BRNICS|BRNAME)/',$key)) continue;
|
||||
list($item,$x) = explode(':',$key,2);
|
||||
if ($trunk && $x>0 && preg_match('/^(VLANID|USE_DHCP|IPADDR|NETMASK|DESCRIPTION)/',$key)) {
|
||||
if ($x0 != $x) {$x0 = $x; $j++;}
|
||||
|
||||
Reference in New Issue
Block a user