mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 08:09:41 +00:00
Interfaces: LAGG: migrate to MVC closes https://github.com/opnsense/core/issues/6384
Migrate ui to MVC, wrap model around existing configuration area to remain backward compatibility. To avoid laggs configured via console not being reachable from the gui, add a uuid to it.
This commit is contained in:
parent
1ccb2c9430
commit
57077b83f5
10
plist
10
plist
@ -378,14 +378,17 @@
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/IPsec/forms/dialogRemote.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/IPsec/forms/dialogSPD.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/IPsec/forms/dialogVTI.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/LaggSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/LoopbackSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VipSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VlanSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/Api/VxlanSettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/LaggController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/LoopbackController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VipController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VlanController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/VxlanController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogLagg.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogLoopback.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogVip.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Interfaces/forms/dialogVlan.xml
|
||||
@ -657,9 +660,12 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/IPsec/Swanctl.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/ACL/ACL.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/LaggInterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/VipInterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/VipNetworkField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/FieldTypes/VlanInterfaceField.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Lagg.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Lagg.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Loopback.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Loopback.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Interfaces/Menu/Menu.xml
|
||||
@ -764,6 +770,7 @@
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/IPsec/spd.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/IPsec/tunnels.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/IPsec/vti.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/lagg.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/loopback.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vip.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Interface/vlan.volt
|
||||
@ -959,6 +966,7 @@
|
||||
/usr/local/opnsense/scripts/interfaces/ppp-linkup.sh
|
||||
/usr/local/opnsense/scripts/interfaces/ppp-rename.sh
|
||||
/usr/local/opnsense/scripts/interfaces/ppp-uptime.sh
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_laggs.php
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_vips.php
|
||||
/usr/local/opnsense/scripts/interfaces/reconfigure_vlans.php
|
||||
/usr/local/opnsense/scripts/interfaces/rtsold_resolvconf.sh
|
||||
@ -2002,8 +2010,6 @@
|
||||
/usr/local/www/interfaces_gif_edit.php
|
||||
/usr/local/www/interfaces_gre.php
|
||||
/usr/local/www/interfaces_gre_edit.php
|
||||
/usr/local/www/interfaces_lagg.php
|
||||
/usr/local/www/interfaces_lagg_edit.php
|
||||
/usr/local/www/interfaces_ppps.php
|
||||
/usr/local/www/interfaces_ppps_edit.php
|
||||
/usr/local/www/interfaces_wireless.php
|
||||
|
||||
@ -538,6 +538,7 @@ EOD;
|
||||
|
||||
while (1) {
|
||||
$lagg = [];
|
||||
$lagg['@attributes'] = ['uuid' => generate_uuid()];
|
||||
|
||||
echo "\nLAGG-capable interfaces:\n\n";
|
||||
|
||||
|
||||
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Interfaces\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use OPNsense\Base\UserException;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Core\Config;
|
||||
|
||||
/**
|
||||
* @package OPNsense\Interfaces
|
||||
*/
|
||||
class LaggSettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'lagg';
|
||||
protected static $internalModelClass = 'OPNsense\Interfaces\Lagg';
|
||||
|
||||
|
||||
/**
|
||||
* write updated or removed laggif to temp
|
||||
*/
|
||||
private function stashUpdate($laggif)
|
||||
{
|
||||
file_put_contents("/tmp/.lagg.todo", "{$laggif}\n", FILE_APPEND | LOCK_EX);
|
||||
chmod("/tmp/.lagg.todo", 0750);
|
||||
}
|
||||
|
||||
/**
|
||||
* search laggs
|
||||
* @return array search results
|
||||
*/
|
||||
public function searchItemAction()
|
||||
{
|
||||
return $this->searchBase("lagg", ['laggif', 'descr', 'members', 'proto'], "descr");
|
||||
}
|
||||
|
||||
/**
|
||||
* Update lagg with given properties
|
||||
* @param string $uuid internal id
|
||||
* @return array save result + validation output
|
||||
*/
|
||||
public function setItemAction($uuid)
|
||||
{
|
||||
$node = $this->getModel()->getNodeByReference('lagg.' . $uuid);
|
||||
$overlay = null;
|
||||
if (!empty($node)) {
|
||||
// not allowed to change lagg interface name
|
||||
$overlay['laggif'] = (string)$node->laggif;
|
||||
}
|
||||
|
||||
$result = $this->setBase("lagg", "lagg", $uuid, $overlay);
|
||||
if ($result['result'] != 'failed') {
|
||||
$this->stashUpdate($overlay !== null ? $overlay['laggif'] : $this->request->get('lagg')['laggif']);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new lagg and set with attributes from post
|
||||
* @return array save result + validation output
|
||||
*/
|
||||
public function addItemAction()
|
||||
{
|
||||
Config::getInstance()->lock();
|
||||
$overlay = [];
|
||||
$ifnames = [];
|
||||
foreach ($this->getModel()->lagg->iterateItems() as $node) {
|
||||
$ifnames[] = (string)$node->laggif;
|
||||
}
|
||||
for ($i=0; true ; ++$i) {
|
||||
$laggif = sprintf('lagg%d', $i);
|
||||
if (!in_array($laggif, $ifnames)) {
|
||||
$overlay['laggif'] = $laggif;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$result = $this->addBase("lagg", "lagg", $overlay);
|
||||
if ($result['result'] != 'failed') {
|
||||
$this->stashUpdate($overlay['laggif']);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve lagg settings or return defaults for new one
|
||||
* @param $uuid item unique id
|
||||
* @return array lagg content
|
||||
*/
|
||||
public function getItemAction($uuid = null)
|
||||
{
|
||||
return $this->getBase("lagg", "lagg", $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete lagg by uuid
|
||||
* @param string $uuid internal id
|
||||
* @return array save status
|
||||
*/
|
||||
public function delItemAction($uuid)
|
||||
{
|
||||
Config::getInstance()->lock();
|
||||
$node = $this->getModel()->getNodeByReference('lagg.' . $uuid);
|
||||
$laggif = $node != null ? (string)$node->laggif : null;
|
||||
$uses = [];
|
||||
$cfg = Config::getInstance()->object();
|
||||
foreach ($cfg->interfaces->children() as $key => $value) {
|
||||
if ((string)$value->if == $laggif) {
|
||||
$uses['interfaces.'.$key] = !empty($value->descr) ? (string)$value->descr : $key;
|
||||
}
|
||||
}
|
||||
if (isset($cfg->vlans) && isset($cfg->vlans->vlan)) {
|
||||
foreach ($cfg->vlans->children() as $vlan) {
|
||||
if ((string)$vlan->if == $laggif) {
|
||||
$uses[(string)$vlan->vlanif] = !empty($vlan->descr) ? (string)$vlan->descr : $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($uses)) {
|
||||
$message = "";
|
||||
foreach ($uses as $key => $value) {
|
||||
$message .= htmlspecialchars(sprintf("\n[%s] %s", $key, $value), ENT_NOQUOTES | ENT_HTML401);
|
||||
}
|
||||
$message = sprintf(gettext("Cannot delete lagg. Currently in use by %s"), $message);
|
||||
throw new \OPNsense\Base\UserException($message, gettext("Lagg in use"));
|
||||
}
|
||||
$result = $this->delBase("lagg", $uuid);
|
||||
if ($result['result'] != 'failed' && !empty($laggif)) {
|
||||
$this->stashUpdate($laggif);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* reconfigure laggs
|
||||
*/
|
||||
public function reconfigureAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
(new Backend())->configdRun("interface lagg configure");
|
||||
return array("status" => "ok");
|
||||
} else {
|
||||
return array("status" => "failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Interfaces;
|
||||
|
||||
use OPNsense\Base\IndexController;
|
||||
|
||||
/**
|
||||
* @package OPNsense\Interfaces
|
||||
*/
|
||||
class LaggController extends IndexController
|
||||
{
|
||||
public function indexAction($selected = null)
|
||||
{
|
||||
$this->view->formDialogEdit = $this->getForm("dialogLagg");
|
||||
$this->view->pick('OPNsense/Interface/lagg');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>lagg.laggif</id>
|
||||
<label>Device</label>
|
||||
<type>info</type>
|
||||
<help></help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.members</id>
|
||||
<label>Parent</label>
|
||||
<type>select_multiple</type>
|
||||
<help>Choose the members that will be used for the link aggregation</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.proto</id>
|
||||
<label>Proto</label>
|
||||
<type>dropdown</type>
|
||||
<help>The protocol to use, please refer to the documentation for a detailed explanation of the various types available</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.lacp_fast_timeout</id>
|
||||
<label>Fast timeout</label>
|
||||
<type>checkbox</type>
|
||||
<style>proto proto_lacp</style>
|
||||
<help>Enable lacp fast-timeout on the interface.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.use_flowid</id>
|
||||
<label>Use flowid</label>
|
||||
<type>dropdown</type>
|
||||
<style>selectpicker proto proto_lacp proto_loadbalance</style>
|
||||
<help>Use the RSS hash from the network card if available, otherwise a hash is locally calculated. The default depends on the system tunable in net.link.lagg.default_use_flowid.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.lagghash</id>
|
||||
<label>Hash Layers</label>
|
||||
<type>select_multiple</type>
|
||||
<style>selectpicker proto proto_lacp proto_loadbalance</style>
|
||||
<help>Set the packet layers to hash for aggregation protocols which load balance.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.lacp_strict</id>
|
||||
<label>Use strict</label>
|
||||
<type>dropdown</type>
|
||||
<style>selectpicker proto proto_lacp</style>
|
||||
<help>Enable lacp strict compliance on the interface. The default depends on the system tunable in net.link.lagg.lacp.default_strict_mode.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.mtu</id>
|
||||
<label>MTU</label>
|
||||
<type>text</type>
|
||||
<help>If you leave this field blank, the smallest mtu of this laggs children will be used.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>lagg.descr</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
<help>You may enter a description here for your reference (not parsed).</help>
|
||||
</field>
|
||||
</form>
|
||||
@ -389,18 +389,6 @@
|
||||
<pattern>api/firewall/group/*</pattern>
|
||||
</patterns>
|
||||
</page-interfaces-groups-edit>
|
||||
<page-interfaces-lagg-edit>
|
||||
<name>Interfaces: LAGG: Edit</name>
|
||||
<patterns>
|
||||
<pattern>interfaces_lagg_edit.php*</pattern>
|
||||
</patterns>
|
||||
</page-interfaces-lagg-edit>
|
||||
<page-interfaces-lagg>
|
||||
<name>Interfaces: LAGG</name>
|
||||
<patterns>
|
||||
<pattern>interfaces_lagg.php*</pattern>
|
||||
</patterns>
|
||||
</page-interfaces-lagg>
|
||||
<page-interfaces-ppps>
|
||||
<name>Interfaces: PPPs</name>
|
||||
<patterns>
|
||||
|
||||
@ -127,9 +127,6 @@
|
||||
<GRE url="/interfaces_gre.php">
|
||||
<Edit url="/interfaces_gre_edit.php*" visibility="hidden"/>
|
||||
</GRE>
|
||||
<LAGG url="/interfaces_lagg.php">
|
||||
<Edit url="/interfaces_lagg_edit.php*" visibility="hidden"/>
|
||||
</LAGG>
|
||||
</Types>
|
||||
<Diagnostics order="970" cssClass="fa fa-medkit fa-fw">
|
||||
<DNSLookup VisibleName="DNS Lookup" url="/ui/diagnostics/dns_diagnostics"/>
|
||||
|
||||
@ -36,4 +36,11 @@
|
||||
<pattern>api/interfaces/vlan_settings/*</pattern>
|
||||
</patterns>
|
||||
</page-interfaces-vlan-edit>
|
||||
<page-interfaces-lagg-edit>
|
||||
<name>Interfaces: LAGG: Edit</name>
|
||||
<patterns>
|
||||
<pattern>ui/interfaces/lagg</pattern>
|
||||
<pattern>api/interfaces/lagg_settings/*</pattern>
|
||||
</patterns>
|
||||
</page-interfaces-lagg-edit>
|
||||
</acl>
|
||||
|
||||
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Interfaces\FieldTypes;
|
||||
|
||||
use OPNsense\Base\FieldTypes\BaseListField;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Core\Backend;
|
||||
|
||||
|
||||
class LaggInterfaceField extends BaseListField
|
||||
{
|
||||
private static $parent_interfaces = null;
|
||||
|
||||
protected function actionPostLoadingEvent()
|
||||
{
|
||||
if (self::$parent_interfaces === null) {
|
||||
self::$parent_interfaces = [];
|
||||
$skip = [];
|
||||
foreach (Config::getInstance()->object()->interfaces->children() as $ifname => $node) {
|
||||
if (!empty((string)$node->if)) {
|
||||
$skip[] = (string)$node->if;
|
||||
}
|
||||
}
|
||||
$itfs = json_decode((new Backend())->configdRun("interface list ifconfig") ?? '', true) ?? [];
|
||||
foreach ($itfs as $ifname => $ifinfo) {
|
||||
if (in_array($ifname, $skip) || !$ifinfo['is_physical']) {
|
||||
continue;
|
||||
}
|
||||
self::$parent_interfaces[$ifname] = sprintf("%s (%s)", $ifname, $ifinfo['macaddr'] ?? '');
|
||||
}
|
||||
}
|
||||
$this->internalOptionList = self::$parent_interfaces;
|
||||
return parent::actionPostLoadingEvent();
|
||||
}
|
||||
}
|
||||
86
src/opnsense/mvc/app/models/OPNsense/Interfaces/Lagg.php
Normal file
86
src/opnsense/mvc/app/models/OPNsense/Interfaces/Lagg.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Interfaces;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
use Phalcon\Messages\Message;
|
||||
|
||||
|
||||
/**
|
||||
* Class Lagg
|
||||
* @package OPNsense\Interfaces
|
||||
*/
|
||||
class Lagg extends BaseModel
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function performValidation($validateFullModel = false)
|
||||
{
|
||||
$messages = parent::performValidation($validateFullModel);
|
||||
// validate members are uniquely assigned to a single lagg
|
||||
$members = [];
|
||||
foreach ($this->getFlatNodes() as $key => $node) {
|
||||
if ($node->getInternalXMLTagName() == 'members') {
|
||||
foreach (explode(',', (string)$node) as $intf) {
|
||||
if (!isset($members[$intf])) {
|
||||
$members[$intf] = [];
|
||||
}
|
||||
$members[$intf][] = $node->getParentNode()->getAttributes()['uuid'];
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($this->getFlatNodes() as $key => $node) {
|
||||
if ($validateFullModel || $node->isFieldChanged()) {
|
||||
if ($node->getParentNode()->getInternalXMLTagName() === 'lagg') {
|
||||
$uuid = $node->getParentNode()->getAttributes()['uuid'];
|
||||
if ($node->getInternalXMLTagName() == 'members') {
|
||||
$tmp = [];
|
||||
foreach (explode(',', (string)$node) as $intf) {
|
||||
if (!empty($members[$intf]) && count($members[$intf]) > 1) {
|
||||
$tmp[] = $intf;
|
||||
}
|
||||
}
|
||||
if (!empty($tmp)) {
|
||||
$messages->appendMessage(
|
||||
new Message(
|
||||
sprintf(gettext('Members %s are already used in other laggs.'), implode(',', $tmp)),
|
||||
$key
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
71
src/opnsense/mvc/app/models/OPNsense/Interfaces/Lagg.xml
Normal file
71
src/opnsense/mvc/app/models/OPNsense/Interfaces/Lagg.xml
Normal file
@ -0,0 +1,71 @@
|
||||
<model>
|
||||
<mount>/laggs</mount>
|
||||
<version>1.0.0</version>
|
||||
<description>Lagg interfaces</description>
|
||||
<items>
|
||||
<lagg type="ArrayField">
|
||||
<laggif type="TextField">
|
||||
<Required>Y</Required>
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>Lagg already exists!</ValidationMessage>
|
||||
<type>UniqueConstraint</type>
|
||||
</check001>
|
||||
</Constraints>
|
||||
<Mask>/^lagg(\d)*$/</Mask>
|
||||
</laggif>
|
||||
<members type=".\LaggInterfaceField">
|
||||
<Required>Y</Required>
|
||||
<Multiple>Y</Multiple>
|
||||
<ValidationMessage>At least one valid member is required</ValidationMessage>
|
||||
</members>
|
||||
<proto type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<default>lacp</default>
|
||||
<OptionValues>
|
||||
<none>None</none>
|
||||
<lacp>lacp</lacp>
|
||||
<failover>failover</failover>
|
||||
<fec>fec</fec>
|
||||
<loadbalance>loadbalance</loadbalance>
|
||||
<roundrobin>roundrobin</roundrobin>
|
||||
</OptionValues>
|
||||
</proto>
|
||||
<lacp_fast_timeout type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</lacp_fast_timeout>
|
||||
<use_flowid type="OptionField">
|
||||
<OptionValues>
|
||||
<default value="">Default</default>
|
||||
<yes value="1">Yes</yes>
|
||||
<no value="0">No</no>
|
||||
</OptionValues>
|
||||
</use_flowid>
|
||||
<lagghash type="OptionField">
|
||||
<Multiple>Y</Multiple>
|
||||
<OptionValues>
|
||||
<l2>L2: src/dst MAC address and optional VLAN number.</l2>
|
||||
<l3>L3: src/dst address for IPv4 or IPv6.</l3>
|
||||
<l4>L4: src/dst port for TCP/UDP/SCTP.</l4>
|
||||
</OptionValues>
|
||||
</lagghash>
|
||||
<lacp_strict type="OptionField">
|
||||
<OptionValues>
|
||||
<default value="">Default</default>
|
||||
<yes value="1">Yes</yes>
|
||||
<no value="0">No</no>
|
||||
</OptionValues>
|
||||
</lacp_strict>
|
||||
<mtu type="IntegerField">
|
||||
<Required>N</Required>
|
||||
<MinimumValue>576</MinimumValue>
|
||||
<MaximumValue>65535</MaximumValue>
|
||||
</mtu>
|
||||
<descr type="TextField">
|
||||
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.\-,_\x{00A0}-\x{FFFF}]){0,255}$/u</mask>
|
||||
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
|
||||
</descr>
|
||||
</lagg>
|
||||
</items>
|
||||
</model>
|
||||
@ -8,6 +8,7 @@
|
||||
<VXLAN url="/ui/interfaces/vxlan"/>
|
||||
<Loopback url="/ui/interfaces/loopback"/>
|
||||
<VLAN url="/ui/interfaces/vlan"/>
|
||||
<LAGG url="/ui/interfaces/lagg"/>
|
||||
</Types>
|
||||
</Interfaces>
|
||||
</menu>
|
||||
|
||||
69
src/opnsense/mvc/app/views/OPNsense/Interface/lagg.volt
Normal file
69
src/opnsense/mvc/app/views/OPNsense/Interface/lagg.volt
Normal file
@ -0,0 +1,69 @@
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
$("#grid-laggs").UIBootgrid(
|
||||
{ search:'/api/interfaces/lagg_settings/searchItem',
|
||||
get:'/api/interfaces/lagg_settings/getItem/',
|
||||
set:'/api/interfaces/lagg_settings/setItem/',
|
||||
add:'/api/interfaces/lagg_settings/addItem/',
|
||||
del:'/api/interfaces/lagg_settings/delItem/',
|
||||
options: {
|
||||
formatters: {
|
||||
members: function (column, row) {
|
||||
return row[column.id].replace(',', '<br/>');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$("#lagg\\.proto").change(function(){
|
||||
$(".proto").closest("tr").hide();
|
||||
$(".proto_"+$(this).val()).each(function(){
|
||||
$(this).closest("tr").show();
|
||||
});
|
||||
});
|
||||
|
||||
$("#reconfigureAct").SimpleActionButton();
|
||||
});
|
||||
</script>
|
||||
<div class="tab-content content-box">
|
||||
<table id="grid-laggs" class="table table-condensed table-hover table-striped" data-editDialog="DialogEdit" data-editAlert="LaggChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="laggif" data-width="5em" data-type="string">{{ lang._('Device') }}</th>
|
||||
<th data-column-id="members" data-type="string" data-width="12em" data-formatter="members">{{ lang._('Members') }}</th>
|
||||
<th data-column-id="proto" data-width="10em" data-type="string">{{ lang._('Protocol') }}</th>
|
||||
<th data-column-id="descr" data-type="string">{{ lang._('Description') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-primary"><span class="fa fa-fw fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-fw fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div class="col-md-12">
|
||||
<div id="LaggChangeMessage" class="alert alert-info" style="display: none" role="alert">
|
||||
{{ lang._('After changing settings, please remember to apply them with the button below') }}
|
||||
</div>
|
||||
<hr/>
|
||||
<button class="btn btn-primary" id="reconfigureAct"
|
||||
data-endpoint='/api/interfaces/lagg_settings/reconfigure'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-error-title="{{ lang._('Error reconfiguring laggs') }}"
|
||||
type="button"
|
||||
></button>
|
||||
<br/><br/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogEdit,'id':'DialogEdit','label':lang._('Edit Lagg')])}}
|
||||
@ -28,5 +28,43 @@
|
||||
*/
|
||||
|
||||
require_once("interfaces.inc");
|
||||
require_once("interfaces.lib.inc");
|
||||
|
||||
echo json_encode(legacy_interfaces_details());
|
||||
$vfaces = [
|
||||
'_stf',
|
||||
'_vlan',
|
||||
'_wlan',
|
||||
'bridge',
|
||||
'carp',
|
||||
'enc',
|
||||
'gif',
|
||||
'gre',
|
||||
'ipfw', /* ipfw logging device, not enabled by default */
|
||||
'ipsec',
|
||||
'l2tp',
|
||||
'lagg',
|
||||
'lo',
|
||||
'ng',
|
||||
'ovpnc',
|
||||
'ovpns',
|
||||
'pflog',
|
||||
'pfsync',
|
||||
'plip',
|
||||
'ppp',
|
||||
'pppoe',
|
||||
'pptp',
|
||||
'qinq',
|
||||
'tap',
|
||||
'tun',
|
||||
'vlan',
|
||||
'vxlan',
|
||||
];
|
||||
|
||||
$response = legacy_interfaces_details();
|
||||
|
||||
foreach ($response as $ifname => &$intf) {
|
||||
$tmp_ifnames = preg_split('/\d+/', $ifname);
|
||||
$intf['is_physical'] = !count(array_intersect($tmp_ifnames, $vfaces));
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
|
||||
77
src/opnsense/scripts/interfaces/reconfigure_laggs.php
Executable file
77
src/opnsense/scripts/interfaces/reconfigure_laggs.php
Executable file
@ -0,0 +1,77 @@
|
||||
#!/usr/local/bin/php
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
require_once 'config.inc';
|
||||
require_once 'filter.inc';
|
||||
require_once 'interfaces.inc';
|
||||
require_once 'util.inc';
|
||||
|
||||
/* gather all relevant lagg interfaces*/
|
||||
$laggs_todo = [];
|
||||
$vfilename = '/tmp/.lagg.todo';
|
||||
if (file_exists($vfilename) && filesize($vfilename) > 0) {
|
||||
$handle = fopen($vfilename, 'r+');
|
||||
if (flock($handle, LOCK_EX)) {
|
||||
fseek($handle, 0);
|
||||
foreach (explode("\n", fread($handle, filesize($vfilename))) as $line) {
|
||||
if (!isset($laggs_todo[$line]) && trim($line) != '') {
|
||||
$laggs_todo[$line] = [];
|
||||
}
|
||||
}
|
||||
fseek($handle, 0);
|
||||
ftruncate($handle, 0);
|
||||
flock($handle, LOCK_UN);
|
||||
}
|
||||
}
|
||||
|
||||
/* collect changed laggs to reconfigure */
|
||||
$lagg_configure = [];
|
||||
foreach ((new OPNsense\Interfaces\Lagg())->lagg->iterateItems() as $item) {
|
||||
$lagg = [];
|
||||
foreach ($item->iterateItems() as $node) {
|
||||
$lagg[$node->getInternalXMLTagName()] = (string)$node;
|
||||
}
|
||||
if (isset($laggs_todo[$lagg['laggif']])) {
|
||||
$lagg_configure[] = $lagg;
|
||||
unset($laggs_todo[$lagg['laggif']]);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove non existing interfaces */
|
||||
foreach (array_keys($laggs_todo) as $laggif) {
|
||||
legacy_interface_destroy($laggif);
|
||||
}
|
||||
|
||||
/*
|
||||
reconfigure still existing laggs,
|
||||
removal should happen first as it may free parent interfaces.
|
||||
*/
|
||||
foreach ($lagg_configure as $lagg) {
|
||||
_interfaces_lagg_configure($lagg);
|
||||
}
|
||||
@ -145,6 +145,11 @@ command: /usr/local/opnsense/scripts/interfaces/reconfigure_vlans.php
|
||||
message: Reconfiguring vlan
|
||||
type: script
|
||||
|
||||
[lagg.configure]
|
||||
command: /usr/local/opnsense/scripts/interfaces/reconfigure_laggs.php
|
||||
message: Reconfiguring laggs
|
||||
type: script
|
||||
|
||||
[loopback.configure]
|
||||
command: /usr/local/sbin/pluginctl -c loopback
|
||||
message: Reconfiguring loopbacks
|
||||
|
||||
@ -1,142 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Deciso B.V.
|
||||
* Copyright (C) 2008 Ermal Luçi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
require_once("guiconfig.inc");
|
||||
|
||||
$a_laggs = &config_read_array('laggs', 'lagg');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$input_errors = array();
|
||||
if (!empty($a_laggs[$_POST['id']])) {
|
||||
$id = $_POST['id'];
|
||||
}
|
||||
|
||||
if (!empty($_POST['action']) && $_POST['action'] == "del" && isset($id)) {
|
||||
if (is_interface_assigned($a_laggs[$id]['laggif'])) {
|
||||
$input_errors[] = gettext("This LAGG interface cannot be deleted because it is still being used.");
|
||||
} else {
|
||||
mwexecf('/sbin/ifconfig %s destroy', $a_laggs[$id]['laggif']);
|
||||
unset($a_laggs[$id]);
|
||||
write_config();
|
||||
header(url_safe('Location: /interfaces_lagg.php'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include("head.inc");
|
||||
|
||||
legacy_html_escape_form_data($a_laggs);
|
||||
|
||||
?>
|
||||
<body>
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
// link delete buttons
|
||||
$(".act_delete").click(function(event){
|
||||
event.preventDefault();
|
||||
var id = $(this).data("id");
|
||||
// delete single
|
||||
BootstrapDialog.show({
|
||||
type:BootstrapDialog.TYPE_DANGER,
|
||||
title: "<?= gettext("LAGG");?>",
|
||||
message: "<?=gettext("Do you really want to delete this LAGG interface?");?>",
|
||||
buttons: [{
|
||||
label: "<?= gettext("No");?>",
|
||||
action: function(dialogRef) {
|
||||
dialogRef.close();
|
||||
}}, {
|
||||
label: "<?= gettext("Yes");?>",
|
||||
action: function(dialogRef) {
|
||||
$("#id").val(id);
|
||||
$("#action").val("del");
|
||||
$("#iform").submit()
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php include("fbegin.inc"); ?>
|
||||
<section class="page-content-main">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<?php if (isset($input_errors) && count($input_errors) > 0) print_input_errors($input_errors); ?>
|
||||
<section class="col-xs-12">
|
||||
<div class="tab-content content-box col-xs-12">
|
||||
<form method="post" name="iform" id="iform">
|
||||
<input type="hidden" id="action" name="action" value="">
|
||||
<input type="hidden" id="id" name="id" value="">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?=gettext("Device");?></th>
|
||||
<th><?=gettext("Members");?></th>
|
||||
<th><?=gettext("Protocol");?></th>
|
||||
<th><?=gettext("Description");?></th>
|
||||
<th class="text-nowrap">
|
||||
<a href="interfaces_lagg_edit.php" class="btn btn-primary btn-xs" data-toggle="tooltip" title="<?= html_safe(gettext('Add')) ?>">
|
||||
<i class="fa fa-plus fa-fw"></i>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$i = 0;
|
||||
foreach ($a_laggs as $lagg): ?>
|
||||
<tr>
|
||||
<td><?=$lagg['laggif'];?></td>
|
||||
<td><?=$lagg['members'];?></td>
|
||||
<td><?=strtoupper($lagg['proto']);?></td>
|
||||
<td><?=$lagg['descr'];?></td>
|
||||
<td class="text-nowrap">
|
||||
<a href="interfaces_lagg_edit.php?id=<?=$i;?>" class="btn btn-xs btn-default" data-toggle="tooltip" title="<?= html_safe(gettext('Edit')) ?>">
|
||||
<i class="fa fa-pencil fa-fw"></i>
|
||||
</a>
|
||||
<button title="<?= html_safe(gettext('Delete')) ?>" data-toggle="tooltip" data-id="<?=$i;?>" class="btn btn-default btn-xs act_delete" type="submit">
|
||||
<i class="fa fa-trash fa-fw"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
$i++;
|
||||
endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php include("foot.inc"); ?>
|
||||
@ -1,393 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Deciso B.V.
|
||||
* Copyright (C) 2008 Ermal Luçi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
require_once("guiconfig.inc");
|
||||
require_once("system.inc");
|
||||
require_once("interfaces.inc");
|
||||
|
||||
/**
|
||||
* list available interfaces for lagg
|
||||
* @param null $selected_id selected item index
|
||||
* @return array
|
||||
*/
|
||||
function available_interfaces($selected_id = null)
|
||||
{
|
||||
global $config;
|
||||
// configured interfaces
|
||||
$configured_interfaces = array();
|
||||
foreach (array_keys(legacy_config_get_interfaces(['virtual' => false])) as $intf) {
|
||||
$configured_interfaces[] = get_real_interface($intf);
|
||||
}
|
||||
// lagg members from other lagg interfaces
|
||||
$lagg_member_interfaces = array();
|
||||
foreach ($config['laggs']['lagg'] as $lagg_idx => $lagg) {
|
||||
if ($lagg_idx == $selected_id) {
|
||||
continue;
|
||||
}
|
||||
foreach (explode(",", $lagg['members']) as $lagg_member) {
|
||||
$lagg_member_interfaces[] = get_real_interface($lagg_member);
|
||||
}
|
||||
}
|
||||
|
||||
$interfaces = array();
|
||||
foreach (get_interface_list() as $intf => $intf_info) {
|
||||
if (in_array($intf, $lagg_member_interfaces)) {
|
||||
// skip members of other lagg interfaces
|
||||
continue;
|
||||
} elseif (in_array($intf, $configured_interfaces)) {
|
||||
// skip configured interfaces
|
||||
continue;
|
||||
}
|
||||
$interfaces[$intf] = $intf_info;
|
||||
}
|
||||
|
||||
return $interfaces;
|
||||
}
|
||||
|
||||
$laggprotos = array("none", "lacp", "failover", "fec", "loadbalance", "roundrobin");
|
||||
|
||||
$a_laggs = &config_read_array('laggs', 'lagg');
|
||||
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
// read form data
|
||||
if (!empty($a_laggs[$_GET['id']])) {
|
||||
$id = $_GET['id'];
|
||||
}
|
||||
$pconfig = array();
|
||||
$pconfig['laggif'] = isset($a_laggs[$id]['laggif']) ? $a_laggs[$id]['laggif'] : null;
|
||||
$pconfig['members'] = isset($a_laggs[$id]['members']) ? explode(",", $a_laggs[$id]['members']) : array();
|
||||
$pconfig['proto'] = isset($a_laggs[$id]['proto']) ? $a_laggs[$id]['proto'] : null;
|
||||
$pconfig['descr'] = isset($a_laggs[$id]['descr']) ? $a_laggs[$id]['descr'] : null;
|
||||
$pconfig['lacp_fast_timeout'] = !empty($a_laggs[$id]['lacp_fast_timeout']);
|
||||
$pconfig['use_flowid'] = isset($a_laggs[$id]['use_flowid']) ? $a_laggs[$id]['use_flowid'] : null;
|
||||
$pconfig['lagghash'] = isset($a_laggs[$id]['lagghash']) ? explode(',', $a_laggs[$id]['lagghash']) : [];
|
||||
$pconfig['lacp_strict'] = isset($a_laggs[$id]['lacp_strict']) ? $a_laggs[$id]['lacp_strict'] : null;
|
||||
$pconfig['mtu'] = isset($a_laggs[$id]['mtu']) ? $a_laggs[$id]['mtu'] : null;
|
||||
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// validate and save form data
|
||||
if (!empty($a_laggs[$_POST['id']])) {
|
||||
$id = $_POST['id'];
|
||||
}
|
||||
$input_errors = array();
|
||||
$pconfig = $_POST;
|
||||
|
||||
/* input validation */
|
||||
$reqdfields = explode(" ", "members proto");
|
||||
$reqdfieldsn = array(gettext("Member interfaces"), gettext("Lagg protocol"));
|
||||
|
||||
do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
|
||||
|
||||
if (isset($pconfig['members'])) {
|
||||
foreach ($pconfig['members'] as $member) {
|
||||
if (!does_interface_exist($member)) {
|
||||
$input_errors[] = sprintf(gettext('Interface \'%s\' supplied as member does not exist'), $member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($pconfig['lagghash'])){
|
||||
foreach ((array)$pconfig['lagghash'] as $item) {
|
||||
if (!in_array($item, ['l2', 'l3', 'l4'])) {
|
||||
$input_errors[] = sprintf(gettext('Invalid lagghash value \'%s\''), $item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!in_array($pconfig['proto'], $laggprotos)) {
|
||||
$input_errors[] = gettext("Protocol supplied is invalid");
|
||||
}
|
||||
|
||||
if (!empty($pconfig['mtu'])) {
|
||||
$mtu_low = 576;
|
||||
$mtu_high = 65535;
|
||||
if ($pconfig['mtu'] < $mtu_low || $pconfig['mtu'] > $mtu_high || (string)((int)$pconfig['mtu']) != $pconfig['mtu'] ) {
|
||||
$input_errors[] = sprintf(gettext('The MTU must be greater than %s bytes and less than %s.'), $mtu_low, $mtu_high);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($input_errors) == 0) {
|
||||
$lagg = array();
|
||||
$lagg['members'] = implode(',', $pconfig['members']);
|
||||
$lagg['descr'] = $pconfig['descr'];
|
||||
$lagg['laggif'] = $pconfig['laggif'];
|
||||
$lagg['proto'] = $pconfig['proto'];
|
||||
$lagg['mtu'] = $pconfig['mtu'];
|
||||
$lagg['lacp_fast_timeout'] = !empty($pconfig['lacp_fast_timeout']);
|
||||
if (in_array($pconfig['use_flowid'] ?? '', ['0', '1'])) {
|
||||
$lagg['use_flowid'] = $pconfig['use_flowid'];
|
||||
}
|
||||
if (in_array($pconfig['lacp_strict'] ?? '', ['0', '1'])) {
|
||||
$lagg['lacp_strict'] = $pconfig['lacp_strict'];
|
||||
}
|
||||
if (!empty($pconfig['lagghash'])) {
|
||||
$lagg['lagghash'] = implode(',', $pconfig['lagghash']);
|
||||
}
|
||||
if (isset($id)) {
|
||||
$lagg['laggif'] = $a_laggs[$id]['laggif'];
|
||||
}
|
||||
|
||||
if (empty($lagg['laggif'])) {
|
||||
$lagg['laggif'] = legacy_interface_create('lagg'); /* XXX find another strategy */
|
||||
}
|
||||
|
||||
if (empty($lagg['laggif']) || strpos($lagg['laggif'], 'lagg') !== 0) {
|
||||
$input_errors[] = gettext("Error occurred creating interface, please retry.");
|
||||
} else {
|
||||
if (isset($id)) {
|
||||
$a_laggs[$id] = $lagg;
|
||||
} else {
|
||||
$a_laggs[] = $lagg;
|
||||
}
|
||||
write_config();
|
||||
_interfaces_lagg_configure($lagg);
|
||||
$confif = convert_real_interface_to_friendly_interface_name($lagg['laggif']);
|
||||
if ($confif != '') {
|
||||
interface_configure(false, $confif);
|
||||
}
|
||||
header(url_safe('Location: /interfaces_lagg.php'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include("head.inc");
|
||||
legacy_html_escape_form_data($pconfig);
|
||||
?>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
$("#proto").change(function(){
|
||||
let this_proto = $("#proto").val();
|
||||
$(".proto").closest('tr').hide();
|
||||
$(".proto").prop( "disabled", true );
|
||||
$(".proto_"+this_proto).closest('tr').show();
|
||||
$(".proto_"+this_proto).prop( "disabled", false );
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
$("#proto").change();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include("fbegin.inc"); ?>
|
||||
<section class="page-content-main">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<?php if (isset($input_errors) && count($input_errors) > 0) print_input_errors($input_errors); ?>
|
||||
<section class="col-xs-12">
|
||||
<div class="content-box">
|
||||
<div class="table-responsive">
|
||||
<form method="post" name="iform" id="iform">
|
||||
<table class="table table-striped opnsense_standard_table_form">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="width:22%"><strong><?=gettext("LAGG configuration");?></strong></td>
|
||||
<td style="width:78%; text-align:right">
|
||||
<small><?=gettext("full help"); ?> </small>
|
||||
<i class="fa fa-toggle-off text-danger" style="cursor: pointer;" id="show_all_help_page"></i>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a id="help_for_members" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Parent interface"); ?></td>
|
||||
<td>
|
||||
<select name="members[]" multiple="multiple" class="selectpicker">
|
||||
<?php
|
||||
foreach (available_interfaces(isset($id) ? $id : null) as $ifn => $ifinfo):?>
|
||||
<option value="<?=$ifn;?>" <?=!empty($pconfig['members']) && in_array($ifn, $pconfig['members']) ? "selected=\"selected\"" : "";?>>
|
||||
<?=$ifn;?> (<?=$ifinfo['mac']?>)
|
||||
</option>
|
||||
<?php
|
||||
endforeach;?>
|
||||
</select>
|
||||
<div class="hidden" data-for="help_for_members">
|
||||
<?=gettext("Choose the members that will be used for the link aggregation"); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_proto" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Lag proto"); ?></td>
|
||||
<td>
|
||||
<select name="proto" class="selectpicker" id="proto">
|
||||
<?php
|
||||
foreach ($laggprotos as $proto):?>
|
||||
<option value="<?=$proto;?>" <?=$proto == $pconfig['proto'] ? "selected=\"selected\"": "";?>>
|
||||
<?=strtoupper($proto);?>
|
||||
</option>
|
||||
<?php
|
||||
endforeach;?>
|
||||
</select>
|
||||
<div class="hidden" data-for="help_for_proto">
|
||||
<ul>
|
||||
<li><b><?=gettext("failover"); ?></b></li>
|
||||
<?=gettext("Sends and receives traffic only through the master port. " .
|
||||
"If the master port becomes unavailable, the next active port is " .
|
||||
"used. The first interface added is the master port; any " .
|
||||
"interfaces added after that are used as failover devices."); ?>
|
||||
<li><b><?=gettext("fec"); ?></b><br /></li>
|
||||
<?=gettext("Supports Cisco EtherChannel. This is a static setup and " .
|
||||
"does not negotiate aggregation with the peer or exchange " .
|
||||
"frames to monitor the link."); ?>
|
||||
<li>
|
||||
<b><?=gettext("lacp"); ?></b></li>
|
||||
<?=gettext("Supports the IEEE 802.3ad Link Aggregation Control Protocol " .
|
||||
"(LACP) and the Marker Protocol. LACP will negotiate a set " .
|
||||
"of aggregable links with the peer in to one or more Link " .
|
||||
"Aggregated Groups. Each LAG is composed of ports of the " .
|
||||
"same speed, set to full-duplex operation. The traffic will " .
|
||||
"be balanced across the ports in the LAG with the greatest " .
|
||||
"total speed, in most cases there will only be one LAG which " .
|
||||
"contains all ports. In the event of changes in physical " .
|
||||
"connectivity, Link Aggregation will quickly converge to a " .
|
||||
"new configuration."); ?>
|
||||
<li><b><?=gettext("loadbalance"); ?></b></li>
|
||||
<?=gettext("Balances outgoing traffic across the active ports based on " .
|
||||
"hashed protocol header information and accepts incoming " .
|
||||
"traffic from any active port. This is a static setup and " .
|
||||
"does not negotiate aggregation with the peer or exchange " .
|
||||
"frames to monitor the link. The hash includes the Ethernet " .
|
||||
"source and destination address, and, if available, the VLAN " .
|
||||
"tag, and the IP source and destination address.") ?>
|
||||
<li><b><?=gettext("roundrobin"); ?></b></li>
|
||||
<?=gettext("Distributes outgoing traffic using a round-robin scheduler " .
|
||||
"through all active ports and accepts incoming traffic from " .
|
||||
"any active port."); ?>
|
||||
<li><b><?=gettext("none"); ?></b></li>
|
||||
<?=gettext("This protocol is intended to do nothing: It disables any " .
|
||||
"traffic without disabling the lagg interface itself."); ?>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_descr" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Description"); ?></td>
|
||||
<td>
|
||||
<input name="descr" type="text" value="<?=$pconfig['descr'];?>" />
|
||||
<div class="hidden" data-for="help_for_descr">
|
||||
<?=gettext("You may enter a description here for your reference (not parsed)."); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_lacp_fast_timeout" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Fast timeout"); ?></td>
|
||||
<td>
|
||||
<input name="lacp_fast_timeout" id="lacp_fast_timeout" class="proto proto_lacp" type="checkbox" value="yes" <?=!empty($pconfig['lacp_fast_timeout']) ? "checked=\"checked\"" : "" ;?>/>
|
||||
<div class="hidden" data-for="help_for_lacp_fast_timeout">
|
||||
<?=gettext("Enable lacp fast-timeout on the interface."); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_use_flowid" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Use flowid"); ?></td>
|
||||
<td>
|
||||
<select name="use_flowid" class="selectpicker proto proto_lacp proto_loadbalance" id="use_flowid">
|
||||
<option value=""><?=gettext("Default");?></option>
|
||||
<option value="1" <?=$pconfig['use_flowid'] === "1" ? "selected=\"selected\"": ""?>>
|
||||
<?=gettext("Yes");?>
|
||||
</option>
|
||||
<option value="0" <?=$pconfig['use_flowid'] === "0" ? "selected=\"selected\"": ""?>>
|
||||
<?=gettext("No");?>
|
||||
</option>
|
||||
</select>
|
||||
<div class="hidden" data-for="help_for_use_flowid">
|
||||
<?=gettext(
|
||||
"Use the RSS hash from the network card if available, otherwise a hash is locally calculated. ".
|
||||
"The default depends on the system tunable in net.link.lagg.default_use_flowid."
|
||||
)?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_lagghash" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Hash Layers"); ?>
|
||||
<td>
|
||||
<select name="lagghash[]" title="<?=gettext("Default");?>" multiple="multiple" class="selectpicker proto proto_lacp proto_loadbalance">
|
||||
<option value="l2" <?=in_array('l2', $pconfig['lagghash']) ? "selected=\"selected\"": ""?> ><?=gettext("L2: src/dst MAC address and optional VLAN number."); ?></option>
|
||||
<option value="l3" <?=in_array('l3', $pconfig['lagghash']) ? "selected=\"selected\"": ""?>><?=gettext("L3: src/dst address for IPv4 or IPv6."); ?></option>
|
||||
<option value="l4" <?=in_array('l4', $pconfig['lagghash']) ? "selected=\"selected\"": ""?>><?=gettext("L4: src/dst port for TCP/UDP/SCTP."); ?></option>
|
||||
</select>
|
||||
<div class="hidden" data-for="help_for_lagghash">
|
||||
<?=gettext("Set the packet layers to hash for aggregation protocols which load balance."); ?><br/>
|
||||
</div>
|
||||
</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_lacp_strict" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Use strict"); ?></td>
|
||||
<td>
|
||||
<select name="lacp_strict" class="selectpicker proto proto_lacp" id="lacp_strict">
|
||||
<option value=""><?=gettext("Default");?></option>
|
||||
<option value="1" <?=$pconfig['lacp_strict'] === "1" ? "selected=\"selected\"": ""?>>
|
||||
<?=gettext("Yes");?>
|
||||
</option>
|
||||
<option value="0" <?=$pconfig['lacp_strict'] === "0" ? "selected=\"selected\"": ""?>>
|
||||
<?=gettext("No");?>
|
||||
</option>
|
||||
</select>
|
||||
<div class="hidden" data-for="help_for_lacp_strict">
|
||||
<?=gettext(
|
||||
"Enable lacp strict compliance on the interface. ".
|
||||
"The default depends on the system tunable in net.link.lagg.lacp.default_strict_mode."
|
||||
)?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_mtu" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("MTU"); ?></td>
|
||||
<td>
|
||||
<input name="mtu" id="mtu" type="text" value="<?=$pconfig['mtu'];?>" />
|
||||
<div class="hidden" data-for="help_for_mtu">
|
||||
<?= gettext("If you leave this field blank, the smallest mtu of this laggs children will be used.");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:22%"> </td>
|
||||
<td style="width:78%">
|
||||
<input type="hidden" name="laggif" value="<?=$pconfig['laggif']; ?>" />
|
||||
<input name="Submit" type="submit" class="btn btn-primary" value="<?=html_safe(gettext('Save')); ?>" />
|
||||
<input type="button" class="btn btn-default" value="<?=html_safe(gettext('Cancel'));?>" onclick="window.location.href='/interfaces_lagg.php'" />
|
||||
<?php if (isset($id)): ?>
|
||||
<input name="id" type="hidden" value="<?=$id;?>" />
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php include("foot.inc"); ?>
|
||||
Loading…
x
Reference in New Issue
Block a user