diff --git a/src/etc/inc/interfaces.inc b/src/etc/inc/interfaces.inc index 4a7890006..017787c00 100644 --- a/src/etc/inc/interfaces.inc +++ b/src/etc/inc/interfaces.inc @@ -158,7 +158,15 @@ function interfaces_vlan_configure($verbose = false) } }); + /* requested vlan protocol, when the vlan has vlans as children, the 802.1ad (QinQ) proto should be used */ + $all_parents = []; foreach ($config['vlans']['vlan'] as $vlan) { + if (!in_array($vlan['vlanif'], $all_parents)) { + $all_parents[] = $vlan['vlanif']; + } + } + foreach ($config['vlans']['vlan'] as $vlan) { + $vlan['proto'] = !in_array($vlan['if'], $all_parents) ? '802.1q' : '802.1ad'; _interfaces_vlan_configure($vlan); } @@ -175,7 +183,7 @@ function _interfaces_vlan_configure($vlan) legacy_interface_destroy($vlan['vlanif']); legacy_interface_create('vlan', $vlan['vlanif']); - legacy_vlan_tag($vlan['vlanif'], $vlan['if'], $vlan['tag'], $vlan['pcp']); + legacy_vlan_tag($vlan['vlanif'], $vlan['if'], $vlan['tag'], $vlan['pcp'], $vlan['proto']); interfaces_bring_up($vlan['vlanif']); } diff --git a/src/etc/inc/interfaces.lib.inc b/src/etc/inc/interfaces.lib.inc index 60bc1c076..c9f030133 100644 --- a/src/etc/inc/interfaces.lib.inc +++ b/src/etc/inc/interfaces.lib.inc @@ -153,9 +153,9 @@ function legacy_bridge_member($ifs, $member) } } -function legacy_vlan_tag($ifs, $member, $tag, $pcp) +function legacy_vlan_tag($ifs, $member, $tag, $pcp, $proto) { - $cmd = '/sbin/ifconfig ' . escapeshellarg($ifs) . ' vlandev ' . escapeshellarg($member) . ' vlan ' . escapeshellarg($tag) . ' vlanpcp ' . escapeshellarg($pcp); + $cmd = '/sbin/ifconfig ' . escapeshellarg($ifs) . ' vlandev ' . escapeshellarg($member) . ' vlan ' . escapeshellarg($tag) . ' vlanpcp ' . escapeshellarg($pcp) . ' vlanproto ' . escapeshellarg($proto); exec($cmd . ' 2>&1', $out, $ret); if ($ret) { @@ -183,6 +183,17 @@ function legacy_vlan_pcp($ifs, $pcp) } } +function legacy_vlan_proto($ifs, $proto) +{ + $cmd = '/sbin/ifconfig ' . escapeshellarg($ifs) . ' vlanproto ' . escapeshellarg($proto); + + exec($cmd . ' 2>&1', $out, $ret); + if ($ret) { + log_error('The command `' . $cmd . '\' failed to execute'); + } +} + + function legacy_interface_stats($ifs = null) { if ($ifs != null) { diff --git a/src/opnsense/scripts/interfaces/reconfigure_vlans.php b/src/opnsense/scripts/interfaces/reconfigure_vlans.php index af837b132..13e45d108 100755 --- a/src/opnsense/scripts/interfaces/reconfigure_vlans.php +++ b/src/opnsense/scripts/interfaces/reconfigure_vlans.php @@ -34,6 +34,7 @@ require_once("util.inc"); // gather all relevant vlan's (new/updated and removed) into a single list $all_vlans = []; +$all_parents = []; $vfilename = "/tmp/.vlans.removed"; if (file_exists($vfilename) && filesize($vfilename) > 0) { $handle = fopen($vfilename, "r+"); @@ -53,6 +54,9 @@ if (file_exists($vfilename) && filesize($vfilename) > 0) { if (!empty($config['vlans']['vlan'])) { foreach ($config['vlans']['vlan'] as $vlan) { $all_vlans[$vlan['vlanif']] = $vlan; + if (!in_array($vlan['vlanif'], $all_parents)) { + $all_parents[] = $vlan['vlanif']; + } } } @@ -63,6 +67,7 @@ foreach (legacy_interfaces_details() as $ifname => $ifdetails) { } if (isset($all_vlans[$ifname])) { $vlan = $all_vlans[$ifname]; + $vlan['proto'] = !in_array($vlan['if'], $all_parents) ? '802.1q' : '802.1ad'; $cvlan = $ifdetails['vlan']; if (empty($vlan)) { // option 1: removed vlan @@ -72,10 +77,15 @@ foreach (legacy_interfaces_details() as $ifname => $ifdetails) { // XXX: legacy code used interface_configure() in these cases, but since you can't change a tag or a parent // for an assigned interface. At the moment that doesn't seem to make much sense legacy_vlan_remove_tag($vlan['vlanif']); - legacy_vlan_tag($vlan['vlanif'], $vlan['if'], $vlan['tag'], $vlan['pcp']); - } elseif ($vlan['pcp'] != $cvlan['pcp']) { - // option 3: only pcp changed, which can be altered instantly - legacy_vlan_pcp($vlan['vlanif'], $vlan['pcp']); + legacy_vlan_tag($vlan['vlanif'], $vlan['if'], $vlan['tag'], $vlan['pcp'], $vlan['proto']); + } elseif ($vlan['pcp'] != $cvlan['pcp'] || $vlan['proto'] != $cvlan['proto']) { + // option 3: only pcp or proto changed, which can be altered instantly + if ($vlan['pcp'] != $cvlan['pcp']) { + legacy_vlan_pcp($vlan['vlanif'], $vlan['pcp']); + } + if ($vlan['proto'] != $cvlan['proto']) { + legacy_vlan_proto($vlan['vlanif'], $vlan['proto']); + } } unset($all_vlans[$ifname]); } @@ -84,6 +94,7 @@ foreach (legacy_interfaces_details() as $ifname => $ifdetails) { // configure new foreach ($all_vlans as $ifname => $vlan) { if (!empty($vlan)) { + $vlan['proto'] = !in_array($vlan['if'], $all_parents) ? '802.1q' : '802.1ad'; _interfaces_vlan_configure($vlan); } }