Squashed commit of the following:

commit f70158ab043ec0c2d5b31f469b0b36c3e1445df6
Author: Ad Schellevis <ad@opnsense.org>
Date:   Sat Sep 28 22:53:12 2024 +0200

    Routing: OSPFv3 - style cleanups for https://github.com/opnsense/plugins/pull/4247

commit 549ee36704f5f40ee2a556eeac0d52b54f880455
Author: Mike Shuey <shuey@fmepnet.org>
Date:   Sat Sep 21 11:47:05 2024 -0700

    Set up networks, prefix lists, and route maps for OSPF6
This commit is contained in:
Ad Schellevis
2024-09-28 23:02:19 +02:00
parent bd009e41c3
commit 1d692d9571
10 changed files with 576 additions and 113 deletions
@@ -1,7 +1,7 @@
<?php
/*
* Copyright (C) 2015-2017 Deciso B.V.
* Copyright (C) 2015-2024 Deciso B.V.
* Copyright (C) 2015 Jos Schellevis <jos@opnsense.org>
* Copyright (C) 2017 Fabian Franz
* Copyright (C) 2017 Michael Muenz <m.muenz@gmail.com>
@@ -40,29 +40,101 @@ class Ospf6settingsController extends ApiMutableModelControllerBase
{
protected static $internalModelName = 'ospf6';
protected static $internalModelClass = '\OPNsense\Quagga\OSPF6';
public function searchNetworkAction()
{
return $this->searchBase('networks.network');
}
public function searchInterfaceAction()
{
return $this->searchBase('interfaces.interface', array("enabled", "interfacename", "area", "networktype"));
return $this->searchBase('interfaces.interface');
}
public function searchPrefixlistAction()
{
return $this->searchBase('prefixlists.prefixlist');
}
public function searchRoutemapAction()
{
return $this->searchBase('routemaps.routemap');
}
public function getNetworkAction($uuid = null)
{
return $this->getBase('network', 'networks.network', $uuid);
}
public function getInterfaceAction($uuid = null)
{
$this->sessionClose();
return $this->getBase('interface', 'interfaces.interface', $uuid);
}
public function getPrefixlistAction($uuid = null)
{
return $this->getBase('prefixlist', 'prefixlists.prefixlist', $uuid);
}
public function getRoutemapAction($uuid = null)
{
return $this->getBase('routemap', 'routemaps.routemap', $uuid);
}
public function addNetworkAction()
{
return $this->addBase('network', 'networks.network');
}
public function addInterfaceAction()
{
return $this->addBase('interface', 'interfaces.interface');
}
public function addPrefixlistAction()
{
return $this->addBase('prefixlist', 'prefixlists.prefixlist');
}
public function addRoutemapAction()
{
return $this->addBase('routemap', 'routemaps.routemap');
}
public function delNetworkAction($uuid)
{
return $this->delBase('networks.network', $uuid);
}
public function delInterfaceAction($uuid)
{
return $this->delBase('interfaces.interface', $uuid);
}
public function delPrefixlistAction($uuid)
{
return $this->delBase('prefixlists.prefixlist', $uuid);
}
public function delRoutemapAction($uuid)
{
return $this->delBase('routemaps.routemap', $uuid);
}
public function setNetworkAction($uuid)
{
return $this->setBase('network', 'networks.network', $uuid);
}
public function setInterfaceAction($uuid)
{
return $this->setBase('interface', 'interfaces.interface', $uuid);
}
public function setPrefixlistAction($uuid)
{
return $this->setBase('prefixlist', 'prefixlists.prefixlist', $uuid);
}
public function setRoutemapAction($uuid)
{
return $this->setBase('routemap', 'routemaps.routemap', $uuid);
}
public function toggleNetworkAction($uuid)
{
return $this->toggleBase('networks.network', $uuid);
}
public function toggleInterfaceAction($uuid)
{
return $this->toggleBase('interfaces.interface', $uuid);
}
public function togglePrefixlistAction($uuid)
{
return $this->toggleBase('prefixlists.prefixlist', $uuid);
}
public function toggleRoutemapAction($uuid)
{
return $this->toggleBase('routemaps.routemap', $uuid);
}
}
@@ -30,7 +30,10 @@ class Ospf6Controller extends \OPNsense\Base\IndexController
public function indexAction()
{
$this->view->ospf6Form = $this->getForm("ospf6");
$this->view->formDialogEditNetwork = $this->getForm("dialogEditOSPF6Network");
$this->view->formDialogEditInterface = $this->getForm("dialogEditOSPF6Interface");
$this->view->formDialogEditPrefixLists = $this->getForm("dialogEditOSPF6PrefixLists");
$this->view->formDialogEditRouteMaps = $this->getForm("dialogEditOSPF6RouteMaps");
$this->view->pick('OPNsense/Quagga/ospf6');
}
}
@@ -30,6 +30,7 @@
<id>interface.cost_demoted</id>
<label>Cost (when demoted)</label>
<type>text</type>
<hint>65535</hint>
</field>
<field>
<id>interface.carp_depend_on</id>
@@ -0,0 +1,41 @@
<form>
<field>
<id>network.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
</field>
<field>
<id>network.ipaddr</id>
<label>Network Address</label>
<type>text</type>
</field>
<field>
<id>network.netmask</id>
<label>Network Mask</label>
<type>text</type>
</field>
<field>
<id>network.area</id>
<label>Area</label>
<type>text</type>
<help>Area in wildcard mask style like 0.0.0.0 and no decimal 0. Only use Area in Interface tab or in Network tab once.</help>
</field>
<field>
<id>network.arearange</id>
<label>Area Range</label>
<type>text</type>
<help>Here you can summarize a network for this area like fe80:1234::0/64</help>
</field>
<field>
<id>network.linkedPrefixlistIn</id>
<label>Prefix-List In</label>
<type>dropdown</type>
<help>Prefix-List for inbound direction</help>
</field>
<field>
<id>network.linkedPrefixlistOut</id>
<label>Prefix-List Out</label>
<type>dropdown</type>
<help>Prefix-List for outbound direction</help>
</field>
</form>
@@ -0,0 +1,32 @@
<form>
<field>
<id>prefixlist.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
<help>Enable / Disable</help>
</field>
<field>
<id>prefixlist.name</id>
<label>Name</label>
<type>text</type>
<help>The name of your Prefix-List, please choose one near to the result you want to achieve.</help>
</field>
<field>
<id>prefixlist.seqnumber</id>
<label>Number</label>
<type>text</type>
<help>The ACL sequence number (10-99)</help>
</field>
<field>
<id>prefixlist.action</id>
<label>Action</label>
<type>select_multiple</type>
<help>Set permit for match or deny to negate the rule.</help>
</field>
<field>
<id>prefixlist.network</id>
<label>Network</label>
<type>text</type>
<help>The network pattern you want to match. It's not validated so please be careful!</help>
</field>
</form>
@@ -0,0 +1,38 @@
<form>
<field>
<id>routemap.enabled</id>
<label>Enabled</label>
<type>checkbox</type>
</field>
<field>
<id>routemap.name</id>
<label>Name</label>
<type>text</type>
<help>Route-map name to match and set your patterns, it will be enabled via redistribution.</help>
</field>
<field>
<id>routemap.action</id>
<label>Action</label>
<type>select_multiple</type>
<help>Set permit for match or deny to negate the rule.</help>
</field>
<field>
<id>routemap.id</id>
<label>ID</label>
<type>text</type>
<help>Route-map ID between 10 and 99. Be aware that the sorting will be done under the hood, so when you add an entry between it get's to the right position</help>
</field>
<field>
<id>routemap.match2</id>
<label>Prefix List</label>
<type>select_multiple</type>
<style>tokenize</style>
<allownew>true</allownew>
</field>
<field>
<id>routemap.set</id>
<label>Set</label>
<type>text</type>
<help>Free text field for your set, please be careful! You can set e.g. "local-preference 300" or "community 1:1" (http://docs.frrouting.org/en/latest/routemap.html#route-map-set-command)</help>
</field>
</form>
@@ -22,6 +22,12 @@
<help><![CDATA[Select other routing sources, which should be redistributed to the other nodes.]]></help>
<hint>Type or select a route source.</hint>
</field>
<field>
<id>ospf6.redistributemap</id>
<label>Redistribution Map</label>
<type>dropdown</type>
<help>Route Map to set for Redistribution.</help>
</field>
<field>
<id>ospf6.routerid</id>
<label>Router ID</label>
@@ -33,7 +39,6 @@
<label>Advertise Default Gateway</label>
<type>checkbox</type>
<help>This will send the information that we have a default gateway.</help>
<style>opt_checkbox</style>
</field>
<field>
<id>ospf6.originatealways</id>
@@ -12,17 +12,25 @@
<Required>Y</Required>
</carp_demote>
<redistribute type="OptionField">
<Required>N</Required>
<multiple>Y</multiple>
<default></default>
<OptionValues>
<connected>Connected routes (directly attached subnet or host)</connected>
<kernel>Kernel routes (not installed via the zebra RIB)</kernel>
<static>Statically configured routes</static>
</OptionValues>
</redistribute>
<redistributemap type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.ospf6</source>
<items>routemaps.routemap</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Route-Map item not found</ValidationMessage>
</redistributemap>
<routerid type="TextField">
<Required>N</Required>
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
</routerid>
<originate type="BooleanField">
@@ -34,11 +42,59 @@
<Required>Y</Required>
</originatealways>
<originatemetric type="IntegerField">
<Required>N</Required>
<MinimumValue>0</MinimumValue>
<MaximumValue>16777214</MaximumValue>
<ValidationMessage>Must be a number between 0 and 16777214.</ValidationMessage>
</originatemetric>
<networks>
<network type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<!-- XXX: it would make sense to merge both into a single field "network" -->
<ipaddr type="NetworkField">
<Required>Y</Required>
<NetMaskAllowed>N</NetMaskAllowed>
<WildcardEnabled>N</WildcardEnabled>
<AddressFamily>ipv6</AddressFamily>
</ipaddr>
<netmask type="IntegerField">
<default>64</default>
<MinimumValue>0</MinimumValue>
<Required>Y</Required>
<MaximumValue>128</MaximumValue>
<ValidationMessage>Network mask must be between 0 and 128.</ValidationMessage>
</netmask>
<area type="TextField">
<Required>Y</Required>
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
</area>
<arearange type="TextField"/>
<linkedPrefixlistIn type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.ospf6</source>
<items>prefixlists.prefixlist</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Prefix-List item not found</ValidationMessage>
</linkedPrefixlistIn>
<linkedPrefixlistOut type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.ospf6</source>
<items>prefixlists.prefixlist</items>
<display>name</display>
<group>name</group>
</template>
</Model>
<ValidationMessage>Related Prefix-List item not found</ValidationMessage>
</linkedPrefixlistOut>
</network>
</networks>
<interfaces>
<interface type="ArrayField">
<enabled type="BooleanField">
@@ -46,16 +102,12 @@
<Required>Y</Required>
</enabled>
<interfacename type="InterfaceField">
<Required>N</Required>
<multiple>N</multiple>
<default></default>
<AllowDynamic>Y</AllowDynamic>
<filters>
<enable>/^(?!0).*$/</enable>
</filters>
</interfacename>
<area type="TextField">
<default></default>
<Required>Y</Required>
<mask>/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/</mask>
</area>
@@ -64,66 +116,45 @@
<Required>Y</Required>
</passive>
<cost type="IntegerField">
<default></default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>4294967295</MaximumValue>
<ValidationMessage>Cost must be between 0 and 4294967295.</ValidationMessage>
</cost>
<cost_demoted type="IntegerField">
<default>65535</default>
<MinimumValue>1</MinimumValue>
<Required>N</Required>
<MaximumValue>65535</MaximumValue>
<ValidationMessage>Cost must be between 1 and 65535.</ValidationMessage>
</cost_demoted>
<carp_depend_on type="VirtualIPField">
<type>carp</type>
<Required>N</Required>
</carp_depend_on>
<hellointerval type="IntegerField">
<default></default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>4294967295</MaximumValue>
<ValidationMessage>Hello interval must be between 0 and 4294967295.</ValidationMessage>
</hellointerval>
<deadinterval type="IntegerField">
<default></default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>4294967295</MaximumValue>
<ValidationMessage>Dead interval must be between 0 and 4294967295.</ValidationMessage>
</deadinterval>
<retransmitinterval type="IntegerField">
<default></default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>4294967295</MaximumValue>
<ValidationMessage>Retransmit interval must be between 0 and 4294967295.</ValidationMessage>
</retransmitinterval>
<transmitdelay type="IntegerField">
<default></default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>4294967295</MaximumValue>
<ValidationMessage>Transmit delay must be between 0 and 4294967295.</ValidationMessage>
</transmitdelay>
<priority type="IntegerField">
<default></default>
<MinimumValue>0</MinimumValue>
<Required>N</Required>
<MaximumValue>4294967295</MaximumValue>
<ValidationMessage>Priority must be between 0 and 4294967295.</ValidationMessage>
</priority>
<bfd type="BooleanField">
<default>0</default>
<Required>N</Required>
</bfd>
<bfd type="BooleanField"/>
<networktype type="OptionField">
<Required>N</Required>
<multiple>N</multiple>
<default></default>
<OptionValues>
<broadcast>Broadcast multi-access network</broadcast>
<point-to-point>Point-to-point network</point-to-point>
@@ -131,5 +162,67 @@
</networktype>
</interface>
</interfaces>
<prefixlists>
<prefixlist type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<name type="TextField">
<Required>Y</Required>
<mask>/^([0-9a-zA-Z\._\-]){1,64}$/u</mask>
<ValidationMessage>The name should only contain alphanumeric characters, dashes, underscores or a dot.</ValidationMessage>
</name>
<seqnumber type="IntegerField">
<Required>Y</Required>
<MinimumValue>10</MinimumValue>
<MaximumValue>99</MaximumValue>
</seqnumber>
<action type="OptionField">
<Required>Y</Required>
<OptionValues>
<permit>Permit</permit>
<deny>Deny</deny>
</OptionValues>
</action>
<network type="TextField">
<Required>Y</Required>
</network>
</prefixlist>
</prefixlists>
<routemaps>
<routemap type="ArrayField">
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
<name type="TextField">
<Required>Y</Required>
</name>
<action type="OptionField">
<Required>Y</Required>
<OptionValues>
<permit>Permit</permit>
<deny>Deny</deny>
</OptionValues>
</action>
<id type="IntegerField">
<Required>Y</Required>
<MinimumValue>10</MinimumValue>
<MaximumValue>99</MaximumValue>
</id>
<match2 type="ModelRelationField">
<Model>
<template>
<source>OPNsense.quagga.ospf6</source>
<items>prefixlists.prefixlist</items>
<display>name</display>
</template>
</Model>
<ValidationMessage>Related item not found</ValidationMessage>
</match2>
<set type="TextField"/>
</routemap>
</routemaps>
</items>
</model>
@@ -1,8 +1,7 @@
{#
OPNsense® is Copyright © 2014 2023 by Deciso B.V.
This file is Copyright © 2017 by Fabian Franz
This file is Copyright © 2017 by Michael Muenz <m.muenz@gmail.com>
Copyright (c) 2014 2024 by Deciso B.V.
Copyright (c) 2017 by Fabian Franz
Copyright (c) Michael Muenz <m.muenz@gmail.com></m.muenz>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -27,22 +26,130 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
#}
<script>
'use strict';
$( document ).ready(function () {
mapDataToFormUI({'frm_ospf6_settings':"/api/quagga/ospf6settings/get"}).done(function(data){
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
});
<!-- Navigation bar -->
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
<li class="active"><a data-toggle="tab" href="#general">{{ lang._('General') }}</a></li>
<li><a data-toggle="tab" href="#interfaces">{{ lang._('Interfaces') }}</a></li>
</ul>
<div class="tab-content content-box tab-content">
<div id="general" class="tab-pane fade in active">
<div class="content-box" style="padding-bottom: 1.5em;">
{{ partial("layout_partials/base_form",['fields':ospf6Form,'id':'frm_ospf6_settings'])}}
<div class="col-md-12">
<hr />
<button class="btn btn-primary" id="saveAct" type="button"><b>{{ lang._('Save') }}</b> <i id="saveAct_progress"></i></button>
</div>
</div>
updateServiceControlUI('quagga');
// link save button to API set action
$("#saveAct").SimpleActionButton({
onPreAction: function() {
const dfObj = new $.Deferred();
saveFormToEndpoint("/api/quagga/ospf6settings/set", 'frm_ospf6_settings', function(){
dfObj.resolve();
});
return dfObj;
}
});
$("#grid-networks").UIBootgrid({
'search':'/api/quagga/ospf6settings/searchNetwork',
'get':'/api/quagga/ospf6settings/getNetwork/',
'set':'/api/quagga/ospf6settings/setNetwork/',
'add':'/api/quagga/ospf6settings/addNetwork/',
'del':'/api/quagga/ospf6settings/delNetwork/',
'toggle':'/api/quagga/ospf6settings/toggleNetwork/',
'options':{
selection:false,
multiSelect:false
}
});
$("#grid-interfaces").UIBootgrid({
'search':'/api/quagga/ospf6settings/searchInterface',
'get':'/api/quagga/ospf6settings/getInterface/',
'set':'/api/quagga/ospf6settings/setInterface/',
'add':'/api/quagga/ospf6settings/addInterface/',
'del':'/api/quagga/ospf6settings/delInterface/',
'toggle':'/api/quagga/ospf6settings/toggleInterface/',
'options':{
selection:false,
multiSelect:false
}
});
$("#grid-prefixlists").UIBootgrid({
'search':'/api/quagga/ospf6settings/searchPrefixlist',
'get':'/api/quagga/ospf6settings/getPrefixlist/',
'set':'/api/quagga/ospf6settings/setPrefixlist/',
'add':'/api/quagga/ospf6settings/addPrefixlist/',
'del':'/api/quagga/ospf6settings/delPrefixlist/',
'toggle':'/api/quagga/ospf6settings/togglePrefixlist/',
'options':{
selection:false,
multiSelect:false
}
});
$("#grid-routemaps").UIBootgrid({
'search':'/api/quagga/ospf6settings/searchRoutemap',
'get':'/api/quagga/ospf6settings/getRoutemap/',
'set':'/api/quagga/ospf6settings/setRoutemap/',
'add':'/api/quagga/ospf6settings/addRoutemap/',
'del':'/api/quagga/ospf6settings/delRoutemap/',
'toggle':'/api/quagga/ospf6settings/toggleRoutemap/',
'options':{
selection:false,
multiSelect:false
}
});
// hook checkbox item with conditional options
$("#ospf6\\.originate").change(function(){
if ($(this).is(':checked')) {
$(".ospf6_originate").closest('tr').show();
} else {
$(".ospf6_originate").closest('tr').hide();
}
});
});
</script>
<!-- Navigation bar -->
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
<li class="active"><a data-toggle="tab" href="#general">{{ lang._('General') }}</a></li>
<li><a data-toggle="tab" href="#networks">{{ lang._('Networks') }}</a></li>
<li><a data-toggle="tab" href="#interfaces">{{ lang._('Interfaces') }}</a></li>
<li><a data-toggle="tab" href="#prefixlists">{{ lang._('Prefix Lists') }}</a></li>
<li><a data-toggle="tab" href="#routemaps">{{ lang._('Route Maps') }}</a></li>
</ul>
<div class="tab-content content-box tab-content">
<div id="general" class="tab-pane fade in active">
<div class="content-box" style="padding-bottom: 1.5em;">
{{ partial("layout_partials/base_form",['fields':ospf6Form,'id':'frm_ospf6_settings'])}}
</div>
</div>
<!-- Tab: Networks -->
<div id="networks" class="tab-pane fade in">
<table id="grid-networks" class="table table-responsive" data-editDialog="DialogEditNetwork">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="ipaddr" data-type="string" data-visible="true">{{ lang._('Network Address') }}</th>
<th data-column-id="netmask" data-type="string" data-visible="true">{{ lang._('Mask') }}</th>
<th data-column-id="area" data-type="string" data-visible="true">{{ lang._('Area') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
<!-- Tab: Interfaces -->
<div id="interfaces" class="tab-pane fade in">
@@ -64,66 +171,85 @@ POSSIBILITY OF SUCH DAMAGE.
<td colspan="5"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button type="button" class="btn btn-xs reload_btn btn-primary"><span class="fa fa-refresh reloadAct_progress"></span> {{ lang._('Reload Service') }}</button>
</td>
</tr>
</tfoot>
</table>
</div>
<!-- Tab: Prefix Lists -->
<div id="prefixlists" class="tab-pane fade in">
<table id="grid-prefixlists" class="table table-responsive" data-editDialog="DialogEditPrefixLists">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowt
oggle" data-sortable="false">{{ lang._('Enabled') }}</th>
<th data-column-id="name" data-type="string" data-visible="true" data-sortable="true">{{ lang._('Name') }}</th>
<th data-column-id="seqnumber" data-type="string" data-visible="true" data-sortable="true">{{ lang._('Sequence Number') }}</th>
<th data-column-id="action" data-type="string" data-visible="true" data-sortable="false">{{ lang._('Action') }}</th>
<th data-column-id="network" data-type="string" data-visible="true" data-sortable="false">{{ lang._('Network') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
<script>
<!-- Tab: Route Maps -->
<div id="routemaps" class="tab-pane fade in">
<table id="grid-routemaps" class="table table-responsive" data-editDialog="DialogEditRouteMaps">
<thead>
<tr>
<th data-column-id="enabled" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="name" data-type="string" data-visible="true">{{ lang._('Name') }}</th>
<th data-column-id="action" data-type="string" data-visible="true">{{ lang._('Action') }}</th>
<th data-column-id="id" data-type="string" data-visible="true">{{ lang._('ID') }}</th>
<th data-column-id="match2" data-type="string" data-visible="true">{{ lang._('Prefix List') }}</th>
<th data-column-id="set" data-type="string" data-visible="true">{{ lang._('Set') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="5"></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
$( document ).ready(function() {
var data_get_map = {'frm_ospf6_settings':"/api/quagga/ospf6settings/get"};
mapDataToFormUI(data_get_map).done(function(data){
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
});
<section class="page-content-main">
<div class="content-box">
<div class="col-md-12">
<button class="btn btn-primary __mb __mt" id="saveAct"
data-endpoint='/api/quagga/service/reconfigure'
data-label="{{ lang._('Apply') }}"
data-error-title="{{ lang._('Error reconfiguring OSPFv3') }}"
data-service-widget="quagga"
type="button"
></button>
</div>
</div>
</section>
updateServiceControlUI('quagga');
// link save button to API set action
$("#saveAct").click(function(){
saveFormToEndpoint(url="/api/quagga/ospf6settings/set",formid='frm_ospf6_settings',callback_ok=function(){
$("#saveAct_progress").addClass("fa fa-spinner fa-pulse");
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
updateServiceControlUI('quagga');
$("#saveAct_progress").removeClass("fa fa-spinner fa-pulse");
});
});
});
/* allow a user to manually reload the service (for forms which do not do it automatically) */
$('.reload_btn').click(function reload_handler() {
$(".reloadAct_progress").addClass("fa-spin");
ajaxCall(url="/api/quagga/service/reconfigure", sendData={}, callback=function(data,status) {
updateServiceControlUI('quagga');
$(".reloadAct_progress").removeClass("fa-spin");
});
});
$("#grid-interfaces").UIBootgrid(
{ 'search':'/api/quagga/ospf6settings/searchInterface',
'get':'/api/quagga/ospf6settings/getInterface/',
'set':'/api/quagga/ospf6settings/setInterface/',
'add':'/api/quagga/ospf6settings/addInterface/',
'del':'/api/quagga/ospf6settings/delInterface/',
'toggle':'/api/quagga/ospf6settings/toggleInterface/',
'options':{selection:false, multiSelect:false}
}
);
// hook checkbox item with conditional options
$(".opt_checkbox").change(function(){
if ($(this).is(':checked')) {
$("." + $(this).attr('id').replace('.', '_')).closest('tr').show();
} else {
$("." + $(this).attr('id').replace('.', '_')).closest('tr').hide();
}
});
});
</script>
{{ partial("layout_partials/base_dialog",['fields':formDialogEditNetwork,'id':'DialogEditNetwork','label':lang._('Edit Network')])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditInterface,'id':'DialogEditInterface','label':lang._('Edit Interface')])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditPrefixLists,'id':'DialogEditPrefixLists','label':lang._('Edit Prefix Lists')])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditRouteMaps,'id':'DialogEditRouteMaps','label':lang._('Edit Route Maps')])}}
@@ -2,13 +2,13 @@
ipv6 ospf6 {{ directive }} {{ modelname }}
{% endif %}{%- endmacro %}
{% from 'OPNsense/Macros/interface.macro' import physical_interface %}
{% if helpers.exists('OPNsense.quagga.ospf6.enabled') and OPNsense.quagga.ospf6.enabled == '1' %}
{% if not helpers.empty('OPNsense.quagga.ospf6.enabled') %}
!
! Zebra configuration saved from vty
! 2017/03/03 20:21:04
!
{% if helpers.exists('OPNsense.quagga.general') %}
{% if helpers.exists('OPNsense.quagga.general.enablesyslog') and OPNsense.quagga.general.enablesyslog == '1' %}
{% if not helpers.empty('OPNsense.quagga.general.enablesyslog') %}
log syslog {{ OPNsense.quagga.general.sysloglevel }}
{% endif %}
{% if helpers.exists('OPNsense.quagga.general.profile') %}
@@ -21,9 +21,8 @@ agentx
!
!
!
{% if helpers.exists('OPNsense.quagga.ospf6.interfaces.interface') %}
{% for interface in helpers.toList('OPNsense.quagga.ospf6.interfaces.interface') %}
{% if interface.enabled == '1' %}
{% for interface in helpers.toList('OPNsense.quagga.ospf6.interfaces.interface') %}
{% if interface.enabled == '1' %}
interface {{ physical_interface(interface.interfacename) }}
{% if interface.bfd|default('') == '1' %}
ipv6 ospf6 bfd
@@ -40,22 +39,48 @@ interface {{ physical_interface(interface.interfacename) }}
}}{{ cline("priority",interface.priority)
}}{{ cline("retransmit-interval",interface.retransmitinterval)
}}!
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% endfor %}
!
router ospf6
{% if helpers.exists('OPNsense.quagga.ospf6.routerid') and OPNsense.quagga.ospf6.routerid != '' %}
{% if not helpers.empty('OPNsense.quagga.ospf6.routerid') %}
ospf6 router-id {{ OPNsense.quagga.ospf6.routerid }}
{% endif %}
{% if not helpers.empty('OPNsense.quagga.ospf6.originate') %}
default-information originate{% if not helpers.empty('OPNsense.quagga.ospf6.originatealways') %} always {% endif %}{% if OPNsense.quagga.ospf6.originatemetric|default('') != '' %} metric {{ OPNsense.quagga.ospf6.originatemetric }}{% endif %}
{% endif %}
{% if helpers.exists('OPNsense.quagga.ospf6.redistribute') and OPNsense.quagga.ospf6.redistribute != '' %}
{% if not helpers.empty('OPNsense.quagga.ospf6.redistribute')%}
{% for line in OPNsense.quagga.ospf6.redistribute.split(',') %}
{% if not helpers.empty('OPNsense.quagga.ospf6.redistributemap') %}{% set line = line + " route-map " + helpers.getUUID(OPNsense.quagga.ospf6.redistributemap).name %}{% endif %}
redistribute {{ line }}
{% endfor %}{% endif %}
{% if helpers.exists('OPNsense.quagga.ospf6.networks.network') %}
{% for network in helpers.toList('OPNsense.quagga.ospf6.networks.network') %}
{% if network.enabled == '1' %}
network {{ network.ipaddr }}/{{ network.netmask }} area {{ network.area }}
{% endif %}
{% if network.arearange|default("") != "" %}
area {{ network.area }} range {{ network.arearange }}
{% endif %}
{% if network.linkedPrefixlistIn|default("") != "" %}
{% for prefixlist in network.linkedPrefixlistIn.split(",") %}
{% set prefixlist2_data = helpers.getUUID(prefixlist) %}
{% if prefixlist2_data != {} and prefixlist2_data.enabled == '1' %}
area {{ network.area }} filter-list prefix {{ prefixlist2_data.name }} in
{% endif %}
{% endfor %}
{% endif %}
{% if network.linkedPrefixlistOut|default("") != "" %}
{% for prefixlist in network.linkedPrefixlistOut.split(",") %}
{% set prefixlist_data = helpers.getUUID(prefixlist) %}
{% if prefixlist_data != {} and prefixlist_data.enabled == '1' %}
area {{ network.area }} filter-list prefix {{ prefixlist_data.name }} out
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% if helpers.exists('OPNsense.quagga.ospf6.interfaces.interface') %}
{% for interface in helpers.toList('OPNsense.quagga.ospf6.interfaces.interface') %}
{% if interface.enabled == '1' %}
@@ -64,6 +89,33 @@ router ospf6
{% endfor %}
{% endif %}
!
{% if helpers.exists('OPNsense.quagga.ospf6.prefixlists.prefixlist') %}
{% for prefixlist in helpers.sortDictList(OPNsense.quagga.ospf6.prefixlists.prefixlist, 'name', 'seqnumber' ) %}
{% if prefixlist.enabled == '1' %}
ip prefix-list {{ prefixlist.name }} seq {{ prefixlist.seqnumber }} {{ prefixlist.action }} {{ prefixlist.network }}
{% endif %}
{% endfor %}
{% endif %}
!
{% if helpers.exists('OPNsense.quagga.ospf6.routemaps.routemap') %}
{% for routemap in helpers.sortDictList(OPNsense.quagga.ospf6.routemaps.routemap, 'name', 'id' ) %}
{% if routemap.enabled == '1' %}
route-map {{ routemap.name }} {{ routemap.action }} {{ routemap.id }}
{% if routemap.match2|default("") != "" %}
{% for prefixlist in routemap.match2.split(",") %}
{% set prefixlist_data = helpers.getUUID(prefixlist) %}
{% if 'match2' in routemap and routemap.match2 != '' %}
match ip address prefix-list {{ prefixlist_data.name }}
{% endif %}
{% endfor %}
{% endif %}
{% if routemap.set|default("") != "" %}
set {{ routemap.set }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
!
line vty
!
{% endif %}