Interfaces/Other Types/VLAN - pass proto to vlan interface for 802.1ad (QinQ) interface types.

Currently this doesn't work (yet), likely needs https://reviews.freebsd.org/D35848 so vlanproto can be set after the interface creation phase (now it's only possible to set proto there).
If `ifconfig XXXX vlanproto 802.1ad` sets the property, we do need this code to make sure we set these on QinQ parent vlan tags. As a workaround we could pass proto in legacy_interface_create() as well to make this (only) work on boot, but looking at the upstream fix, this might be something easy to pull in the near future.

for https://github.com/opnsense/core/issues/5893
This commit is contained in:
Ad Schellevis 2022-09-03 15:31:25 +02:00
parent f6cebb421b
commit e1d8b471d0
3 changed files with 37 additions and 7 deletions

View File

@ -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']);
}

View File

@ -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) {

View File

@ -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);
}
}