mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-15 09:04:39 +00:00
Interfaces: Other Types: VLAN - Add stacked VLAN support (IEEE 802.1ad / QinQ) (#5607)
* Interfaces: Other Types: VLAN - Add stacked VLAN support (IEEE 802.1ad / QinQ) for https://github.com/opnsense/core/issues/5560 This commit adds QinQ to the new VLAN MVC implementation. o Implement new interface nameing, vlan_XXX for vlans and qinq_XXX for QinQ interfaces, to keep the names static its much easier to cope with changes. o For backwards compatibilty keep existing interface naming for old entries. o interfaces_vlan_configure() is only called during bootup and should enforce proper ordering in device creation (vlans first stacked later) o interface_vlan_configure() remove pcp tricker around 0 as the model will enforce zero's anyway o lock vlan when being used in QinQ interfaces
This commit is contained in:
parent
21643101eb
commit
99aacf7326
@ -182,7 +182,16 @@ function interfaces_vlan_configure($verbose = false)
|
||||
echo 'Configuring VLAN interfaces...';
|
||||
flush();
|
||||
}
|
||||
|
||||
// Handle QinQ dependencies by sorting list of vlans to create (first all vlans so we can stack QinQ on top)
|
||||
usort($config['vlans']['vlan'], function ($a, $b) {
|
||||
$aqinq = strpos($a['vlanif'], 'vlan') !== false ? 0 : 1 ;
|
||||
$bqinq = strpos($b['vlanif'], 'vlan') !== false ? 0 : 1 ;
|
||||
if ($aqinq === $bqinq) {
|
||||
return $a['vlanif'] <=> $b['vlanif'];
|
||||
} else {
|
||||
return $aqinq <=> $bqinq;
|
||||
}
|
||||
});
|
||||
foreach ($config['vlans']['vlan'] as $vlan) {
|
||||
interface_vlan_configure($vlan);
|
||||
}
|
||||
@ -196,12 +205,11 @@ function interface_vlan_configure($vlan)
|
||||
{
|
||||
interfaces_bring_up($vlan['if']); /* XXX overreach? */
|
||||
|
||||
/* XXX avoid destroy/create */
|
||||
/* destroy is a safety precaution, when confguring via api or gui this function should only be called on new vlans */
|
||||
legacy_interface_destroy($vlan['vlanif']);
|
||||
legacy_interface_create('vlan', $vlan['vlanif']);
|
||||
|
||||
$pcp = isset($vlan['pcp']) ? $vlan['pcp'] : 0;
|
||||
legacy_vlan_tag($vlan['vlanif'], $vlan['if'], $vlan['tag'], $pcp);
|
||||
legacy_vlan_tag($vlan['vlanif'], $vlan['if'], $vlan['tag'], $vlan['pcp']);
|
||||
|
||||
interfaces_bring_up($vlan['vlanif']);
|
||||
}
|
||||
|
||||
@ -38,10 +38,28 @@ class VlanSettingsController extends ApiMutableModelControllerBase
|
||||
protected static $internalModelName = 'vlan';
|
||||
protected static $internalModelClass = 'OPNsense\Interfaces\Vlan';
|
||||
|
||||
private function generateVlanIfName()
|
||||
private function generateVlanIfName($current=null)
|
||||
{
|
||||
$tmp = $this->request->getPost("vlan");
|
||||
return "{$tmp['if']}_vlan{$tmp['tag']}";
|
||||
$prefix = (strpos($tmp['if'], 'vlan') === false ? "vlan" : "qinq");
|
||||
if ($current != null && (string)$current->vlanif == "{$tmp['if']}_vlan{$tmp['tag']}") {
|
||||
// keep legacy naming
|
||||
return "{$tmp['if']}_vlan{$tmp['tag']}";
|
||||
} elseif ($current != null && strpos((string)$current->vlanif, '_vlan') === false &&
|
||||
strpos((string)$current->vlanif, $prefix) === 0
|
||||
) {
|
||||
// new naming convention and same type, name stays the same
|
||||
return (string)$current->vlanif;
|
||||
} else {
|
||||
// autonumber new
|
||||
$ifid = 0;
|
||||
foreach ($this->getModel()->vlan->iterateItems() as $node) {
|
||||
if (strpos((string)$node->vlanif . "_", $prefix) === 0) {
|
||||
$ifid = max($ifid, (int)explode("_", (string)$node->vlanif)[1]);
|
||||
}
|
||||
}
|
||||
return $prefix . "_" . ($ifid+1);
|
||||
}
|
||||
}
|
||||
|
||||
private function interfaceAssigned($if)
|
||||
@ -66,8 +84,23 @@ class VlanSettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
$node = $this->getModel()->getNodeByReference('vlan.' . $uuid);
|
||||
$old_vlanif = $node != null ? (string)$node->vlanif : null;
|
||||
$new_vlanif = $this->generateVlanIfName();
|
||||
if ($old_vlanif != null && $old_vlanif != $new_vlanif && $this->interfaceAssigned($old_vlanif)) {
|
||||
$new_vlanif = $this->generateVlanIfName($node);
|
||||
$children = 0;
|
||||
foreach ($this->getModel()->vlan->iterateItems() as $node) {
|
||||
if ((string)$node->if == $old_vlanif) {
|
||||
$children++;
|
||||
}
|
||||
}
|
||||
if ($old_vlanif != null && $old_vlanif != $new_vlanif && $children > 0) {
|
||||
$result = [
|
||||
"result" => "failed",
|
||||
"validations" => [
|
||||
"vlan.vlanif" => gettext("This VLAN cannot be deleted because it is used in QinQ interfaces.")
|
||||
]
|
||||
];
|
||||
} elseif ($old_vlanif != null && $old_vlanif != $new_vlanif && $this->interfaceAssigned($old_vlanif)) {
|
||||
// Reassignment is only an issue when naming changes. These additional validations only apply
|
||||
// for legacy interface nameing (e.g. <interface>_vlan_<tag>) and type changes vlan verses qinq.
|
||||
$tmp = $this->request->getPost("vlan");
|
||||
if ($tmp['tag'] != (string)$node->tag) {
|
||||
$result = [
|
||||
@ -110,7 +143,15 @@ class VlanSettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
$node = $this->getModel()->getNodeByReference('vlan.' . $uuid);
|
||||
$old_vlanif = $node != null ? (string)$node->vlanif : null;
|
||||
if ($old_vlanif != null && $this->interfaceAssigned($old_vlanif)) {
|
||||
$children = 0;
|
||||
foreach ($this->getModel()->vlan->iterateItems() as $node) {
|
||||
if ((string)$node->if == $old_vlanif) {
|
||||
$children++;
|
||||
}
|
||||
}
|
||||
if ($children > 0) {
|
||||
throw new UserException(gettext("This VLAN cannot be deleted because it is used in QinQ interfaces."));
|
||||
} elseif ($old_vlanif != null && $this->interfaceAssigned($old_vlanif)) {
|
||||
throw new UserException(gettext("This VLAN cannot be deleted because it is assigned as an interface."));
|
||||
} else {
|
||||
$result = $this->delBase("vlan", $uuid);
|
||||
|
||||
@ -52,9 +52,7 @@ class VlanInterfaceField extends BaseListField
|
||||
$ifconfig = json_decode((new Backend())->configdRun('interface list ifconfig'), true);
|
||||
if (!empty($ifconfig)) {
|
||||
foreach ($ifconfig as $ifname => $details) {
|
||||
// XXX: skip same interface types as legacy, may need to revise later
|
||||
if (
|
||||
strpos($ifname, "_vlan") > 1 || strpos($ifname, "lo") === 0 || strpos($ifname, "enc") === 0 ||
|
||||
if (strpos($ifname, "qinq") === 0 || strpos($ifname, "lo") === 0 || strpos($ifname, "enc") === 0 ||
|
||||
strpos($ifname, "pflog") === 0 || strpos($ifname, "pfsync") === 0 ||
|
||||
strpos($ifname, "bridge") === 0 ||
|
||||
strpos($ifname, "gre") === 0 || strpos($ifname, "gif") === 0 || strpos($ifname, "ipsec") === 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user