Page MenuHomeVyOS Platform

No OneTemporary

Size
246 KB
Referenced Files
None
Subscribers
None
diff --git a/data/templates/frr/vrf.route-map.frr.j2 b/data/templates/frr/vrf.route-map.frr.j2
deleted file mode 100644
index 5e0c56a7b..000000000
--- a/data/templates/frr/vrf.route-map.frr.j2
+++ /dev/null
@@ -1,10 +0,0 @@
-!
-{% if vrf is vyos_defined and route_map is vyos_defined %}
-vrf {{ vrf }}
- ip protocol {{ protocol }} route-map {{ route_map }}
- exit-vrf
-!
-{% elif route_map is vyos_defined %}
-ip protocol {{ protocol }} route-map {{ route_map }}
-{% endif %}
-!
diff --git a/data/templates/frr/vrf.route-map.v6.frr.j2 b/data/templates/frr/vrf.route-map.v6.frr.j2
deleted file mode 100644
index 7dc59a046..000000000
--- a/data/templates/frr/vrf.route-map.v6.frr.j2
+++ /dev/null
@@ -1,10 +0,0 @@
-!
-{% if vrf is vyos_defined and route_map is vyos_defined %}
-vrf {{ vrf }}
- ipv6 protocol {{ protocol }} route-map {{ route_map }}
- exit-vrf
-!
-{% elif route_map is vyos_defined %}
-ipv6 protocol {{ protocol }} route-map {{ route_map }}
-{% endif %}
-!
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index a9122db57..527eaf991 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -1,1578 +1,1577 @@
<!-- include start from bgp/protocol-common-config.xml.i -->
<node name="address-family">
<properties>
<help>BGP address-family parameters</help>
</properties>
<children>
<node name="ipv4-unicast">
<properties>
<help>IPv4 BGP settings</help>
</properties>
<children>
<tagNode name="aggregate-address">
<properties>
<help>BGP aggregate network</help>
<valueHelp>
<format>ipv4net</format>
<description>BGP aggregate network</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-aggregate-address.xml.i>
</children>
</tagNode>
<node name="distance">
<properties>
<help>Administrative distances for BGP routes</help>
</properties>
<children>
<leafNode name="external">
<properties>
<help>eBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>eBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="internal">
<properties>
<help>iBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>iBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="local">
<properties>
<help>Locally originated BGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>Locally originated BGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<tagNode name="prefix">
<properties>
<help>Administrative distance for a specific BGP prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>Administrative distance for a specific BGP prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="distance">
<properties>
<help>Administrative distance for prefix</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for external BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
#include <include/bgp/afi-export-import.xml.i>
#include <include/bgp/afi-label.xml.i>
#include <include/bgp/afi-maximum-paths.xml.i>
<tagNode name="network">
<properties>
<help>BGP network</help>
<valueHelp>
<format>ipv4net</format>
<description>BGP network</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="backdoor">
<properties>
<help>Network as a backdoor route</help>
<valueless/>
</properties>
</leafNode>
#include <include/route-map.xml.i>
</children>
</tagNode>
#include <include/bgp/afi-rd.xml.i>
#include <include/bgp/afi-route-map-vpn.xml.i>
#include <include/bgp/afi-route-target-vpn.xml.i>
<node name="redistribute">
<properties>
<help>Redistribute routes from other protocols into BGP</help>
</properties>
<children>
<node name="connected">
<properties>
<help>Redistribute connected routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="isis">
<properties>
<help>Redistribute IS-IS routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="kernel">
<properties>
<help>Redistribute kernel routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="ospf">
<properties>
<help>Redistribute OSPF routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="rip">
<properties>
<help>Redistribute RIP routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="babel">
<properties>
<help>Redistribute Babel routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="static">
<properties>
<help>Redistribute static routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<leafNode name="table">
<properties>
<help>Redistribute non-main Kernel Routing Table</help>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<node name="ipv4-multicast">
<properties>
<help>Multicast IPv4 BGP settings</help>
</properties>
<children>
<tagNode name="aggregate-address">
<properties>
<help>BGP aggregate network/prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>BGP aggregate network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-aggregate-address.xml.i>
</children>
</tagNode>
<node name="distance">
<properties>
<help>Administrative distances for BGP routes</help>
</properties>
<children>
<leafNode name="external">
<properties>
<help>eBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>eBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="internal">
<properties>
<help>iBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>iBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="local">
<properties>
<help>Locally originated BGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>Locally originated BGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<tagNode name="prefix">
<properties>
<help>Administrative distance for a specific BGP prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>Administrative distance for a specific BGP prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="distance">
<properties>
<help>Administrative distance for prefix</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for external BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
<tagNode name="network">
<properties>
<help>Import BGP network/prefix into multicast IPv4 RIB</help>
<valueHelp>
<format>ipv4net</format>
<description>Multicast IPv4 BGP network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="backdoor">
<properties>
<help>Use BGP network/prefix as a backdoor route</help>
<valueless/>
</properties>
</leafNode>
#include <include/route-map.xml.i>
</children>
</tagNode>
</children>
</node>
<node name="ipv4-labeled-unicast">
<properties>
<help>Labeled Unicast IPv4 BGP settings</help>
</properties>
<children>
<tagNode name="aggregate-address">
<properties>
<help>BGP aggregate network/prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>BGP aggregate network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-aggregate-address.xml.i>
</children>
</tagNode>
<tagNode name="network">
<properties>
<help>Import BGP network/prefix into labeled unicast IPv4 RIB</help>
<valueHelp>
<format>ipv4net</format>
<description>Labeled Unicast IPv4 BGP network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="backdoor">
<properties>
<help>Use BGP network/prefix as a backdoor route</help>
<valueless/>
</properties>
</leafNode>
#include <include/route-map.xml.i>
</children>
</tagNode>
</children>
</node>
<node name="ipv4-flowspec">
<properties>
<help>Flowspec IPv4 BGP settings</help>
</properties>
<children>
<node name="local-install">
<properties>
<help>Apply local policy routing to interface</help>
</properties>
<children>
<leafNode name="interface">
<properties>
<help>Interface</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
<multi/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<node name="ipv4-vpn">
<properties>
<help>Unicast VPN IPv4 BGP settings</help>
</properties>
<children>
<tagNode name="network">
<properties>
<help>Import BGP network/prefix into unicast VPN IPv4 RIB</help>
<valueHelp>
<format>ipv4net</format>
<description>Unicast VPN IPv4 BGP network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/route-distinguisher.xml.i>
<leafNode name="label">
<properties>
<help>MPLS label value assigned to route</help>
<valueHelp>
<format>u32:0-1048575</format>
<description>MPLS label value</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-1048575"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
<node name="ipv6-unicast">
<properties>
<help>IPv6 BGP settings</help>
</properties>
<children>
<tagNode name="aggregate-address">
<properties>
<help>BGP aggregate network</help>
<valueHelp>
<format>ipv6net</format>
<description>Aggregate network</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-aggregate-address.xml.i>
</children>
</tagNode>
<node name="distance">
<properties>
<help>Administrative distances for BGP routes</help>
</properties>
<children>
<leafNode name="external">
<properties>
<help>eBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>eBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="internal">
<properties>
<help>iBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>iBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="local">
<properties>
<help>Locally originated BGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>Locally originated BGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<tagNode name="prefix">
<properties>
<help>Administrative distance for a specific BGP prefix</help>
<valueHelp>
<format>ipv6net</format>
<description>Administrative distance for a specific BGP prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="distance">
<properties>
<help>Administrative distance for prefix</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for external BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
#include <include/bgp/afi-export-import.xml.i>
#include <include/bgp/afi-label.xml.i>
#include <include/bgp/afi-maximum-paths.xml.i>
<tagNode name="network">
<properties>
<help>BGP network</help>
<valueHelp>
<format>ipv6net</format>
<description>Aggregate network</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-path-limit.xml.i>
#include <include/route-map.xml.i>
</children>
</tagNode>
#include <include/bgp/afi-rd.xml.i>
#include <include/bgp/afi-route-map-vpn.xml.i>
#include <include/bgp/afi-route-target-vpn.xml.i>
<node name="redistribute">
<properties>
<help>Redistribute routes from other protocols into BGP</help>
</properties>
<children>
<node name="connected">
<properties>
<help>Redistribute connected routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="kernel">
<properties>
<help>Redistribute kernel routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="ospfv3">
<properties>
<help>Redistribute OSPFv3 routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="ripng">
<properties>
<help>Redistribute RIPng routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="babel">
<properties>
<help>Redistribute Babel routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<node name="static">
<properties>
<help>Redistribute static routes into BGP</help>
</properties>
<children>
#include <include/bgp/afi-redistribute-metric-route-map.xml.i>
</children>
</node>
<leafNode name="table">
<properties>
<help>Redistribute non-main Kernel Routing Table</help>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<node name="ipv6-multicast">
<properties>
<help>Multicast IPv6 BGP settings</help>
</properties>
<children>
<tagNode name="aggregate-address">
<properties>
<help>BGP aggregate network/prefix</help>
<valueHelp>
<format>ipv6net</format>
<description>BGP aggregate network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-aggregate-address.xml.i>
</children>
</tagNode>
<node name="distance">
<properties>
<help>Administrative distances for BGP routes</help>
</properties>
<children>
<leafNode name="external">
<properties>
<help>eBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>eBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="internal">
<properties>
<help>iBGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>iBGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="local">
<properties>
<help>Locally originated BGP routes administrative distance</help>
<valueHelp>
<format>u32:1-255</format>
<description>Locally originated BGP routes administrative distance</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<tagNode name="prefix">
<properties>
<help>Administrative distance for a specific BGP prefix</help>
<valueHelp>
<format>ipv6net</format>
<description>Administrative distance for a specific BGP prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="distance">
<properties>
<help>Administrative distance for prefix</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for external BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
<tagNode name="network">
<properties>
<help>Import BGP network/prefix into multicast IPv6 RIB</help>
<valueHelp>
<format>ipv6net</format>
<description>Multicast IPv6 BGP network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-path-limit.xml.i>
#include <include/route-map.xml.i>
</children>
</tagNode>
</children>
</node>
<node name="ipv6-labeled-unicast">
<properties>
<help>Labeled Unicast IPv6 BGP settings</help>
</properties>
<children>
<tagNode name="aggregate-address">
<properties>
<help>BGP aggregate network/prefix</help>
<valueHelp>
<format>ipv6net</format>
<description>BGP aggregate network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-aggregate-address.xml.i>
</children>
</tagNode>
<tagNode name="network">
<properties>
<help>Import BGP network/prefix into labeled unicast IPv6 RIB</help>
<valueHelp>
<format>ipv6net</format>
<description>Labeled Unicast IPv6 BGP network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="backdoor">
<properties>
<help>Use BGP network/prefix as a backdoor route</help>
<valueless/>
</properties>
</leafNode>
#include <include/route-map.xml.i>
</children>
</tagNode>
</children>
</node>
<node name="ipv6-flowspec">
<properties>
<help>Flowspec IPv6 BGP settings</help>
</properties>
<children>
<node name="local-install">
<properties>
<help>Apply local policy routing to interface</help>
</properties>
<children>
<leafNode name="interface">
<properties>
<help>Interface</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
<multi/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<node name="ipv6-vpn">
<properties>
<help>Unicast VPN IPv6 BGP settings</help>
</properties>
<children>
<tagNode name="network">
<properties>
<help>Import BGP network/prefix into unicast VPN IPv6 RIB</help>
<valueHelp>
<format>ipv6net</format>
<description>Unicast VPN IPv6 BGP network/prefix</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/route-distinguisher.xml.i>
<leafNode name="label">
<properties>
<help>MPLS label value assigned to route</help>
<valueHelp>
<format>u32:0-1048575</format>
<description>MPLS label value</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-1048575"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
<node name="l2vpn-evpn">
<properties>
<help>L2VPN EVPN BGP settings</help>
</properties>
<children>
<node name="advertise">
<properties>
<help>Advertise prefix routes</help>
</properties>
<children>
<node name="ipv4">
<properties>
<help>IPv4 address family</help>
</properties>
<children>
#include <include/bgp/afi-l2vpn-advertise.xml.i>
</children>
</node>
<node name="ipv6">
<properties>
<help>IPv6 address family</help>
</properties>
<children>
#include <include/bgp/afi-l2vpn-advertise.xml.i>
</children>
</node>
</children>
</node>
<leafNode name="advertise-all-vni">
<properties>
<help>Advertise All local VNIs</help>
<valueless/>
</properties>
</leafNode>
#include <include/bgp/afi-l2vpn-common.xml.i>
<leafNode name="advertise-pip">
<properties>
<help>EVPN system primary IP</help>
<valueHelp>
<format>ipv4</format>
<description>IP address</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
<leafNode name="rt-auto-derive">
<properties>
<help>Auto derivation of Route Target (RFC8365)</help>
<valueless/>
</properties>
</leafNode>
<node name="flooding">
<properties>
<help>Specify handling for BUM packets</help>
</properties>
<children>
<leafNode name="disable">
<properties>
<help>Do not flood any BUM packets</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="head-end-replication">
<properties>
<help>Flood BUM packets using head-end replication</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<tagNode name="vni">
<properties>
<help>VXLAN Network Identifier</help>
<valueHelp>
<format>u32:1-16777215</format>
<description>VNI number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-16777215"/>
</constraint>
</properties>
<children>
#include <include/bgp/afi-l2vpn-common.xml.i>
</children>
</tagNode>
</children>
</node>
</children>
</node>
<node name="listen">
<properties>
<help>Listen for and accept BGP dynamic neighbors from range</help>
</properties>
<children>
<leafNode name="limit">
<properties>
<help>Maximum number of dynamic neighbors that can be created</help>
<valueHelp>
<format>u32:1-5000</format>
<description>BGP neighbor limit</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-5000"/>
</constraint>
</properties>
</leafNode>
<tagNode name="range">
<properties>
<help>BGP dynamic neighbors listen range</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 dynamic neighbors listen range</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 dynamic neighbors listen range</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
#include <include/bgp/peer-group.xml.i>
</children>
</tagNode>
</children>
</node>
<leafNode name="system-as">
<properties>
<help>Autonomous System Number (ASN)</help>
<valueHelp>
<format>u32:1-4294967294</format>
<description>Autonomous System Number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4294967294"/>
</constraint>
</properties>
</leafNode>
<tagNode name="neighbor">
<properties>
<help>BGP neighbor</help>
<valueHelp>
<format>ipv4</format>
<description>BGP neighbor IP address</description>
</valueHelp>
<valueHelp>
<format>ipv6</format>
<description>BGP neighbor IPv6 address</description>
</valueHelp>
<valueHelp>
<format>txt</format>
<description>Interface name</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
<validator name="ipv6-address"/>
#include <include/constraint/interface-name.xml.i>
</constraint>
</properties>
<children>
<node name="address-family">
<properties>
<help>Address-family parameters</help>
</properties>
<children>
#include <include/bgp/neighbor-afi-ipv4-unicast.xml.i>
#include <include/bgp/neighbor-afi-ipv6-unicast.xml.i>
#include <include/bgp/neighbor-afi-ipv4-labeled-unicast.xml.i>
#include <include/bgp/neighbor-afi-ipv6-labeled-unicast.xml.i>
#include <include/bgp/neighbor-afi-ipv4-vpn.xml.i>
#include <include/bgp/neighbor-afi-ipv6-vpn.xml.i>
#include <include/bgp/neighbor-afi-ipv4-flowspec.xml.i>
#include <include/bgp/neighbor-afi-ipv6-flowspec.xml.i>
#include <include/bgp/neighbor-afi-ipv4-multicast.xml.i>
#include <include/bgp/neighbor-afi-ipv6-multicast.xml.i>
#include <include/bgp/neighbor-afi-l2vpn-evpn.xml.i>
</children>
</node>
<leafNode name="advertisement-interval">
<properties>
<help>Minimum interval for sending routing updates</help>
<valueHelp>
<format>u32:0-600</format>
<description>Advertisement interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-600"/>
</constraint>
</properties>
</leafNode>
#include <include/generic-description.xml.i>
#include <include/bgp/neighbor-bfd.xml.i>
#include <include/bgp/neighbor-capability.xml.i>
#include <include/bgp/neighbor-disable-capability-negotiation.xml.i>
#include <include/bgp/neighbor-disable-connected-check.xml.i>
#include <include/bgp/neighbor-ebgp-multihop.xml.i>
#include <include/bgp/neighbor-graceful-restart.xml.i>
<node name="interface">
<properties>
<help>Interface parameters</help>
</properties>
<children>
#include <include/bgp/peer-group.xml.i>
#include <include/bgp/remote-as.xml.i>
#include <include/source-interface.xml.i>
<node name="v6only">
<properties>
<help>Enable BGP with v6 link-local only</help>
</properties>
<children>
#include <include/bgp/peer-group.xml.i>
#include <include/bgp/remote-as.xml.i>
</children>
</node>
</children>
</node>
#include <include/bgp/neighbor-local-as.xml.i>
#include <include/bgp/neighbor-local-role.xml.i>
#include <include/bgp/neighbor-override-capability.xml.i>
#include <include/bgp/neighbor-path-attribute.xml.i>
#include <include/bgp/neighbor-passive.xml.i>
#include <include/bgp/neighbor-password.xml.i>
#include <include/bgp/peer-group.xml.i>
#include <include/bgp/remote-as.xml.i>
#include <include/bgp/neighbor-shutdown.xml.i>
<leafNode name="solo">
<properties>
<help>Do not send back prefixes learned from the neighbor</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="strict-capability-match">
<properties>
<help>Enable strict capability negotiation</help>
<valueless/>
</properties>
</leafNode>
<node name="timers">
<properties>
<help>Neighbor timers</help>
</properties>
<children>
<leafNode name="connect">
<properties>
<help>BGP connect timer for this neighbor</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Connect timer in seconds</description>
</valueHelp>
<valueHelp>
<format>0</format>
<description>Disable connect timer</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-65535"/>
</constraint>
</properties>
</leafNode>
#include <include/bgp/timers-holdtime.xml.i>
#include <include/bgp/timers-keepalive.xml.i>
</children>
</node>
#include <include/bgp/neighbor-ttl-security.xml.i>
#include <include/bgp/neighbor-update-source.xml.i>
#include <include/port-number.xml.i>
</children>
</tagNode>
<node name="parameters">
<properties>
<help>BGP parameters</help>
</properties>
<children>
<leafNode name="always-compare-med">
<properties>
<help>Always compare MEDs from different neighbors</help>
<valueless/>
</properties>
</leafNode>
<node name="bestpath">
<properties>
<help>Default bestpath selection mechanism</help>
</properties>
<children>
<node name="as-path">
<properties>
<help>AS-path attribute comparison parameters</help>
</properties>
<children>
<leafNode name="confed">
<properties>
<help>Compare AS-path lengths including confederation sets and sequences</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="ignore">
<properties>
<help>Ignore AS-path length in selecting a route</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="multipath-relax">
<properties>
<help>Allow load sharing across routes that have different AS paths (but same length)</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="bandwidth">
<properties>
<help>Link Bandwidth attribute</help>
<completionHelp>
<list>default-weight-for-missing ignore skip-missing</list>
</completionHelp>
<valueHelp>
<format>default-weight-for-missing</format>
<description>Assign low default weight (1) to paths not having link bandwidth</description>
</valueHelp>
<valueHelp>
<format>ignore</format>
<description>Ignore link bandwidth (do regular ECMP, not weighted)</description>
</valueHelp>
<valueHelp>
<format>skip-missing</format>
<description>Ignore paths without link bandwidth for ECMP (if other paths have it)</description>
</valueHelp>
<constraint>
<regex>(default-weight-for-missing|ignore|skip-missing)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="compare-routerid">
<properties>
<help>Compare the router-id for identical EBGP paths</help>
<valueless/>
</properties>
</leafNode>
<node name="med">
<properties>
<help>MED attribute comparison parameters</help>
</properties>
<children>
<leafNode name="confed">
<properties>
<help>Compare MEDs among confederation paths</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="missing-as-worst">
<properties>
<help>Treat missing route as a MED as the least preferred one</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<node name="peer-type">
<properties>
<help>Peer type</help>
</properties>
<children>
<leafNode name="multipath-relax">
<properties>
<help>Allow load sharing across routes learned from different peer types</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<leafNode name="cluster-id">
<properties>
<help>Route-reflector cluster-id</help>
<valueHelp>
<format>ipv4</format>
<description>Route-reflector cluster-id</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
<node name="confederation">
<properties>
<help>AS confederation parameters</help>
</properties>
<children>
<leafNode name="identifier">
<properties>
<help>Confederation AS identifier</help>
<valueHelp>
<format>u32:1-4294967294</format>
<description>Confederation AS id</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4294967294"/>
</constraint>
</properties>
</leafNode>
<leafNode name="peers">
<properties>
<help>Peer ASs in the BGP confederation</help>
<valueHelp>
<format>u32:1-4294967294</format>
<description>Peer AS number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4294967294"/>
</constraint>
<multi/>
</properties>
</leafNode>
</children>
</node>
<node name="conditional-advertisement">
<properties>
<help>Conditional advertisement settings</help>
</properties>
<children>
<leafNode name="timer">
<properties>
<help>Set period to rescan BGP table to check if condition is met</help>
<valueHelp>
<format>u32:5-240</format>
<description>Period to rerun the conditional advertisement scanner process</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 5-240"/>
</constraint>
</properties>
<defaultValue>60</defaultValue>
</leafNode>
</children>
</node>
<node name="dampening">
<properties>
<help>Enable route-flap dampening</help>
</properties>
<children>
<leafNode name="half-life">
<properties>
<help>Half-life time for dampening</help>
<valueHelp>
<format>u32:1-45</format>
<description>Half-life penalty in minutes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-45"/>
</constraint>
</properties>
</leafNode>
<leafNode name="max-suppress-time">
<properties>
<help>Maximum duration to suppress a stable route</help>
<valueHelp>
<format>u32:1-255</format>
<description>Maximum suppress duration in minutes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="re-use">
<properties>
<help>Threshold to start reusing a route</help>
<valueHelp>
<format>u32:1-20000</format>
<description>Re-use penalty points</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-20000"/>
</constraint>
</properties>
</leafNode>
<leafNode name="start-suppress-time">
<properties>
<help>When to start suppressing a route</help>
<valueHelp>
<format>u32:1-20000</format>
<description>Start-suppress penalty points</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-20000"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<node name="default">
<properties>
<help>BGP defaults</help>
</properties>
<children>
<leafNode name="local-pref">
<properties>
<help>Default local preference</help>
<valueHelp>
<format>u32</format>
<description>Local preference</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="deterministic-med">
<properties>
<help>Compare MEDs between different peers in the same AS</help>
<valueless/>
</properties>
</leafNode>
<node name="distance">
<properties>
<help>Administratives distances for BGP routes</help>
</properties>
<children>
<node name="global">
<properties>
<help>Global administratives distances for BGP routes</help>
</properties>
<children>
<leafNode name="external">
<properties>
<help>Administrative distance for external BGP routes</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for external BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="internal">
<properties>
<help>Administrative distance for internal BGP routes</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for internal BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
<leafNode name="local">
<properties>
<help>Administrative distance for local BGP routes</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for internal BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<tagNode name="prefix">
<properties>
<help>Administrative distance for a specific BGP prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>Administrative distance for a specific BGP prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="distance">
<properties>
<help>Administrative distance for prefix</help>
<valueHelp>
<format>u32:1-255</format>
<description>Administrative distance for external BGP routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-255"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</node>
<leafNode name="ebgp-requires-policy">
<properties>
<help>Require in and out policy for eBGP peers (RFC8212)</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="fast-convergence">
<properties>
<help>Teardown sessions immediately whenever peer becomes unreachable</help>
<valueless/>
</properties>
</leafNode>
<node name="graceful-restart">
<properties>
<help>Graceful restart capability parameters</help>
</properties>
<children>
<leafNode name="stalepath-time">
<properties>
<help>Maximum time to hold onto restarting neighbors stale paths</help>
<valueHelp>
<format>u32:1-3600</format>
<description>Hold time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-3600"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="graceful-shutdown">
<properties>
<help>Graceful shutdown</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="log-neighbor-changes">
<properties>
<help>Log neighbor up/down changes and reset reason</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="minimum-holdtime">
<properties>
<help>BGP minimum holdtime</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Minimum holdtime in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="network-import-check">
<properties>
<help>Enable IGP route check for network statements</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="route-reflector-allow-outbound-policy">
<properties>
<help>Route reflector client allow policy outbound</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="no-client-to-client-reflection">
<properties>
<help>Disable client to client route reflection</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="no-fast-external-failover">
<properties>
<help>Disable immediate session reset on peer link down event</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="no-suppress-duplicates">
<properties>
<help>Disable suppress duplicate updates if the route actually not changed</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="reject-as-sets">
<properties>
<help>Reject routes with AS_SET or AS_CONFED_SET flag</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="shutdown">
<properties>
<help>Administrative shutdown of the BGP instance</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="suppress-fib-pending">
<properties>
<help>Advertise only routes that are programmed in kernel to peers</help>
<valueless/>
</properties>
</leafNode>
#include <include/router-id.xml.i>
<node name="tcp-keepalive">
<properties>
<help>TCP keepalive parameters</help>
</properties>
<children>
<leafNode name="idle">
<properties>
<help>TCP keepalive idle time</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Idle time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="interval">
<properties>
<help>TCP keepalive interval</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="probes">
<properties>
<help>TCP keepalive maximum probes</help>
<valueHelp>
<format>u32:1-30</format>
<description>Maximum probes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-30"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<tagNode name="peer-group">
<properties>
<help>Name of peer-group</help>
<constraint>
#include <include/constraint/alpha-numeric-hyphen-underscore.xml.i>
</constraint>
</properties>
<children>
<node name="address-family">
<properties>
<help>Address-family parameters</help>
</properties>
<children>
#include <include/bgp/neighbor-afi-ipv4-unicast.xml.i>
#include <include/bgp/neighbor-afi-ipv6-unicast.xml.i>
#include <include/bgp/neighbor-afi-l2vpn-evpn.xml.i>
</children>
</node>
#include <include/generic-description.xml.i>
#include <include/bgp/neighbor-bfd.xml.i>
#include <include/bgp/neighbor-capability.xml.i>
#include <include/bgp/neighbor-disable-capability-negotiation.xml.i>
#include <include/bgp/neighbor-disable-connected-check.xml.i>
#include <include/bgp/neighbor-ebgp-multihop.xml.i>
#include <include/bgp/neighbor-graceful-restart.xml.i>
#include <include/bgp/neighbor-graceful-restart.xml.i>
#include <include/bgp/neighbor-local-as.xml.i>
#include <include/bgp/neighbor-local-role.xml.i>
#include <include/bgp/neighbor-override-capability.xml.i>
#include <include/bgp/neighbor-path-attribute.xml.i>
#include <include/bgp/neighbor-passive.xml.i>
#include <include/bgp/neighbor-password.xml.i>
#include <include/bgp/neighbor-shutdown.xml.i>
#include <include/bgp/neighbor-ttl-security.xml.i>
#include <include/bgp/neighbor-update-source.xml.i>
#include <include/bgp/remote-as.xml.i>
#include <include/port-number.xml.i>
</children>
</tagNode>
-#include <include/route-map.xml.i>
<node name="timers">
<properties>
<help>BGP protocol timers</help>
</properties>
<children>
#include <include/bgp/timers-holdtime.xml.i>
#include <include/bgp/timers-keepalive.xml.i>
</children>
</node>
<!-- include end -->
diff --git a/interface-definitions/include/eigrp/protocol-common-config.xml.i b/interface-definitions/include/eigrp/protocol-common-config.xml.i
index 88365187a..a21d18424 100644
--- a/interface-definitions/include/eigrp/protocol-common-config.xml.i
+++ b/interface-definitions/include/eigrp/protocol-common-config.xml.i
@@ -1,125 +1,124 @@
<!-- include start from eigrp/protocol-common-config.xml.i -->
<leafNode name="local-as">
<properties>
<help>Autonomous System Number (ASN)</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Autonomous System Number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="maximum-paths">
<properties>
<help>Forward packets over multiple paths</help>
<valueHelp>
<format>u32:1-32</format>
<description>Number of paths</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-32"/>
</constraint>
</properties>
</leafNode>
<node name="metric">
<properties>
<help>Modify metrics and parameters for advertisement</help>
</properties>
<children>
<leafNode name="weights">
<properties>
<help>Modify metric coefficients</help>
<valueHelp>
<format>u32:0-255</format>
<description>K1</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="network">
<properties>
<help>Enable routing on an IP network</help>
<valueHelp>
<format>ipv4net</format>
<description>EIGRP network prefix</description>
</valueHelp>
<constraint>
<validator name="ip-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="passive-interface">
<properties>
<help>Suppress routing updates on an interface</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
</leafNode>
<leafNode name="redistribute">
<properties>
<help>Redistribute information from another routing protocol</help>
<valueHelp>
<format>bgp</format>
<description>Border Gateway Protocol (BGP)</description>
</valueHelp>
<valueHelp>
<format>connected</format>
<description>Connected routes</description>
</valueHelp>
<valueHelp>
<format>nhrp</format>
<description>Next Hop Resolution Protocol (NHRP)</description>
</valueHelp>
<valueHelp>
<format>ospf</format>
<description>Open Shortest Path First (OSPFv2)</description>
</valueHelp>
<valueHelp>
<format>rip</format>
<description>Routing Information Protocol (RIP)</description>
</valueHelp>
<valueHelp>
<format>babel</format>
<description>Babel routing protocol (Babel)</description>
</valueHelp>
<valueHelp>
<format>static</format>
<description>Statically configured routes</description>
</valueHelp>
<valueHelp>
<format>vnc</format>
<description>Virtual Network Control (VNC)</description>
</valueHelp>
<completionHelp>
<list>bgp connected nhrp ospf rip static vnc</list>
</completionHelp>
<constraint>
<regex>(bgp|connected|nhrp|ospf|rip|babel|static|vnc)</regex>
</constraint>
<multi/>
</properties>
</leafNode>
-#include <include/route-map.xml.i>
#include <include/router-id.xml.i>
<!-- FRR timers not implemented yet -->
<leafNode name="variance">
<properties>
<help>Control load balancing variance</help>
<valueHelp>
<format>u32:1-128</format>
<description>Metric variance multiplier</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-128"/>
</constraint>
</properties>
</leafNode>
<!-- include end -->
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 8103b5c5d..4ca7061db 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -1,691 +1,690 @@
<!-- include start from isis/protocol-common-config.xml.i -->
<node name="area-password">
<properties>
<help>Configure the authentication password for an area</help>
</properties>
<children>
#include <include/isis/password.xml.i>
</children>
</node>
<node name="default-information">
<properties>
<help>Control distribution of default information</help>
</properties>
<children>
<node name="originate">
<properties>
<help>Distribute a default route</help>
</properties>
<children>
<node name="ipv4">
<properties>
<help>Distribute default route for IPv4</help>
</properties>
<children>
#include <include/isis/default-information-level.xml.i>
</children>
</node>
<node name="ipv6">
<properties>
<help>Distribute default route for IPv6</help>
</properties>
<children>
#include <include/isis/default-information-level.xml.i>
</children>
</node>
</children>
</node>
</children>
</node>
<node name="domain-password">
<properties>
<help>Set the authentication password for a routing domain</help>
</properties>
<children>
#include <include/isis/password.xml.i>
</children>
</node>
<leafNode name="dynamic-hostname">
<properties>
<help>Dynamic hostname for IS-IS</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="level">
<properties>
<help>IS-IS level number</help>
<completionHelp>
<list>level-1 level-1-2 level-2</list>
</completionHelp>
<valueHelp>
<format>level-1</format>
<description>Act as a station router</description>
</valueHelp>
<valueHelp>
<format>level-1-2</format>
<description>Act as both a station and an area router</description>
</valueHelp>
<valueHelp>
<format>level-2</format>
<description>Act as an area router</description>
</valueHelp>
<constraint>
<regex>(level-1|level-1-2|level-2)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="log-adjacency-changes">
<properties>
<help>Log adjacency state changes</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="lsp-gen-interval">
<properties>
<help>Minimum interval between regenerating same LSP</help>
<valueHelp>
<format>u32:1-120</format>
<description>Minimum interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-120"/>
</constraint>
</properties>
</leafNode>
<leafNode name="lsp-mtu">
<properties>
<help>Configure the maximum size of generated LSPs</help>
<valueHelp>
<format>u32:128-4352</format>
<description>Maximum size of generated LSPs</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 128-4352"/>
</constraint>
</properties>
<defaultValue>1497</defaultValue>
</leafNode>
<leafNode name="lsp-refresh-interval">
<properties>
<help>LSP refresh interval</help>
<valueHelp>
<format>u32:1-65235</format>
<description>LSP refresh interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65235"/>
</constraint>
</properties>
</leafNode>
<leafNode name="max-lsp-lifetime">
<properties>
<help>Maximum LSP lifetime</help>
<valueHelp>
<format>u32:350-65535</format>
<description>LSP lifetime in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="metric-style">
<properties>
<help>Use old-style (ISO 10589) or new-style packet formats</help>
<completionHelp>
<list>narrow transition wide</list>
</completionHelp>
<valueHelp>
<format>narrow</format>
<description>Use old style of TLVs with narrow metric</description>
</valueHelp>
<valueHelp>
<format>transition</format>
<description>Send and accept both styles of TLVs during transition</description>
</valueHelp>
<valueHelp>
<format>wide</format>
<description>Use new style of TLVs to carry wider metric</description>
</valueHelp>
<constraint>
<regex>(narrow|transition|wide)</regex>
</constraint>
</properties>
</leafNode>
#include <include/isis/ldp-sync-protocol.xml.i>
<leafNode name="net">
<properties>
<help>A Network Entity Title for this process (ISO only)</help>
<valueHelp>
<format>XX.XXXX. ... .XXX.XX</format>
<description>Network entity title (NET)</description>
</valueHelp>
<constraint>
<regex>[a-fA-F0-9]{2}(\.[a-fA-F0-9]{4}){3,9}\.[a-fA-F0-9]{2}</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="purge-originator">
<properties>
<help>Use the RFC 6232 purge-originator</help>
<valueless/>
</properties>
</leafNode>
<node name="traffic-engineering">
<properties>
<help>IS-IS traffic engineering extensions</help>
</properties>
<children>
<leafNode name="enable">
<properties>
<help>Enable MPLS traffic engineering extensions</help>
<valueless/>
</properties>
</leafNode>
<!--
<node name="inter-as">
<properties>
<help>MPLS traffic engineering inter-AS support</help>
</properties>
<children>
<leafNode name="level-1">
<properties>
<help>Area native mode self originate inter-AS LSP with L1 only flooding scope</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="level-1-2">
<properties>
<help>Area native mode self originate inter-AS LSP with L1 and L2 flooding scope</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="level-2">
<properties>
<help>Area native mode self originate inter-AS LSP with L2 only flooding scope</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<leafNode name="inter-as">
<properties>
<help>MPLS traffic engineering inter-AS support</help>
<valueless/>
</properties>
</leafNode>
-->
<leafNode name="address">
<properties>
<help>MPLS traffic engineering router ID</help>
<valueHelp>
<format>ipv4</format>
<description>IPv4 address</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<node name="segment-routing">
<properties>
<help>Segment-Routing (SPRING) settings</help>
</properties>
<children>
<node name="global-block">
<properties>
<help>Segment Routing Global Block label range</help>
</properties>
<children>
#include <include/segment-routing-label-value.xml.i>
</children>
</node>
<node name="local-block">
<properties>
<help>Segment Routing Local Block label range</help>
</properties>
<children>
#include <include/segment-routing-label-value.xml.i>
</children>
</node>
<leafNode name="maximum-label-depth">
<properties>
<help>Maximum MPLS labels allowed for this router</help>
<valueHelp>
<format>u32:1-16</format>
<description>MPLS label depth</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-16"/>
</constraint>
</properties>
</leafNode>
<tagNode name="prefix">
<properties>
<help>Static IPv4/IPv6 prefix segment/label mapping</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 prefix segment</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 prefix segment</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<node name="absolute">
<properties>
<help>Specify the absolute value of prefix segment/label ID</help>
</properties>
<children>
<leafNode name="value">
<properties>
<help>Specify the absolute value of prefix segment/label ID</help>
<valueHelp>
<format>u32:16-1048575</format>
<description>The absolute segment/label ID value</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 16-1048575"/>
</constraint>
</properties>
</leafNode>
<leafNode name="explicit-null">
<properties>
<help>Request upstream neighbor to replace segment/label with explicit null label</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="no-php-flag">
<properties>
<help>Do not request penultimate hop popping for segment/label</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
<node name="index">
<properties>
<help>Specify the index value of prefix segment/label ID</help>
</properties>
<children>
<leafNode name="value">
<properties>
<help>Specify the index value of prefix segment/label ID</help>
<valueHelp>
<format>u32:0-65535</format>
<description>The index segment/label ID value</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="explicit-null">
<properties>
<help>Request upstream neighbor to replace segment/label with explicit null label</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="no-php-flag">
<properties>
<help>Do not request penultimate hop popping for segment/label</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</tagNode>
</children>
</node>
<node name="redistribute">
<properties>
<help>Redistribute information from another routing protocol</help>
</properties>
<children>
<node name="ipv4">
<properties>
<help>Redistribute IPv4 routes</help>
</properties>
<children>
<node name="bgp">
<properties>
<help>Border Gateway Protocol (BGP)</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="connected">
<properties>
<help>Redistribute connected routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="kernel">
<properties>
<help>Redistribute kernel routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="ospf">
<properties>
<help>Redistribute OSPF routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="rip">
<properties>
<help>Redistribute RIP routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="babel">
<properties>
<help>Redistribute Babel routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="static">
<properties>
<help>Redistribute static routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
</children>
</node>
<node name="ipv6">
<properties>
<help>Redistribute IPv6 routes</help>
</properties>
<children>
<node name="bgp">
<properties>
<help>Redistribute BGP routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="connected">
<properties>
<help>Redistribute connected routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="kernel">
<properties>
<help>Redistribute kernel routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="ospf6">
<properties>
<help>Redistribute OSPFv3 routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="ripng">
<properties>
<help>Redistribute RIPng routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="babel">
<properties>
<help>Redistribute Babel routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="static">
<properties>
<help>Redistribute static routes into IS-IS</help>
</properties>
<children>
#include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
</children>
</node>
</children>
</node>
<leafNode name="set-attached-bit">
<properties>
<help>Set attached bit to identify as L1/L2 router for inter-area traffic</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="set-overload-bit">
<properties>
<help>Set overload bit to avoid any transit traffic</help>
<valueless/>
</properties>
</leafNode>
<node name="spf-delay-ietf">
<properties>
<help>IETF SPF delay algorithm</help>
</properties>
<children>
<leafNode name="init-delay">
<properties>
<help>Delay used while in QUIET state</help>
<valueHelp>
<format>u32:0-60000</format>
<description>Delay used while in QUIET state (in ms)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-60000"/>
</constraint>
</properties>
</leafNode>
<leafNode name="short-delay">
<properties>
<help>Delay used while in SHORT_WAIT state</help>
<valueHelp>
<format>u32:0-60000</format>
<description>Delay used while in SHORT_WAIT state (in ms)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-60000"/>
</constraint>
</properties>
</leafNode>
<leafNode name="long-delay">
<properties>
<help>Delay used while in LONG_WAIT</help>
<valueHelp>
<format>u32:0-60000</format>
<description>Delay used while in LONG_WAIT state in ms</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-60000"/>
</constraint>
</properties>
</leafNode>
<leafNode name="holddown">
<properties>
<help>Time with no received IGP events before considering IGP stable</help>
<valueHelp>
<format>u32:0-60000</format>
<description>Time with no received IGP events before considering IGP stable in ms</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-60000"/>
</constraint>
</properties>
</leafNode>
<leafNode name="time-to-learn">
<properties>
<help>Maximum duration needed to learn all the events related to a single failure</help>
<valueHelp>
<format>u32:0-60000</format>
<description>Maximum duration needed to learn all the events related to a single failure in ms</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-60000"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
<leafNode name="spf-interval">
<properties>
<help>Minimum interval between SPF calculations</help>
<valueHelp>
<format>u32:1-120</format>
<description>Interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-120"/>
</constraint>
</properties>
</leafNode>
<tagNode name="interface">
<properties>
<help>Interface params</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
<children>
#include <include/bfd/bfd.xml.i>
<leafNode name="circuit-type">
<properties>
<help>Configure circuit type for interface</help>
<completionHelp>
<list>level-1 level-1-2 level-2-only</list>
</completionHelp>
<valueHelp>
<format>level-1</format>
<description>Level-1 only adjacencies are formed</description>
</valueHelp>
<valueHelp>
<format>level-1-2</format>
<description>Level-1-2 adjacencies are formed</description>
</valueHelp>
<valueHelp>
<format>level-2-only</format>
<description>Level-2 only adjacencies are formed</description>
</valueHelp>
<constraint>
<regex>(level-1|level-1-2|level-2-only)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="hello-padding">
<properties>
<help>Add padding to IS-IS hello packets</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="hello-interval">
<properties>
<help>Set Hello interval</help>
<valueHelp>
<format>u32:1-600</format>
<description>Set Hello interval</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-600"/>
</constraint>
</properties>
</leafNode>
<leafNode name="hello-multiplier">
<properties>
<help>Set Hello interval</help>
<valueHelp>
<format>u32:2-100</format>
<description>Set multiplier for Hello holding time</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 2-100"/>
</constraint>
</properties>
</leafNode>
#include <include/isis/metric.xml.i>
#include <include/isis/ldp-sync-interface.xml.i>
<node name="network">
<properties>
<help>Set network type</help>
</properties>
<children>
<leafNode name="point-to-point">
<properties>
<help>point-to-point network type</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
#include <include/isis/passive.xml.i>
<node name="password">
<properties>
<help>Configure the authentication password for a circuit</help>
</properties>
<children>
#include <include/isis/password.xml.i>
</children>
</node>
<leafNode name="priority">
<properties>
<help>Set priority for Designated Router election</help>
<valueHelp>
<format>u32:0-127</format>
<description>Priority value</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-127"/>
</constraint>
</properties>
</leafNode>
<leafNode name="psnp-interval">
<properties>
<help>Set PSNP interval</help>
<valueHelp>
<format>u32:0-127</format>
<description>PSNP interval in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-127"/>
</constraint>
</properties>
</leafNode>
<leafNode name="no-three-way-handshake">
<properties>
<help>Disable three-way handshake</help>
<valueless/>
</properties>
</leafNode>
</children>
</tagNode>
-#include <include/route-map.xml.i>
<!-- include end -->
diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i
index e400119dd..b7f22cb88 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -1,880 +1,879 @@
<!-- include start from ospf/protocol-common-config.xml.i -->
<tagNode name="access-list">
<properties>
<help>Access list to filter networks in routing updates</help>
<completionHelp>
<path>policy access-list</path>
</completionHelp>
<valueHelp>
<format>u32</format>
<description>Access-list number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
<children>
<leafNode name="export">
<properties>
<help>Filter for outgoing routing update</help>
<completionHelp>
<list>bgp connected kernel rip static</list>
</completionHelp>
<valueHelp>
<format>bgp</format>
<description>Filter BGP routes</description>
</valueHelp>
<valueHelp>
<format>connected</format>
<description>Filter connected routes</description>
</valueHelp>
<valueHelp>
<format>isis</format>
<description>Filter IS-IS routes</description>
</valueHelp>
<valueHelp>
<format>kernel</format>
<description>Filter Kernel routes</description>
</valueHelp>
<valueHelp>
<format>rip</format>
<description>Filter RIP routes</description>
</valueHelp>
<valueHelp>
<format>static</format>
<description>Filter static routes</description>
</valueHelp>
<constraint>
<regex>(bgp|connected|isis|kernel|rip|static)</regex>
</constraint>
<constraintErrorMessage>Must be bgp, connected, kernel, rip, or static</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
</children>
</tagNode>
<tagNode name="area">
<properties>
<help>OSPF area settings</help>
<valueHelp>
<format>u32</format>
<description>OSPF area number in decimal notation</description>
</valueHelp>
<valueHelp>
<format>ipv4</format>
<description>OSPF area number in dotted decimal notation</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
<validator name="ip-address"/>
</constraint>
</properties>
<children>
<node name="area-type">
<properties>
<help>Area type</help>
</properties>
<children>
<leafNode name="normal">
<properties>
<help>Normal OSPF area</help>
<valueless/>
</properties>
</leafNode>
<node name="nssa">
<properties>
<help>Not-So-Stubby OSPF area</help>
</properties>
<children>
<leafNode name="default-cost">
<properties>
<help>Summary-default cost of an NSSA area</help>
<valueHelp>
<format>u32:0-16777215</format>
<description>Summary default cost</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-16777215"/>
</constraint>
</properties>
</leafNode>
<leafNode name="no-summary">
<properties>
<help>Do not inject inter-area routes into stub</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="translate">
<properties>
<help>Configure NSSA-ABR</help>
<completionHelp>
<list>always candidate never</list>
</completionHelp>
<valueHelp>
<format>always</format>
<description>Always translate LSA types</description>
</valueHelp>
<valueHelp>
<format>candidate</format>
<description>Translate for election</description>
</valueHelp>
<valueHelp>
<format>never</format>
<description>Never translate LSA types</description>
</valueHelp>
<constraint>
<regex>(always|candidate|never)</regex>
</constraint>
</properties>
<defaultValue>candidate</defaultValue>
</leafNode>
</children>
</node>
<node name="stub">
<properties>
<help>Stub OSPF area</help>
</properties>
<children>
<leafNode name="default-cost">
<properties>
<help>Summary-default cost</help>
<valueHelp>
<format>u32:0-16777215</format>
<description>Summary default cost</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-16777215"/>
</constraint>
</properties>
</leafNode>
<leafNode name="no-summary">
<properties>
<help>Do not inject inter-area routes into the stub</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<leafNode name="authentication">
<properties>
<help>OSPF area authentication type</help>
<completionHelp>
<list>plaintext-password md5</list>
</completionHelp>
<valueHelp>
<format>plaintext-password</format>
<description>Use plain-text authentication</description>
</valueHelp>
<valueHelp>
<format>md5</format>
<description>Use MD5 authentication</description>
</valueHelp>
<constraint>
<regex>(plaintext-password|md5)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="network">
<properties>
<help>OSPF network</help>
<valueHelp>
<format>ipv4net</format>
<description>OSPF network</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<tagNode name="range">
<properties>
<help>Summarize routes matching a prefix (border routers only)</help>
<valueHelp>
<format>ipv4net</format>
<description>Area range prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="cost">
<properties>
<help>Metric for this range</help>
<valueHelp>
<format>u32:0-16777215</format>
<description>Metric for this range</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-16777215"/>
</constraint>
</properties>
</leafNode>
<leafNode name="not-advertise">
<properties>
<help>Do not advertise this range</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="substitute">
<properties>
<help>Advertise area range as another prefix</help>
<valueHelp>
<format>ipv4net</format>
<description>Advertise area range as another prefix</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
</leafNode>
</children>
</tagNode>
<leafNode name="shortcut">
<properties>
<help>Area shortcut mode</help>
<completionHelp>
<list>default disable enable</list>
</completionHelp>
<valueHelp>
<format>default</format>
<description>Set default</description>
</valueHelp>
<valueHelp>
<format>disable</format>
<description>Disable shortcutting mode</description>
</valueHelp>
<valueHelp>
<format>enable</format>
<description>Enable shortcutting mode</description>
</valueHelp>
<constraint>
<regex>(default|disable|enable)</regex>
</constraint>
</properties>
</leafNode>
<leafNode name="export-list">
<properties>
<help>Set the filter for networks announced to other areas</help>
<completionHelp>
<path>policy access-list</path>
</completionHelp>
<valueHelp>
<format>u32</format>
<description>Access-list number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
</leafNode>
<leafNode name="import-list">
<properties>
<help>Set the filter for networks from other areas announced</help>
<completionHelp>
<path>policy access-list</path>
</completionHelp>
<valueHelp>
<format>u32</format>
<description>Access-list number</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
</constraint>
</properties>
</leafNode>
<tagNode name="virtual-link">
<properties>
<help>Virtual link</help>
<valueHelp>
<format>ipv4</format>
<description>OSPF area in dotted decimal notation</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
<validator name="ip-address"/>
</constraint>
</properties>
<children>
#include <include/ospf/authentication.xml.i>
#include <include/ospf/intervals.xml.i>
</children>
</tagNode>
</children>
</tagNode>
#include <include/ospf/auto-cost.xml.i>
#include <include/ospf/default-information.xml.i>
<leafNode name="default-metric">
<properties>
<help>Metric of redistributed routes</help>
<valueHelp>
<format>u32:0-16777214</format>
<description>Metric of redistributed routes</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-16777214"/>
</constraint>
</properties>
</leafNode>
<leafNode name="maximum-paths">
<properties>
<help>Maximum multiple paths (ECMP)</help>
<valueHelp>
<format>u32:1-64</format>
<description>Maximum multiple paths (ECMP)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-64"/>
</constraint>
</properties>
</leafNode>
#include <include/isis/ldp-sync-protocol.xml.i>
<node name="distance">
<properties>
<help>Administrative distance</help>
</properties>
<children>
#include <include/ospf/distance-global.xml.i>
<node name="ospf">
<properties>
<help>OSPF administrative distance</help>
</properties>
<children>
#include <include/ospf/distance-per-protocol.xml.i>
</children>
</node>
</children>
</node>
<tagNode name="interface">
<properties>
<help>Interface configuration</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
<valueHelp>
<format>txt</format>
<description>Interface name</description>
</valueHelp>
<constraint>
#include <include/constraint/interface-name.xml.i>
</constraint>
</properties>
<children>
<leafNode name="area">
<properties>
<help>Enable OSPF on this interface</help>
<completionHelp>
<path>protocols ospf area</path>
</completionHelp>
<valueHelp>
<format>u32</format>
<description>OSPF area ID as decimal notation</description>
</valueHelp>
<valueHelp>
<format>ipv4</format>
<description>OSPF area ID in IP address notation</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
<validator name="ip-address"/>
</constraint>
</properties>
</leafNode>
#include <include/ospf/authentication.xml.i>
#include <include/ospf/intervals.xml.i>
#include <include/ospf/interface-common.xml.i>
#include <include/isis/ldp-sync-interface.xml.i>
<leafNode name="bandwidth">
<properties>
<help>Interface bandwidth (Mbit/s)</help>
<valueHelp>
<format>u32:1-100000</format>
<description>Bandwidth in Megabit/sec (for calculating OSPF cost)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-100000"/>
</constraint>
</properties>
</leafNode>
<leafNode name="hello-multiplier">
<properties>
<help>Hello multiplier factor</help>
<valueHelp>
<format>u32:1-10</format>
<description>Number of Hellos to send each second</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-10"/>
</constraint>
</properties>
</leafNode>
<leafNode name="network">
<properties>
<help>Network type</help>
<completionHelp>
<list>broadcast non-broadcast point-to-multipoint point-to-point</list>
</completionHelp>
<valueHelp>
<format>broadcast</format>
<description>Broadcast network type</description>
</valueHelp>
<valueHelp>
<format>non-broadcast</format>
<description>Non-broadcast network type</description>
</valueHelp>
<valueHelp>
<format>point-to-multipoint</format>
<description>Point-to-multipoint network type</description>
</valueHelp>
<valueHelp>
<format>point-to-point</format>
<description>Point-to-point network type</description>
</valueHelp>
<constraint>
<regex>(broadcast|non-broadcast|point-to-multipoint|point-to-point)</regex>
</constraint>
<constraintErrorMessage>Must be broadcast, non-broadcast, point-to-multipoint or point-to-point</constraintErrorMessage>
</properties>
</leafNode>
<node name="passive">
<properties>
<help>Suppress routing updates on an interface</help>
</properties>
<children>
#include <include/generic-disable-node.xml.i>
</children>
</node>
</children>
</tagNode>
#include <include/ospf/log-adjacency-changes.xml.i>
<node name="max-metric">
<properties>
<help>OSPF maximum and infinite-distance metric</help>
</properties>
<children>
<node name="router-lsa">
<properties>
<help>Advertise own Router-LSA with infinite distance (stub router)</help>
</properties>
<children>
<leafNode name="administrative">
<properties>
<help>Administratively apply, for an indefinite period</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="on-shutdown">
<properties>
<help>Advertise stub-router prior to full shutdown of OSPF</help>
<valueHelp>
<format>u32:5-100</format>
<description>Time (seconds) to advertise self as stub-router</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 5-100"/>
</constraint>
</properties>
</leafNode>
<leafNode name="on-startup">
<properties>
<help>Automatically advertise stub Router-LSA on startup of OSPF</help>
<valueHelp>
<format>u32:5-86400</format>
<description>Time (seconds) to advertise self as stub-router</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 5-86400"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
</children>
</node>
<node name="mpls-te">
<properties>
<help>MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters</help>
</properties>
<children>
<leafNode name="enable">
<properties>
<help>Enable MPLS-TE functionality</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="router-address">
<properties>
<help>Stable IP address of the advertising router</help>
<valueHelp>
<format>ipv4</format>
<description>Stable IP address of the advertising router</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
<defaultValue>0.0.0.0</defaultValue>
</leafNode>
</children>
</node>
<tagNode name="neighbor">
<properties>
<help>Specify neighbor router</help>
<valueHelp>
<format>ipv4</format>
<description>Neighbor IP address</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
</constraint>
</properties>
<children>
<leafNode name="poll-interval">
<properties>
<help>Dead neighbor polling interval</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Seconds between dead neighbor polling interval</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
<defaultValue>60</defaultValue>
</leafNode>
<leafNode name="priority">
<properties>
<help>Neighbor priority in seconds</help>
<valueHelp>
<format>u32:0-255</format>
<description>Neighbor priority</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
</children>
</tagNode>
<node name="parameters">
<properties>
<help>OSPF specific parameters</help>
</properties>
<children>
<leafNode name="abr-type">
<properties>
<help>OSPF ABR type</help>
<completionHelp>
<list>cisco ibm shortcut standard</list>
</completionHelp>
<valueHelp>
<format>cisco</format>
<description>Cisco ABR type</description>
</valueHelp>
<valueHelp>
<format>ibm</format>
<description>IBM ABR type</description>
</valueHelp>
<valueHelp>
<format>shortcut</format>
<description>Shortcut ABR type</description>
</valueHelp>
<valueHelp>
<format>standard</format>
<description>Standard ABR type</description>
</valueHelp>
<constraint>
<regex>(cisco|ibm|shortcut|standard)</regex>
</constraint>
</properties>
<defaultValue>cisco</defaultValue>
</leafNode>
<leafNode name="opaque-lsa">
<properties>
<help>Enable the Opaque-LSA capability (rfc2370)</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="rfc1583-compatibility">
<properties>
<help>Enable RFC1583 criteria for handling AS external routes</help>
<valueless/>
</properties>
</leafNode>
#include <include/router-id.xml.i>
</children>
</node>
<leafNode name="passive-interface">
<properties>
<help>Suppress routing updates on an interface</help>
<completionHelp>
<list>default</list>
</completionHelp>
<valueHelp>
<format>default</format>
<description>Default to suppress routing updates on all interfaces</description>
</valueHelp>
<constraint>
<regex>(default)</regex>
</constraint>
</properties>
</leafNode>
<node name="segment-routing">
<properties>
<help>Segment-Routing (SPRING) settings</help>
</properties>
<children>
<node name="global-block">
<properties>
<help>Segment Routing Global Block label range</help>
</properties>
<children>
#include <include/segment-routing-label-value.xml.i>
</children>
</node>
<node name="local-block">
<properties>
<help>Segment Routing Local Block label range</help>
</properties>
<children>
#include <include/segment-routing-label-value.xml.i>
</children>
</node>
<leafNode name="maximum-label-depth">
<properties>
<help>Maximum MPLS labels allowed for this router</help>
<valueHelp>
<format>u32:1-16</format>
<description>MPLS label depth</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-16"/>
</constraint>
</properties>
</leafNode>
<tagNode name="prefix">
<properties>
<help>Static IPv4 prefix segment/label mapping</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 prefix segment</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
</constraint>
</properties>
<children>
<node name="index">
<properties>
<help>Specify the index value of prefix segment/label ID</help>
</properties>
<children>
<leafNode name="value">
<properties>
<help>Specify the index value of prefix segment/label ID</help>
<valueHelp>
<format>u32:0-65535</format>
<description>The index segment/label ID value</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="explicit-null">
<properties>
<help>Request upstream neighbor to replace segment/label with explicit null label</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="no-php-flag">
<properties>
<help>Do not request penultimate hop popping for segment/label</help>
<valueless/>
</properties>
</leafNode>
</children>
</node>
</children>
</tagNode>
</children>
</node>
<node name="redistribute">
<properties>
<help>Redistribute information from another routing protocol</help>
</properties>
<children>
<node name="bgp">
<properties>
<help>Redistribute BGP routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<node name="connected">
<properties>
<help>Redistribute connected routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<node name="isis">
<properties>
<help>Redistribute IS-IS routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<node name="kernel">
<properties>
<help>Redistribute Kernel routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<node name="rip">
<properties>
<help>Redistribute RIP routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<node name="babel">
<properties>
<help>Redistribute Babel routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<node name="static">
<properties>
<help>Redistribute statically configured routes</help>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</node>
<tagNode name="table">
<properties>
<help>Redistribute non-main Kernel Routing Table</help>
<completionHelp>
<path>protocols static table</path>
</completionHelp>
<valueHelp>
<format>u32:1-200</format>
<description>Policy route table number</description>
</valueHelp>
</properties>
<children>
#include <include/ospf/metric.xml.i>
#include <include/ospf/metric-type.xml.i>
#include <include/route-map.xml.i>
</children>
</tagNode>
</children>
</node>
<node name="refresh">
<properties>
<help>Adjust refresh parameters</help>
</properties>
<children>
<leafNode name="timers">
<properties>
<help>Refresh timer</help>
<valueHelp>
<format>u32:10-1800</format>
<description>Timer value in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 10-1800"/>
</constraint>
</properties>
</leafNode>
</children>
</node>
-#include <include/route-map.xml.i>
<node name="timers">
<properties>
<help>Adjust routing timers</help>
</properties>
<children>
<node name="throttle">
<properties>
<help>Throttling adaptive timers</help>
</properties>
<children>
<node name="spf">
<properties>
<help>OSPF SPF timers</help>
</properties>
<children>
<leafNode name="delay">
<properties>
<help>Delay from the first change received to SPF calculation</help>
<valueHelp>
<format>u32:0-600000</format>
<description>Delay in milliseconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-600000"/>
</constraint>
</properties>
<defaultValue>200</defaultValue>
</leafNode>
<leafNode name="initial-holdtime">
<properties>
<help>Initial hold time between consecutive SPF calculations</help>
<valueHelp>
<format>u32:0-600000</format>
<description>Initial hold time in milliseconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-600000"/>
</constraint>
</properties>
<defaultValue>1000</defaultValue>
</leafNode>
<leafNode name="max-holdtime">
<properties>
<help>Maximum hold time</help>
<valueHelp>
<format>u32:0-600000</format>
<description>Max hold time in milliseconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-600000"/>
</constraint>
</properties>
<defaultValue>10000</defaultValue>
</leafNode>
</children>
</node>
</children>
</node>
</children>
</node>
<!-- include end -->
\ No newline at end of file
diff --git a/interface-definitions/include/ospfv3/protocol-common-config.xml.i b/interface-definitions/include/ospfv3/protocol-common-config.xml.i
index 1c33ca920..a7de50638 100644
--- a/interface-definitions/include/ospfv3/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospfv3/protocol-common-config.xml.i
@@ -1,260 +1,259 @@
<!-- include start from ospfv3/protocol-common-config.xml.i -->
<tagNode name="area">
<properties>
<help>OSPFv3 Area</help>
<valueHelp>
<format>u32</format>
<description>Area ID as a decimal value</description>
</valueHelp>
<valueHelp>
<format>ipv4</format>
<description>Area ID in IP address forma</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
<validator name="ip-address"/>
</constraint>
</properties>
<children>
<node name="area-type">
<properties>
<help>OSPFv3 Area type</help>
</properties>
<children>
<node name="nssa">
<properties>
<help>NSSA OSPFv3 area</help>
</properties>
<children>
<leafNode name="default-information-originate">
<properties>
<help>Originate Type 7 default into NSSA area</help>
<valueless/>
</properties>
</leafNode>
#include <include/ospfv3/no-summary.xml.i>
</children>
</node>
<node name="stub">
<properties>
<help>Stub OSPFv3 area</help>
</properties>
<children>
#include <include/ospfv3/no-summary.xml.i>
</children>
</node>
</children>
</node>
<leafNode name="export-list">
<properties>
<help>Name of export-list</help>
<completionHelp>
<path>policy access-list6</path>
</completionHelp>
</properties>
</leafNode>
<leafNode name="import-list">
<properties>
<help>Name of import-list</help>
<completionHelp>
<path>policy access-list6</path>
</completionHelp>
</properties>
</leafNode>
<tagNode name="range">
<properties>
<help>Specify IPv6 prefix (border routers only)</help>
<valueHelp>
<format>ipv6net</format>
<description>Specify IPv6 prefix (border routers only)</description>
</valueHelp>
<constraint>
<validator name="ipv6-prefix"/>
</constraint>
</properties>
<children>
<leafNode name="advertise">
<properties>
<help>Advertise this range</help>
<valueless/>
</properties>
</leafNode>
<leafNode name="not-advertise">
<properties>
<help>Do not advertise this range</help>
<valueless/>
</properties>
</leafNode>
</children>
</tagNode>
</children>
</tagNode>
#include <include/ospf/auto-cost.xml.i>
#include <include/ospf/default-information.xml.i>
<node name="distance">
<properties>
<help>Administrative distance</help>
</properties>
<children>
#include <include/ospf/distance-global.xml.i>
<node name="ospfv3">
<properties>
<help>OSPFv3 administrative distance</help>
</properties>
<children>
#include <include/ospf/distance-per-protocol.xml.i>
</children>
</node>
</children>
</node>
<tagNode name="interface">
<properties>
<help>Enable routing on an IPv6 interface</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
<valueHelp>
<format>txt</format>
<description>Interface used for routing information exchange</description>
</valueHelp>
<constraint>
#include <include/constraint/interface-name.xml.i>
</constraint>
</properties>
<children>
<leafNode name="area">
<properties>
<help>Enable OSPF on this interface</help>
<completionHelp>
<path>protocols ospfv3 area</path>
</completionHelp>
<valueHelp>
<format>u32</format>
<description>OSPF area ID as decimal notation</description>
</valueHelp>
<valueHelp>
<format>ipv4</format>
<description>OSPF area ID in IP address notation</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-4294967295"/>
<validator name="ip-address"/>
</constraint>
</properties>
</leafNode>
#include <include/ospf/intervals.xml.i>
#include <include/ospf/interface-common.xml.i>
<leafNode name="ifmtu">
<properties>
<help>Interface MTU</help>
<valueHelp>
<format>u32:1-65535</format>
<description>Interface MTU</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
</properties>
</leafNode>
<leafNode name="instance-id">
<properties>
<help>Instance ID</help>
<valueHelp>
<format>u32:0-255</format>
<description>Instance Id</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 0-255"/>
</constraint>
</properties>
<defaultValue>0</defaultValue>
</leafNode>
<leafNode name="network">
<properties>
<help>Network type</help>
<completionHelp>
<list>broadcast point-to-point</list>
</completionHelp>
<valueHelp>
<format>broadcast</format>
<description>Broadcast network type</description>
</valueHelp>
<valueHelp>
<format>point-to-point</format>
<description>Point-to-point network type</description>
</valueHelp>
<constraint>
<regex>(broadcast|point-to-point)</regex>
</constraint>
<constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage>
</properties>
</leafNode>
#include <include/isis/passive.xml.i>
</children>
</tagNode>
#include <include/ospf/log-adjacency-changes.xml.i>
<node name="parameters">
<properties>
<help>OSPFv3 specific parameters</help>
</properties>
<children>
#include <include/router-id.xml.i>
</children>
</node>
<node name="redistribute">
<properties>
<help>Redistribute information from another routing protocol</help>
</properties>
<children>
<node name="bgp">
<properties>
<help>Redistribute BGP routes</help>
</properties>
<children>
#include <include/route-map.xml.i>
</children>
</node>
<node name="connected">
<properties>
<help>Redistribute connected routes</help>
</properties>
<children>
#include <include/route-map.xml.i>
</children>
</node>
<node name="kernel">
<properties>
<help>Redistribute kernel routes</help>
</properties>
<children>
#include <include/route-map.xml.i>
</children>
</node>
<node name="ripng">
<properties>
<help>Redistribute RIPNG routes</help>
</properties>
<children>
#include <include/route-map.xml.i>
</children>
</node>
<node name="babel">
<properties>
<help>Redistribute Babel routes</help>
</properties>
<children>
#include <include/route-map.xml.i>
</children>
</node>
<node name="static">
<properties>
<help>Redistribute static routes</help>
</properties>
<children>
#include <include/route-map.xml.i>
</children>
</node>
</children>
</node>
-#include <include/route-map.xml.i>
<!-- include end -->
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index f6eede87a..ce9590fc2 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -1,1108 +1,1087 @@
#!/usr/bin/env python3
#
# Copyright (C) 2021-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.configsession import ConfigSessionError
from vyos.template import is_ipv6
from vyos.util import process_named_running
PROCESS_NAME = 'bgpd'
ASN = '64512'
base_path = ['protocols', 'bgp']
route_map_in = 'foo-map-in'
route_map_out = 'foo-map-out'
prefix_list_in = 'pfx-foo-in'
prefix_list_out = 'pfx-foo-out'
prefix_list_in6 = 'pfx-foo-in6'
prefix_list_out6 = 'pfx-foo-out6'
bfd_profile = 'foo-bar-baz'
import_afi = 'ipv4-unicast'
import_vrf = 'red'
import_rd = ASN + ':100'
import_vrf_base = ['vrf', 'name']
neighbor_config = {
'192.0.2.1' : {
'bfd' : '',
'cap_dynamic' : '',
'cap_ext_next' : '',
'remote_as' : '100',
'adv_interv' : '400',
'passive' : '',
'password' : 'VyOS-Secure123',
'shutdown' : '',
'cap_over' : '',
'ttl_security' : '5',
'system_as' : '300',
'route_map_in' : route_map_in,
'route_map_out' : route_map_out,
'no_send_comm_ext' : '',
'addpath_all' : '',
'p_attr_discard' : '123',
},
'192.0.2.2' : {
'bfd_profile' : bfd_profile,
'remote_as' : '200',
'shutdown' : '',
'no_cap_nego' : '',
'port' : '667',
'cap_strict' : '',
'advertise_map' : route_map_in,
'non_exist_map' : route_map_out,
'pfx_list_in' : prefix_list_in,
'pfx_list_out' : prefix_list_out,
'no_send_comm_std' : '',
'local_role' : 'rs-client',
},
'192.0.2.3' : {
'advertise_map' : route_map_in,
'description' : 'foo bar baz',
'remote_as' : '200',
'passive' : '',
'multi_hop' : '5',
'update_src' : 'lo',
'peer_group' : 'foo',
'graceful_rst' : '',
},
'2001:db8::1' : {
'advertise_map' : route_map_in,
'exist_map' : route_map_out,
'cap_dynamic' : '',
'cap_ext_next' : '',
'remote_as' : '123',
'adv_interv' : '400',
'passive' : '',
'password' : 'VyOS-Secure123',
'shutdown' : '',
'cap_over' : '',
'ttl_security' : '5',
'system_as' : '300',
'solo' : '',
'route_map_in' : route_map_in,
'route_map_out' : route_map_out,
'no_send_comm_std' : '',
'addpath_per_as' : '',
'peer_group' : 'foo-bar',
'local_role' : 'customer',
'local_role_strict': '',
},
'2001:db8::2' : {
'remote_as' : '456',
'shutdown' : '',
'no_cap_nego' : '',
'port' : '667',
'cap_strict' : '',
'pfx_list_in' : prefix_list_in6,
'pfx_list_out' : prefix_list_out6,
'no_send_comm_ext' : '',
'peer_group' : 'foo-bar_baz',
'graceful_rst_hlp' : '',
'disable_conn_chk' : '',
},
}
peer_group_config = {
'foo' : {
'advertise_map' : route_map_in,
'exist_map' : route_map_out,
'bfd' : '',
'remote_as' : '100',
'passive' : '',
'password' : 'VyOS-Secure123',
'shutdown' : '',
'cap_over' : '',
'ttl_security' : '5',
'disable_conn_chk' : '',
'p_attr_discard' : '250',
},
'bar' : {
'remote_as' : '111',
'graceful_rst_no' : '',
'port' : '667',
},
'foo-bar' : {
'advertise_map' : route_map_in,
'description' : 'foo peer bar group',
'remote_as' : '200',
'shutdown' : '',
'no_cap_nego' : '',
'system_as' : '300',
'pfx_list_in' : prefix_list_in,
'pfx_list_out' : prefix_list_out,
'no_send_comm_ext' : '',
},
'foo-bar_baz' : {
'advertise_map' : route_map_in,
'non_exist_map' : route_map_out,
'bfd_profile' : bfd_profile,
'cap_dynamic' : '',
'cap_ext_next' : '',
'remote_as' : '200',
'passive' : '',
'multi_hop' : '5',
'update_src' : 'lo',
'route_map_in' : route_map_in,
'route_map_out' : route_map_out,
'local_role' : 'peer',
'local_role_strict': '',
},
}
class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
@classmethod
def setUpClass(cls):
super(TestProtocolsBGP, cls).setUpClass()
# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
cls.cli_delete(cls, base_path)
cls.cli_set(cls, ['policy', 'route-map', route_map_in, 'rule', '10', 'action', 'permit'])
cls.cli_set(cls, ['policy', 'route-map', route_map_out, 'rule', '10', 'action', 'permit'])
cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_in, 'rule', '10', 'action', 'permit'])
cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_in, 'rule', '10', 'prefix', '192.0.2.0/25'])
cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'action', 'permit'])
cls.cli_set(cls, ['policy', 'prefix-list', prefix_list_out, 'rule', '10', 'prefix', '192.0.2.128/25'])
cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'action', 'permit'])
cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_in6, 'rule', '10', 'prefix', '2001:db8:1000::/64'])
cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'action', 'deny'])
cls.cli_set(cls, ['policy', 'prefix-list6', prefix_list_out6, 'rule', '10', 'prefix', '2001:db8:2000::/64'])
@classmethod
def tearDownClass(cls):
cls.cli_delete(cls, ['policy'])
def setUp(self):
self.cli_set(base_path + ['system-as', ASN])
def tearDown(self):
self.cli_delete(['vrf'])
self.cli_delete(base_path)
self.cli_commit()
# Check for running process
self.assertTrue(process_named_running(PROCESS_NAME))
def create_bgp_instances_for_import_test(self):
table = '1000'
self.cli_set(base_path + ['system-as', ASN])
# testing only one AFI is sufficient as it's generic code
self.cli_set(import_vrf_base + [import_vrf, 'table', table])
self.cli_set(import_vrf_base + [import_vrf, 'protocols', 'bgp', 'system-as', ASN])
def verify_frr_config(self, peer, peer_config, frrconfig):
# recurring patterns to verify for both a simple neighbor and a peer-group
if 'bfd' in peer_config:
self.assertIn(f' neighbor {peer} bfd', frrconfig)
if 'bfd_profile' in peer_config:
self.assertIn(f' neighbor {peer} bfd profile {peer_config["bfd_profile"]}', frrconfig)
self.assertIn(f' neighbor {peer} bfd check-control-plane-failure', frrconfig)
if 'cap_dynamic' in peer_config:
self.assertIn(f' neighbor {peer} capability dynamic', frrconfig)
if 'cap_ext_next' in peer_config:
self.assertIn(f' neighbor {peer} capability extended-nexthop', frrconfig)
if 'description' in peer_config:
self.assertIn(f' neighbor {peer} description {peer_config["description"]}', frrconfig)
if 'no_cap_nego' in peer_config:
self.assertIn(f' neighbor {peer} dont-capability-negotiate', frrconfig)
if 'multi_hop' in peer_config:
self.assertIn(f' neighbor {peer} ebgp-multihop {peer_config["multi_hop"]}', frrconfig)
if 'local_as' in peer_config:
self.assertIn(f' neighbor {peer} local-as {peer_config["local_as"]} no-prepend replace-as', frrconfig)
if 'local_role' in peer_config:
tmp = f' neighbor {peer} local-role {peer_config["local_role"]}'
if 'local_role_strict' in peer_config:
tmp += ' strict'
self.assertIn(tmp, frrconfig)
if 'cap_over' in peer_config:
self.assertIn(f' neighbor {peer} override-capability', frrconfig)
if 'passive' in peer_config:
self.assertIn(f' neighbor {peer} passive', frrconfig)
if 'password' in peer_config:
self.assertIn(f' neighbor {peer} password {peer_config["password"]}', frrconfig)
if 'port' in peer_config:
self.assertIn(f' neighbor {peer} port {peer_config["port"]}', frrconfig)
if 'remote_as' in peer_config:
self.assertIn(f' neighbor {peer} remote-as {peer_config["remote_as"]}', frrconfig)
if 'solo' in peer_config:
self.assertIn(f' neighbor {peer} solo', frrconfig)
if 'shutdown' in peer_config:
self.assertIn(f' neighbor {peer} shutdown', frrconfig)
if 'ttl_security' in peer_config:
self.assertIn(f' neighbor {peer} ttl-security hops {peer_config["ttl_security"]}', frrconfig)
if 'update_src' in peer_config:
self.assertIn(f' neighbor {peer} update-source {peer_config["update_src"]}', frrconfig)
if 'route_map_in' in peer_config:
self.assertIn(f' neighbor {peer} route-map {peer_config["route_map_in"]} in', frrconfig)
if 'route_map_out' in peer_config:
self.assertIn(f' neighbor {peer} route-map {peer_config["route_map_out"]} out', frrconfig)
if 'pfx_list_in' in peer_config:
self.assertIn(f' neighbor {peer} prefix-list {peer_config["pfx_list_in"]} in', frrconfig)
if 'pfx_list_out' in peer_config:
self.assertIn(f' neighbor {peer} prefix-list {peer_config["pfx_list_out"]} out', frrconfig)
if 'no_send_comm_std' in peer_config:
self.assertIn(f' no neighbor {peer} send-community', frrconfig)
if 'no_send_comm_ext' in peer_config:
self.assertIn(f' no neighbor {peer} send-community extended', frrconfig)
if 'addpath_all' in peer_config:
self.assertIn(f' neighbor {peer} addpath-tx-all-paths', frrconfig)
if 'p_attr_discard' in peer_config:
self.assertIn(f' neighbor {peer} path-attribute discard {peer_config["p_attr_discard"]}', frrconfig)
if 'addpath_per_as' in peer_config:
self.assertIn(f' neighbor {peer} addpath-tx-bestpath-per-AS', frrconfig)
if 'advertise_map' in peer_config:
base = f' neighbor {peer} advertise-map {peer_config["advertise_map"]}'
if 'exist_map' in peer_config:
base = f'{base} exist-map {peer_config["exist_map"]}'
if 'non_exist_map' in peer_config:
base = f'{base} non-exist-map {peer_config["non_exist_map"]}'
self.assertIn(base, frrconfig)
if 'graceful_rst' in peer_config:
self.assertIn(f' neighbor {peer} graceful-restart', frrconfig)
if 'graceful_rst_no' in peer_config:
self.assertIn(f' neighbor {peer} graceful-restart-disable', frrconfig)
if 'graceful_rst_hlp' in peer_config:
self.assertIn(f' neighbor {peer} graceful-restart-helper', frrconfig)
if 'disable_conn_chk' in peer_config:
self.assertIn(f' neighbor {peer} disable-connected-check', frrconfig)
def test_bgp_01_simple(self):
router_id = '127.0.0.1'
local_pref = '500'
stalepath_time = '60'
max_path_v4 = '2'
max_path_v4ibgp = '4'
max_path_v6 = '8'
max_path_v6ibgp = '16'
cond_adv_timer = '30'
min_hold_time = '2'
tcp_keepalive_idle = '66'
tcp_keepalive_interval = '77'
tcp_keepalive_probes = '22'
self.cli_set(base_path + ['parameters', 'router-id', router_id])
self.cli_set(base_path + ['parameters', 'log-neighbor-changes'])
# System AS number MUST be defined - as this is set in setUp() we remove
# this once for testing of the proper error
self.cli_delete(base_path + ['system-as'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(base_path + ['system-as', ASN])
# Default local preference (higher = more preferred, default value is 100)
self.cli_set(base_path + ['parameters', 'default', 'local-pref', local_pref])
self.cli_set(base_path + ['parameters', 'graceful-restart', 'stalepath-time', stalepath_time])
self.cli_set(base_path + ['parameters', 'graceful-shutdown'])
self.cli_set(base_path + ['parameters', 'ebgp-requires-policy'])
self.cli_set(base_path + ['parameters', 'bestpath', 'as-path', 'multipath-relax'])
self.cli_set(base_path + ['parameters', 'bestpath', 'bandwidth', 'default-weight-for-missing'])
self.cli_set(base_path + ['parameters', 'bestpath', 'compare-routerid'])
self.cli_set(base_path + ['parameters', 'bestpath', 'peer-type', 'multipath-relax'])
self.cli_set(base_path + ['parameters', 'conditional-advertisement', 'timer', cond_adv_timer])
self.cli_set(base_path + ['parameters', 'fast-convergence'])
self.cli_set(base_path + ['parameters', 'minimum-holdtime', min_hold_time])
self.cli_set(base_path + ['parameters', 'no-suppress-duplicates'])
self.cli_set(base_path + ['parameters', 'reject-as-sets'])
self.cli_set(base_path + ['parameters', 'route-reflector-allow-outbound-policy'])
self.cli_set(base_path + ['parameters', 'shutdown'])
self.cli_set(base_path + ['parameters', 'suppress-fib-pending'])
self.cli_set(base_path + ['parameters', 'tcp-keepalive', 'idle', tcp_keepalive_idle])
self.cli_set(base_path + ['parameters', 'tcp-keepalive', 'interval', tcp_keepalive_interval])
self.cli_set(base_path + ['parameters', 'tcp-keepalive', 'probes', tcp_keepalive_probes])
# AFI maximum path support
self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'maximum-paths', 'ebgp', max_path_v4])
self.cli_set(base_path + ['address-family', 'ipv4-unicast', 'maximum-paths', 'ibgp', max_path_v4ibgp])
self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'maximum-paths', 'ebgp', max_path_v6])
self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'maximum-paths', 'ibgp', max_path_v6ibgp])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' bgp router-id {router_id}', frrconfig)
self.assertIn(f' bgp log-neighbor-changes', frrconfig)
self.assertIn(f' bgp default local-preference {local_pref}', frrconfig)
self.assertIn(f' bgp conditional-advertisement timer {cond_adv_timer}', frrconfig)
self.assertIn(f' bgp fast-convergence', frrconfig)
self.assertIn(f' bgp graceful-restart stalepath-time {stalepath_time}', frrconfig)
self.assertIn(f' bgp graceful-shutdown', frrconfig)
self.assertIn(f' bgp bestpath as-path multipath-relax', frrconfig)
self.assertIn(f' bgp bestpath bandwidth default-weight-for-missing', frrconfig)
self.assertIn(f' bgp bestpath compare-routerid', frrconfig)
self.assertIn(f' bgp bestpath peer-type multipath-relax', frrconfig)
self.assertIn(f' bgp minimum-holdtime {min_hold_time}', frrconfig)
self.assertIn(f' bgp reject-as-sets', frrconfig)
self.assertIn(f' bgp route-reflector allow-outbound-policy', frrconfig)
self.assertIn(f' bgp shutdown', frrconfig)
self.assertIn(f' bgp suppress-fib-pending', frrconfig)
self.assertIn(f' bgp tcp-keepalive {tcp_keepalive_idle} {tcp_keepalive_interval} {tcp_keepalive_probes}', frrconfig)
self.assertNotIn(f'bgp ebgp-requires-policy', frrconfig)
self.assertIn(f' no bgp suppress-duplicates', frrconfig)
afiv4_config = self.getFRRconfig(' address-family ipv4 unicast')
self.assertIn(f' maximum-paths {max_path_v4}', afiv4_config)
self.assertIn(f' maximum-paths ibgp {max_path_v4ibgp}', afiv4_config)
afiv6_config = self.getFRRconfig(' address-family ipv6 unicast')
self.assertIn(f' maximum-paths {max_path_v6}', afiv6_config)
self.assertIn(f' maximum-paths ibgp {max_path_v6ibgp}', afiv6_config)
def test_bgp_02_neighbors(self):
# Test out individual neighbor configuration items, not all of them are
# also available to a peer-group!
self.cli_set(base_path + ['parameters', 'deterministic-med'])
for peer, peer_config in neighbor_config.items():
afi = 'ipv4-unicast'
if is_ipv6(peer):
afi = 'ipv6-unicast'
if 'adv_interv' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'advertisement-interval', peer_config["adv_interv"]])
if 'bfd' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'bfd'])
if 'bfd_profile' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'bfd', 'profile', peer_config["bfd_profile"]])
self.cli_set(base_path + ['neighbor', peer, 'bfd', 'check-control-plane-failure'])
if 'cap_dynamic' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'capability', 'dynamic'])
if 'cap_ext_next' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'capability', 'extended-nexthop'])
if 'description' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'description', peer_config["description"]])
if 'no_cap_nego' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'disable-capability-negotiation'])
if 'multi_hop' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'ebgp-multihop', peer_config["multi_hop"]])
if 'local_as' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'local-as', peer_config["local_as"], 'no-prepend', 'replace-as'])
if 'local_role' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'local-role', peer_config["local_role"]])
if 'local_role_strict' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'local-role', peer_config["local_role"], 'strict'])
if 'cap_over' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'override-capability'])
if 'passive' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'passive'])
if 'password' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'password', peer_config["password"]])
if 'port' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'port', peer_config["port"]])
if 'remote_as' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'remote-as', peer_config["remote_as"]])
if 'cap_strict' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'strict-capability-match'])
if 'shutdown' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'shutdown'])
if 'solo' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'solo'])
if 'ttl_security' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'ttl-security', 'hops', peer_config["ttl_security"]])
if 'update_src' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'update-source', peer_config["update_src"]])
if 'p_attr_discard' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'path-attribute', 'discard', peer_config["p_attr_discard"]])
if 'route_map_in' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'route-map', 'import', peer_config["route_map_in"]])
if 'route_map_out' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'route-map', 'export', peer_config["route_map_out"]])
if 'pfx_list_in' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'prefix-list', 'import', peer_config["pfx_list_in"]])
if 'pfx_list_out' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'prefix-list', 'export', peer_config["pfx_list_out"]])
if 'no_send_comm_std' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'disable-send-community', 'standard'])
if 'no_send_comm_ext' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'disable-send-community', 'extended'])
if 'addpath_all' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-all'])
if 'addpath_per_as' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'addpath-tx-per-as'])
if 'graceful_rst' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'enable'])
if 'graceful_rst_no' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'disable'])
if 'graceful_rst_hlp' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'graceful-restart', 'restart-helper'])
if 'disable_conn_chk' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'disable-connected-check'])
# Conditional advertisement
if 'advertise_map' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'advertise-map', peer_config["advertise_map"]])
# Either exist-map or non-exist-map needs to be specified
if 'exist_map' not in peer_config and 'non_exist_map' not in peer_config:
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'exist-map', route_map_in])
if 'exist_map' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'exist-map', peer_config["exist_map"]])
if 'non_exist_map' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'address-family', afi, 'conditionally-advertise', 'non-exist-map', peer_config["non_exist_map"]])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
for peer, peer_config in neighbor_config.items():
if 'adv_interv' in peer_config:
self.assertIn(f' neighbor {peer} advertisement-interval {peer_config["adv_interv"]}', frrconfig)
if 'cap_strict' in peer_config:
self.assertIn(f' neighbor {peer} strict-capability-match', frrconfig)
self.verify_frr_config(peer, peer_config, frrconfig)
def test_bgp_03_peer_groups(self):
# Test out individual peer-group configuration items
for peer_group, config in peer_group_config.items():
if 'bfd' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'bfd'])
if 'bfd_profile' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'bfd', 'profile', config["bfd_profile"]])
self.cli_set(base_path + ['peer-group', peer_group, 'bfd', 'check-control-plane-failure'])
if 'cap_dynamic' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'capability', 'dynamic'])
if 'cap_ext_next' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'capability', 'extended-nexthop'])
if 'description' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'description', config["description"]])
if 'no_cap_nego' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'disable-capability-negotiation'])
if 'multi_hop' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'ebgp-multihop', config["multi_hop"]])
if 'local_as' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'local-as', config["local_as"], 'no-prepend', 'replace-as'])
if 'local_role' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'local-role', config["local_role"]])
if 'local_role_strict' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'local-role', config["local_role"], 'strict'])
if 'cap_over' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'override-capability'])
if 'passive' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'passive'])
if 'password' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'password', config["password"]])
if 'port' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'port', config["port"]])
if 'remote_as' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'remote-as', config["remote_as"]])
if 'shutdown' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'shutdown'])
if 'ttl_security' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'ttl-security', 'hops', config["ttl_security"]])
if 'update_src' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'update-source', config["update_src"]])
if 'route_map_in' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'route-map', 'import', config["route_map_in"]])
if 'route_map_out' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'route-map', 'export', config["route_map_out"]])
if 'pfx_list_in' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'prefix-list', 'import', config["pfx_list_in"]])
if 'pfx_list_out' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'prefix-list', 'export', config["pfx_list_out"]])
if 'no_send_comm_std' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'disable-send-community', 'standard'])
if 'no_send_comm_ext' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'disable-send-community', 'extended'])
if 'addpath_all' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-all'])
if 'addpath_per_as' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'addpath-tx-per-as'])
if 'graceful_rst' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'enable'])
if 'graceful_rst_no' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'disable'])
if 'graceful_rst_hlp' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'graceful-restart', 'restart-helper'])
if 'disable_conn_chk' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'disable-connected-check'])
if 'p_attr_discard' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'path-attribute', 'discard', config["p_attr_discard"]])
# Conditional advertisement
if 'advertise_map' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'advertise-map', config["advertise_map"]])
# Either exist-map or non-exist-map needs to be specified
if 'exist_map' not in config and 'non_exist_map' not in config:
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'exist-map', route_map_in])
if 'exist_map' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'exist-map', config["exist_map"]])
if 'non_exist_map' in config:
self.cli_set(base_path + ['peer-group', peer_group, 'address-family', 'ipv4-unicast', 'conditionally-advertise', 'non-exist-map', config["non_exist_map"]])
for peer, peer_config in neighbor_config.items():
if 'peer_group' in peer_config:
self.cli_set(base_path + ['neighbor', peer, 'peer-group', peer_config['peer_group']])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
for peer, peer_config in peer_group_config.items():
self.assertIn(f' neighbor {peer_group} peer-group', frrconfig)
self.verify_frr_config(peer, peer_config, frrconfig)
for peer, peer_config in neighbor_config.items():
if 'peer_group' in peer_config:
self.assertIn(f' neighbor {peer} peer-group {peer_config["peer_group"]}', frrconfig)
def test_bgp_04_afi_ipv4(self):
networks = {
'10.0.0.0/8' : {
'as_set' : '',
},
'100.64.0.0/10' : {
'as_set' : '',
},
'192.168.0.0/16' : {
'summary_only' : '',
},
}
# We want to redistribute ...
redistributes = ['connected', 'isis', 'kernel', 'ospf', 'rip', 'static']
for redistribute in redistributes:
self.cli_set(base_path + ['address-family', 'ipv4-unicast',
'redistribute', redistribute])
for network, network_config in networks.items():
self.cli_set(base_path + ['address-family', 'ipv4-unicast',
'network', network])
if 'as_set' in network_config:
self.cli_set(base_path + ['address-family', 'ipv4-unicast',
'aggregate-address', network, 'as-set'])
if 'summary_only' in network_config:
self.cli_set(base_path + ['address-family', 'ipv4-unicast',
'aggregate-address', network, 'summary-only'])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' address-family ipv4 unicast', frrconfig)
for redistribute in redistributes:
self.assertIn(f' redistribute {redistribute}', frrconfig)
for network, network_config in networks.items():
self.assertIn(f' network {network}', frrconfig)
if 'as_set' in network_config:
self.assertIn(f' aggregate-address {network} as-set', frrconfig)
if 'summary_only' in network_config:
self.assertIn(f' aggregate-address {network} summary-only', frrconfig)
def test_bgp_05_afi_ipv6(self):
networks = {
'2001:db8:100::/48' : {
},
'2001:db8:200::/48' : {
},
'2001:db8:300::/48' : {
'summary_only' : '',
},
}
# We want to redistribute ...
redistributes = ['connected', 'kernel', 'ospfv3', 'ripng', 'static']
for redistribute in redistributes:
self.cli_set(base_path + ['address-family', 'ipv6-unicast',
'redistribute', redistribute])
for network, network_config in networks.items():
self.cli_set(base_path + ['address-family', 'ipv6-unicast',
'network', network])
if 'summary_only' in network_config:
self.cli_set(base_path + ['address-family', 'ipv6-unicast',
'aggregate-address', network, 'summary-only'])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' address-family ipv6 unicast', frrconfig)
# T2100: By default ebgp-requires-policy is disabled to keep VyOS
# 1.3 and 1.2 backwards compatibility
self.assertIn(f' no bgp ebgp-requires-policy', frrconfig)
for redistribute in redistributes:
# FRR calls this OSPF6
if redistribute == 'ospfv3':
redistribute = 'ospf6'
self.assertIn(f' redistribute {redistribute}', frrconfig)
for network, network_config in networks.items():
self.assertIn(f' network {network}', frrconfig)
if 'as_set' in network_config:
self.assertIn(f' aggregate-address {network} summary-only', frrconfig)
def test_bgp_06_listen_range(self):
# Implemented via T1875
limit = '64'
listen_ranges = ['192.0.2.0/25', '192.0.2.128/25']
peer_group = 'listenfoobar'
self.cli_set(base_path + ['listen', 'limit', limit])
for prefix in listen_ranges:
self.cli_set(base_path + ['listen', 'range', prefix])
# check validate() - peer-group must be defined for range/prefix
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(base_path + ['listen', 'range', prefix, 'peer-group', peer_group])
# check validate() - peer-group does yet not exist!
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(base_path + ['peer-group', peer_group, 'remote-as', ASN])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' neighbor {peer_group} peer-group', frrconfig)
self.assertIn(f' neighbor {peer_group} remote-as {ASN}', frrconfig)
self.assertIn(f' bgp listen limit {limit}', frrconfig)
for prefix in listen_ranges:
self.assertIn(f' bgp listen range {prefix} peer-group {peer_group}', frrconfig)
-
def test_bgp_07_l2vpn_evpn(self):
vnis = ['10010', '10020', '10030']
neighbors = ['192.0.2.10', '192.0.2.20', '192.0.2.30']
self.cli_set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-all-vni'])
self.cli_set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-default-gw'])
self.cli_set(base_path + ['address-family', 'l2vpn-evpn', 'advertise-svi-ip'])
self.cli_set(base_path + ['address-family', 'l2vpn-evpn', 'flooding', 'disable'])
for vni in vnis:
self.cli_set(base_path + ['address-family', 'l2vpn-evpn', 'vni', vni, 'advertise-default-gw'])
self.cli_set(base_path + ['address-family', 'l2vpn-evpn', 'vni', vni, 'advertise-svi-ip'])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' address-family l2vpn evpn', frrconfig)
self.assertIn(f' advertise-all-vni', frrconfig)
self.assertIn(f' advertise-default-gw', frrconfig)
self.assertIn(f' advertise-svi-ip', frrconfig)
self.assertIn(f' flooding disable', frrconfig)
for vni in vnis:
vniconfig = self.getFRRconfig(f' vni {vni}')
self.assertIn(f'vni {vni}', vniconfig)
self.assertIn(f' advertise-default-gw', vniconfig)
self.assertIn(f' advertise-svi-ip', vniconfig)
- def test_bgp_08_zebra_route_map(self):
- # Implemented because of T3328
- self.cli_set(base_path + ['route-map', route_map_in])
- # commit changes
- self.cli_commit()
-
- # Verify FRR configuration
- zebra_route_map = f'ip protocol bgp route-map {route_map_in}'
- frrconfig = self.getFRRconfig(zebra_route_map)
- self.assertIn(zebra_route_map, frrconfig)
-
- # Remove the route-map again
- self.cli_delete(base_path + ['route-map'])
- # commit changes
- self.cli_commit()
-
- # Verify FRR configuration
- frrconfig = self.getFRRconfig(zebra_route_map)
- self.assertNotIn(zebra_route_map, frrconfig)
-
def test_bgp_09_distance_and_flowspec(self):
distance_external = '25'
distance_internal = '30'
distance_local = '35'
distance_v4_prefix = '169.254.0.0/32'
distance_v6_prefix = '2001::/128'
distance_prefix_value = '110'
distance_families = ['ipv4-unicast', 'ipv6-unicast','ipv4-multicast', 'ipv6-multicast']
verify_families = ['ipv4 unicast', 'ipv6 unicast','ipv4 multicast', 'ipv6 multicast']
flowspec_families = ['address-family ipv4 flowspec', 'address-family ipv6 flowspec']
flowspec_int = 'lo'
# Per family distance support
for family in distance_families:
self.cli_set(base_path + ['address-family', family, 'distance', 'external', distance_external])
self.cli_set(base_path + ['address-family', family, 'distance', 'internal', distance_internal])
self.cli_set(base_path + ['address-family', family, 'distance', 'local', distance_local])
if 'ipv4' in family:
self.cli_set(base_path + ['address-family', family, 'distance',
'prefix', distance_v4_prefix, 'distance', distance_prefix_value])
if 'ipv6' in family:
self.cli_set(base_path + ['address-family', family, 'distance',
'prefix', distance_v6_prefix, 'distance', distance_prefix_value])
# IPv4 flowspec interface check
self.cli_set(base_path + ['address-family', 'ipv4-flowspec', 'local-install', 'interface', flowspec_int])
# IPv6 flowspec interface check
self.cli_set(base_path + ['address-family', 'ipv6-flowspec', 'local-install', 'interface', flowspec_int])
# Commit changes
self.cli_commit()
# Verify FRR distances configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
for family in verify_families:
self.assertIn(f'address-family {family}', frrconfig)
self.assertIn(f'distance bgp {distance_external} {distance_internal} {distance_local}', frrconfig)
if 'ipv4' in family:
self.assertIn(f'distance {distance_prefix_value} {distance_v4_prefix}', frrconfig)
if 'ipv6' in family:
self.assertIn(f'distance {distance_prefix_value} {distance_v6_prefix}', frrconfig)
# Verify FRR flowspec configuration
for family in flowspec_families:
self.assertIn(f'{family}', frrconfig)
self.assertIn(f'local-install {flowspec_int}', frrconfig)
def test_bgp_10_vrf_simple(self):
router_id = '127.0.0.3'
vrfs = ['red', 'green', 'blue']
# It is safe to assume that when the basic VRF test works, all
# other BGP related features work, as we entirely inherit the CLI
# templates and Jinja2 FRR template.
table = '1000'
self.cli_set(base_path + ['system-as', ASN])
# testing only one AFI is sufficient as it's generic code
for vrf in vrfs:
vrf_base = ['vrf', 'name', vrf]
self.cli_set(vrf_base + ['table', table])
self.cli_set(vrf_base + ['protocols', 'bgp', 'system-as', ASN])
self.cli_set(vrf_base + ['protocols', 'bgp', 'parameters', 'router-id', router_id])
self.cli_set(vrf_base + ['protocols', 'bgp', 'route-map', route_map_in])
table = str(int(table) + 1000)
# import VRF routes do main RIB
self.cli_set(base_path + ['address-family', 'ipv6-unicast', 'import', 'vrf', vrf])
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' address-family ipv6 unicast', frrconfig)
for vrf in vrfs:
self.assertIn(f' import vrf {vrf}', frrconfig)
# Verify FRR bgpd configuration
frr_vrf_config = self.getFRRconfig(f'router bgp {ASN} vrf {vrf}')
self.assertIn(f'router bgp {ASN} vrf {vrf}', frr_vrf_config)
self.assertIn(f' bgp router-id {router_id}', frr_vrf_config)
# XXX: Currently this is not working as FRR() class does not support
# route-maps for multiple vrfs because the modify_section() only works
# on lines and not text blocks.
#
# vrfconfig = self.getFRRconfig(f'vrf {vrf}')
# zebra_route_map = f' ip protocol bgp route-map {route_map_in}'
# self.assertIn(zebra_route_map, vrfconfig)
def test_bgp_11_confederation(self):
router_id = '127.10.10.2'
confed_id = str(int(ASN) + 1)
confed_asns = '10 20 30 40'
self.cli_set(base_path + ['system-as', ASN])
self.cli_set(base_path + ['parameters', 'router-id', router_id])
self.cli_set(base_path + ['parameters', 'confederation', 'identifier', confed_id])
for asn in confed_asns.split():
self.cli_set(base_path + ['parameters', 'confederation', 'peers', asn])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' bgp router-id {router_id}', frrconfig)
self.assertIn(f' bgp confederation identifier {confed_id}', frrconfig)
self.assertIn(f' bgp confederation peers {confed_asns}', frrconfig)
def test_bgp_12_v6_link_local(self):
remote_asn = str(int(ASN) + 10)
interface = 'eth0'
self.cli_set(base_path + ['system-as', ASN])
self.cli_set(base_path + ['neighbor', interface, 'address-family', 'ipv6-unicast'])
self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as', remote_asn])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' neighbor {interface} interface v6only remote-as {remote_asn}', frrconfig)
self.assertIn(f' address-family ipv6 unicast', frrconfig)
self.assertIn(f' neighbor {interface} activate', frrconfig)
self.assertIn(f' exit-address-family', frrconfig)
def test_bgp_13_vpn(self):
remote_asn = str(int(ASN) + 150)
neighbor = '192.0.2.55'
vrf_name = 'red'
label = 'auto'
rd = f'{neighbor}:{ASN}'
rt_export = f'{neighbor}:1002 1.2.3.4:567'
rt_import = f'{neighbor}:1003 500:100'
self.cli_set(base_path + ['system-as', ASN])
# testing only one AFI is sufficient as it's generic code
for afi in ['ipv4-unicast', 'ipv6-unicast']:
self.cli_set(base_path + ['address-family', afi, 'export', 'vpn'])
self.cli_set(base_path + ['address-family', afi, 'import', 'vpn'])
self.cli_set(base_path + ['address-family', afi, 'label', 'vpn', 'export', label])
self.cli_set(base_path + ['address-family', afi, 'rd', 'vpn', 'export', rd])
self.cli_set(base_path + ['address-family', afi, 'route-map', 'vpn', 'export', route_map_out])
self.cli_set(base_path + ['address-family', afi, 'route-map', 'vpn', 'import', route_map_in])
self.cli_set(base_path + ['address-family', afi, 'route-target', 'vpn', 'export', rt_export])
self.cli_set(base_path + ['address-family', afi, 'route-target', 'vpn', 'import', rt_import])
# commit changes
self.cli_commit()
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
for afi in ['ipv4', 'ipv6']:
afi_config = self.getFRRconfig(f' address-family {afi} unicast', endsection='exit-address-family', daemon='bgpd')
self.assertIn(f'address-family {afi} unicast', afi_config)
self.assertIn(f' export vpn', afi_config)
self.assertIn(f' import vpn', afi_config)
self.assertIn(f' label vpn export {label}', afi_config)
self.assertIn(f' rd vpn export {rd}', afi_config)
self.assertIn(f' route-map vpn export {route_map_out}', afi_config)
self.assertIn(f' route-map vpn import {route_map_in}', afi_config)
self.assertIn(f' rt vpn export {rt_export}', afi_config)
self.assertIn(f' rt vpn import {rt_import}', afi_config)
self.assertIn(f' exit-address-family', afi_config)
def test_bgp_14_remote_as_peer_group_override(self):
# Peer-group member cannot override remote-as of peer-group
remote_asn = str(int(ASN) + 150)
neighbor = '192.0.2.1'
peer_group = 'bar'
interface = 'eth0'
self.cli_set(base_path + ['system-as', ASN])
self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn])
self.cli_set(base_path + ['neighbor', neighbor, 'peer-group', peer_group])
self.cli_set(base_path + ['peer-group', peer_group, 'remote-as', remote_asn])
# Peer-group member cannot override remote-as of peer-group
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_delete(base_path + ['neighbor', neighbor, 'remote-as'])
# re-test with interface based peer-group
self.cli_set(base_path + ['neighbor', interface, 'interface', 'peer-group', peer_group])
self.cli_set(base_path + ['neighbor', interface, 'interface', 'remote-as', 'external'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_delete(base_path + ['neighbor', interface, 'interface', 'remote-as'])
# re-test with interface based v6only peer-group
self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'peer-group', peer_group])
self.cli_set(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as', 'external'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_delete(base_path + ['neighbor', interface, 'interface', 'v6only', 'remote-as'])
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' neighbor {neighbor} peer-group {peer_group}', frrconfig)
self.assertIn(f' neighbor {peer_group} peer-group', frrconfig)
self.assertIn(f' neighbor {peer_group} remote-as {remote_asn}', frrconfig)
def test_bgp_15_local_as_ebgp(self):
# https://vyos.dev/T4560
# local-as allowed only for ebgp peers
neighbor = '192.0.2.99'
remote_asn = '500'
local_asn = '400'
self.cli_set(base_path + ['system-as', ASN])
self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', ASN])
self.cli_set(base_path + ['neighbor', neighbor, 'local-as', local_asn])
# check validate() - local-as allowed only for ebgp peers
with self.assertRaises(ConfigSessionError):
self.cli_commit()
self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn])
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f' neighbor {neighbor} remote-as {remote_asn}', frrconfig)
self.assertIn(f' neighbor {neighbor} local-as {local_asn}', frrconfig)
def test_bgp_16_import_rd_rt_compatibility(self):
# Verify if import vrf and rd vpn export
# exist in the same address family
self.create_bgp_instances_for_import_test()
self.cli_set(
base_path + ['address-family', import_afi, 'import', 'vrf',
import_vrf])
self.cli_set(
base_path + ['address-family', import_afi, 'rd', 'vpn', 'export',
import_rd])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
def test_bgp_17_import_rd_rt_compatibility(self):
# Verify if vrf that is in import vrf list contains rd vpn export
self.create_bgp_instances_for_import_test()
self.cli_set(
base_path + ['address-family', import_afi, 'import', 'vrf',
import_vrf])
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f'address-family ipv4 unicast', frrconfig)
self.assertIn(f' import vrf {import_vrf}', frrconfig)
self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf)
self.cli_set(
import_vrf_base + [import_vrf] + base_path + ['address-family',
import_afi, 'rd',
'vpn', 'export',
import_rd])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
def test_bgp_18_deleting_import_vrf(self):
# Verify deleting vrf that is in import vrf list
self.create_bgp_instances_for_import_test()
self.cli_set(
base_path + ['address-family', import_afi, 'import', 'vrf',
import_vrf])
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f'address-family ipv4 unicast', frrconfig)
self.assertIn(f' import vrf {import_vrf}', frrconfig)
self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf)
self.cli_delete(import_vrf_base + [import_vrf])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
def test_bgp_19_deleting_default_vrf(self):
# Verify deleting existent vrf default if other vrfs were created
self.create_bgp_instances_for_import_test()
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf)
self.cli_delete(base_path)
with self.assertRaises(ConfigSessionError):
self.cli_commit()
def test_bgp_20_import_rd_rt_compatibility(self):
# Verify if vrf that has rd vpn export is in import vrf of other vrfs
self.create_bgp_instances_for_import_test()
self.cli_set(
import_vrf_base + [import_vrf] + base_path + ['address-family',
import_afi, 'rd',
'vpn', 'export',
import_rd])
self.cli_commit()
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
frrconfig_vrf = self.getFRRconfig(f'router bgp {ASN} vrf {import_vrf}')
self.assertIn(f'router bgp {ASN}', frrconfig)
self.assertIn(f'router bgp {ASN} vrf {import_vrf}', frrconfig_vrf)
self.assertIn(f'address-family ipv4 unicast', frrconfig_vrf)
self.assertIn(f' rd vpn export {import_rd}', frrconfig_vrf)
self.cli_set(
base_path + ['address-family', import_afi, 'import', 'vrf',
import_vrf])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
def test_bgp_21_import_unspecified_vrf(self):
# Verify if vrf that is in import is unspecified
self.create_bgp_instances_for_import_test()
self.cli_set(
base_path + ['address-family', import_afi, 'import', 'vrf',
'test'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index cf553f0e8..66505e58d 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -1,529 +1,518 @@
#!/usr/bin/env python3
#
# Copyright (C) 2020-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from sys import exit
from sys import argv
from vyos.base import Warning
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configverify import verify_prefix_list
from vyos.configverify import verify_route_map
from vyos.configverify import verify_vrf
from vyos.template import is_ip
from vyos.template import is_interface
from vyos.template import render_to_string
from vyos.util import dict_search
from vyos.validate import is_addr_assigned
from vyos import ConfigError
from vyos import frr
from vyos import airbag
airbag.enable()
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
vrf = None
if len(argv) > 1:
vrf = argv[1]
base_path = ['protocols', 'bgp']
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'bgp'] or base_path
bgp = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
# instead of the VRF instance.
if vrf: bgp.update({'vrf' : vrf})
bgp['dependent_vrfs'] = conf.get_config_dict(['vrf', 'name'],
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)
bgp['dependent_vrfs'].update({'default': {'protocols': {
'bgp': conf.get_config_dict(base_path, key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)}}})
if not conf.exists(base):
# If bgp instance is deleted then mark it
bgp.update({'deleted' : ''})
return bgp
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify().
#
# XXX: one MUST always call this without the key_mangling() option! See
# vyos.configverify.verify_common_route_maps() for more information.
tmp = conf.get_config_dict(['policy'])
# Merge policy dict into "regular" config dict
bgp = dict_merge(tmp, bgp)
return bgp
def verify_vrf_as_import(search_vrf_name: str, afi_name: str, vrfs_config: dict) -> bool:
"""
:param search_vrf_name: search vrf name in import list
:type search_vrf_name: str
:param afi_name: afi/safi name
:type afi_name: str
:param vrfs_config: configuration dependents vrfs
:type vrfs_config: dict
:return: if vrf in import list retrun true else false
:rtype: bool
"""
for vrf_name, vrf_config in vrfs_config.items():
import_list = dict_search(
f'protocols.bgp.address_family.{afi_name}.import.vrf',
vrf_config)
if import_list:
if search_vrf_name in import_list:
return True
return False
def verify_vrf_import_options(afi_config: dict) -> bool:
"""
Search if afi contains one of options
:param afi_config: afi/safi
:type afi_config: dict
:return: if vrf contains rd and route-target options return true else false
:rtype: bool
"""
options = [
f'rd.vpn.export',
f'route_target.vpn.import',
f'route_target.vpn.export',
f'route_target.vpn.both'
]
for option in options:
if dict_search(option, afi_config):
return True
return False
def verify_vrf_import(vrf_name: str, vrfs_config: dict, afi_name: str) -> bool:
"""
Verify if vrf exists and contain options
:param vrf_name: name of VRF
:type vrf_name: str
:param vrfs_config: dependent vrfs config
:type vrfs_config: dict
:param afi_name: afi/safi name
:type afi_name: str
:return: if vrf contains rd and route-target options return true else false
:rtype: bool
"""
if vrf_name != 'default':
verify_vrf({'vrf': vrf_name})
if dict_search(f'{vrf_name}.protocols.bgp.address_family.{afi_name}',
vrfs_config):
afi_config = \
vrfs_config[vrf_name]['protocols']['bgp']['address_family'][
afi_name]
if verify_vrf_import_options(afi_config):
return True
return False
def verify_vrflist_import(afi_name: str, afi_config: dict, vrfs_config: dict) -> bool:
"""
Call function to verify
if scpecific vrf contains rd and route-target
options return true else false
:param afi_name: afi/safi name
:type afi_name: str
:param afi_config: afi/safi configuration
:type afi_config: dict
:param vrfs_config: dependent vrfs config
:type vrfs_config:dict
:return: if vrf contains rd and route-target options return true else false
:rtype: bool
"""
for vrf_name in afi_config['import']['vrf']:
if verify_vrf_import(vrf_name, vrfs_config, afi_name):
return True
return False
def verify_remote_as(peer_config, bgp_config):
if 'remote_as' in peer_config:
return peer_config['remote_as']
if 'peer_group' in peer_config:
peer_group_name = peer_config['peer_group']
tmp = dict_search(f'peer_group.{peer_group_name}.remote_as', bgp_config)
if tmp: return tmp
if 'interface' in peer_config:
if 'remote_as' in peer_config['interface']:
return peer_config['interface']['remote_as']
if 'peer_group' in peer_config['interface']:
peer_group_name = peer_config['interface']['peer_group']
tmp = dict_search(f'peer_group.{peer_group_name}.remote_as', bgp_config)
if tmp: return tmp
if 'v6only' in peer_config['interface']:
if 'remote_as' in peer_config['interface']['v6only']:
return peer_config['interface']['v6only']['remote_as']
return None
def verify_afi(peer_config, bgp_config):
if 'address_family' in peer_config:
return True
if 'peer_group' in peer_config:
peer_group_name = peer_config['peer_group']
tmp = dict_search(f'peer_group.{peer_group_name}.address_family', bgp_config)
if tmp: return True
return False
def verify(bgp):
if 'deleted' in bgp:
if 'vrf' in bgp:
# Cannot delete vrf if it exists in import vrf list in other vrfs
for tmp_afi in ['ipv4_unicast', 'ipv6_unicast']:
if verify_vrf_as_import(bgp['vrf'],tmp_afi,bgp['dependent_vrfs']):
raise ConfigError(f'Cannot delete vrf {bgp["vrf"]} instance, ' \
'Please unconfigure import vrf commands!')
else:
# We are running in the default VRF context, thus we can not delete
# our main BGP instance if there are dependent BGP VRF instances.
if 'dependent_vrfs' in bgp:
for vrf, vrf_options in bgp['dependent_vrfs'].items():
if vrf != 'default':
if dict_search('protocols.bgp', vrf_options):
raise ConfigError('Cannot delete default BGP instance, ' \
'dependent VRF instance(s) exist!')
return None
if 'system_as' not in bgp:
raise ConfigError('BGP system-as number must be defined!')
# Common verification for both peer-group and neighbor statements
for neighbor in ['neighbor', 'peer_group']:
# bail out early if there is no neighbor or peer-group statement
# this also saves one indention level
if neighbor not in bgp:
continue
for peer, peer_config in bgp[neighbor].items():
# Only regular "neighbor" statement can have a peer-group set
# Check if the configure peer-group exists
if 'peer_group' in peer_config:
peer_group = peer_config['peer_group']
if 'peer_group' not in bgp or peer_group not in bgp['peer_group']:
raise ConfigError(f'Specified peer-group "{peer_group}" for '\
f'neighbor "{neighbor}" does not exist!')
if 'local_role' in peer_config:
#Ensure Local Role has only one value.
if len(peer_config['local_role']) > 1:
raise ConfigError(f'Only one local role can be specified for peer "{peer}"!')
if 'local_as' in peer_config:
if len(peer_config['local_as']) > 1:
raise ConfigError(f'Only one local-as number can be specified for peer "{peer}"!')
# Neighbor local-as override can not be the same as the local-as
# we use for this BGP instane!
asn = list(peer_config['local_as'].keys())[0]
if asn == bgp['system_as']:
raise ConfigError('Cannot have local-as same as system-as number')
# Neighbor AS specified for local-as and remote-as can not be the same
if dict_search('remote_as', peer_config) == asn:
raise ConfigError(f'Neighbor "{peer}" has local-as specified which is '\
'the same as remote-as, this is not allowed!')
# ttl-security and ebgp-multihop can't be used in the same configration
if 'ebgp_multihop' in peer_config and 'ttl_security' in peer_config:
raise ConfigError('You can not set both ebgp-multihop and ttl-security hops')
# interface and ebgp-multihop can't be used in the same configration
if 'ebgp_multihop' in peer_config and 'interface' in peer_config:
raise ConfigError(f'Ebgp-multihop can not be used with directly connected '\
f'neighbor "{peer}"')
# Check if neighbor has both override capability and strict capability match
# configured at the same time.
if 'override_capability' in peer_config and 'strict_capability_match' in peer_config:
raise ConfigError(f'Neighbor "{peer}" cannot have both override-capability and '\
'strict-capability-match configured at the same time!')
# Check spaces in the password
if 'password' in peer_config and ' ' in peer_config['password']:
raise ConfigError('Whitespace is not allowed in passwords!')
# Some checks can/must only be done on a neighbor and not a peer-group
if neighbor == 'neighbor':
# remote-as must be either set explicitly for the neighbor
# or for the entire peer-group
if not verify_remote_as(peer_config, bgp):
raise ConfigError(f'Neighbor "{peer}" remote-as must be set!')
if not verify_afi(peer_config, bgp):
Warning(f'BGP neighbor "{peer}" requires address-family!')
# Peer-group member cannot override remote-as of peer-group
if 'peer_group' in peer_config:
peer_group = peer_config['peer_group']
if 'remote_as' in peer_config and 'remote_as' in bgp['peer_group'][peer_group]:
raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!')
if 'interface' in peer_config:
if 'peer_group' in peer_config['interface']:
peer_group = peer_config['interface']['peer_group']
if 'remote_as' in peer_config['interface'] and 'remote_as' in bgp['peer_group'][peer_group]:
raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!')
if 'v6only' in peer_config['interface']:
if 'peer_group' in peer_config['interface']['v6only']:
peer_group = peer_config['interface']['v6only']['peer_group']
if 'remote_as' in peer_config['interface']['v6only'] and 'remote_as' in bgp['peer_group'][peer_group]:
raise ConfigError(f'Peer-group member "{peer}" cannot override remote-as of peer-group "{peer_group}"!')
# Only checks for ipv4 and ipv6 neighbors
# Check if neighbor address is assigned as system interface address
vrf = None
vrf_error_msg = f' in default VRF!'
if 'vrf' in bgp:
vrf = bgp['vrf']
vrf_error_msg = f' in VRF "{vrf}"!'
if is_ip(peer) and is_addr_assigned(peer, vrf):
raise ConfigError(f'Can not configure local address as neighbor "{peer}"{vrf_error_msg}')
elif is_interface(peer):
if 'peer_group' in peer_config:
raise ConfigError(f'peer-group must be set under the interface node of "{peer}"')
if 'remote_as' in peer_config:
raise ConfigError(f'remote-as must be set under the interface node of "{peer}"')
if 'source_interface' in peer_config['interface']:
raise ConfigError(f'"source-interface" option not allowed for neighbor "{peer}"')
# Local-AS allowed only for EBGP peers
if 'local_as' in peer_config:
remote_as = verify_remote_as(peer_config, bgp)
if remote_as == bgp['system_as']:
raise ConfigError(f'local-as configured for "{peer}", allowed only for eBGP peers!')
for afi in ['ipv4_unicast', 'ipv4_multicast', 'ipv4_labeled_unicast', 'ipv4_flowspec',
'ipv6_unicast', 'ipv6_multicast', 'ipv6_labeled_unicast', 'ipv6_flowspec',
'l2vpn_evpn']:
# Bail out early if address family is not configured
if 'address_family' not in peer_config or afi not in peer_config['address_family']:
continue
# Check if neighbor has both ipv4 unicast and ipv4 labeled unicast configured at the same time.
if 'ipv4_unicast' in peer_config['address_family'] and 'ipv4_labeled_unicast' in peer_config['address_family']:
raise ConfigError(f'Neighbor "{peer}" cannot have both ipv4-unicast and ipv4-labeled-unicast configured at the same time!')
# Check if neighbor has both ipv6 unicast and ipv6 labeled unicast configured at the same time.
if 'ipv6_unicast' in peer_config['address_family'] and 'ipv6_labeled_unicast' in peer_config['address_family']:
raise ConfigError(f'Neighbor "{peer}" cannot have both ipv6-unicast and ipv6-labeled-unicast configured at the same time!')
afi_config = peer_config['address_family'][afi]
if 'conditionally_advertise' in afi_config:
if 'advertise_map' not in afi_config['conditionally_advertise']:
raise ConfigError('Must speficy advertise-map when conditionally-advertise is in use!')
# Verify advertise-map (which is a route-map) exists
verify_route_map(afi_config['conditionally_advertise']['advertise_map'], bgp)
if ('exist_map' not in afi_config['conditionally_advertise'] and
'non_exist_map' not in afi_config['conditionally_advertise']):
raise ConfigError('Must either speficy exist-map or non-exist-map when ' \
'conditionally-advertise is in use!')
if {'exist_map', 'non_exist_map'} <= set(afi_config['conditionally_advertise']):
raise ConfigError('Can not specify both exist-map and non-exist-map for ' \
'conditionally-advertise!')
if 'exist_map' in afi_config['conditionally_advertise']:
verify_route_map(afi_config['conditionally_advertise']['exist_map'], bgp)
if 'non_exist_map' in afi_config['conditionally_advertise']:
verify_route_map(afi_config['conditionally_advertise']['non_exist_map'], bgp)
# T4332: bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use
if 'addpath_tx_per_as' in afi_config:
if dict_search('parameters.deterministic_med', bgp) == None:
raise ConfigError('addpath-tx-per-as requires BGP deterministic-med paramtere to be set!')
# Validate if configured Prefix list exists
if 'prefix_list' in afi_config:
for tmp in ['import', 'export']:
if tmp not in afi_config['prefix_list']:
# bail out early
continue
if afi == 'ipv4_unicast':
verify_prefix_list(afi_config['prefix_list'][tmp], bgp)
elif afi == 'ipv6_unicast':
verify_prefix_list(afi_config['prefix_list'][tmp], bgp, version='6')
if 'route_map' in afi_config:
for tmp in ['import', 'export']:
if tmp in afi_config['route_map']:
verify_route_map(afi_config['route_map'][tmp], bgp)
if 'route_reflector_client' in afi_config:
if 'remote_as' in peer_config and peer_config['remote_as'] != 'internal' and peer_config['remote_as'] != bgp['system_as']:
raise ConfigError('route-reflector-client only supported for iBGP peers')
else:
if 'peer_group' in peer_config:
peer_group_as = dict_search(f'peer_group.{peer_group}.remote_as', bgp)
if peer_group_as != None and peer_group_as != 'internal' and peer_group_as != bgp['system_as']:
raise ConfigError('route-reflector-client only supported for iBGP peers')
# Throw an error if a peer group is not configured for allow range
for prefix in dict_search('listen.range', bgp) or []:
# we can not use dict_search() here as prefix contains dots ...
if 'peer_group' not in bgp['listen']['range'][prefix]:
raise ConfigError(f'Listen range for prefix "{prefix}" has no peer group configured.')
peer_group = bgp['listen']['range'][prefix]['peer_group']
if 'peer_group' not in bgp or peer_group not in bgp['peer_group']:
raise ConfigError(f'Peer-group "{peer_group}" for listen range "{prefix}" does not exist!')
if not verify_remote_as(bgp['listen']['range'][prefix], bgp):
raise ConfigError(f'Peer-group "{peer_group}" requires remote-as to be set!')
# Throw an error if the global administrative distance parameters aren't all filled out.
if dict_search('parameters.distance.global', bgp) != None:
for key in ['external', 'internal', 'local']:
if dict_search(f'parameters.distance.global.{key}', bgp) == None:
raise ConfigError('Missing mandatory configuration option for '\
f'global administrative distance {key}!')
# TCP keepalive requires all three parameters to be set
if dict_search('parameters.tcp_keepalive', bgp) != None:
if not {'idle', 'interval', 'probes'} <= set(bgp['parameters']['tcp_keepalive']):
raise ConfigError('TCP keepalive incomplete - idle, keepalive and probes must be set')
# Address Family specific validation
if 'address_family' in bgp:
for afi, afi_config in bgp['address_family'].items():
if 'distance' in afi_config:
# Throw an error if the address family specific administrative
# distance parameters aren't all filled out.
for key in ['external', 'internal', 'local']:
if key not in afi_config['distance']:
raise ConfigError('Missing mandatory configuration option for '\
f'{afi} administrative distance {key}!')
if afi in ['ipv4_unicast', 'ipv6_unicast']:
vrf_name = bgp['vrf'] if dict_search('vrf', bgp) else 'default'
# Verify if currant VRF contains rd and route-target options
# and does not exist in import list in other VRFs
if dict_search(f'rd.vpn.export', afi_config):
if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']):
raise ConfigError(
'Command "import vrf" conflicts with "rd vpn export" command!')
if dict_search('route_target.vpn.both', afi_config):
if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']):
raise ConfigError(
'Command "import vrf" conflicts with "route-target vpn both" command!')
if dict_search('route_target.vpn.import', afi_config):
if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']):
raise ConfigError(
'Command "import vrf conflicts" with "route-target vpn import" command!')
if dict_search('route_target.vpn.export', afi_config):
if verify_vrf_as_import(vrf_name, afi, bgp['dependent_vrfs']):
raise ConfigError(
'Command "import vrf" conflicts with "route-target vpn export" command!')
# Verify if VRFs in import do not contain rd
# and route-target options
if dict_search('import.vrf', afi_config) is not None:
# Verify if VRF with import does not contain rd
# and route-target options
if verify_vrf_import_options(afi_config):
raise ConfigError(
'Please unconfigure "import vrf" commands before using vpn commands in the same VRF!')
# Verify if VRFs in import list do not contain rd
# and route-target options
if verify_vrflist_import(afi, afi_config, bgp['dependent_vrfs']):
raise ConfigError(
'Please unconfigure import vrf commands before using vpn commands in dependent VRFs!')
# FRR error: please unconfigure vpn to vrf commands before
# using import vrf commands
if 'vpn' in afi_config['import'] or dict_search('export.vpn', afi_config) != None:
raise ConfigError('Please unconfigure VPN to VRF commands before '\
'using "import vrf" commands!')
# Verify that the export/import route-maps do exist
for export_import in ['export', 'import']:
tmp = dict_search(f'route_map.vpn.{export_import}', afi_config)
if tmp: verify_route_map(tmp, bgp)
return None
def generate(bgp):
if not bgp or 'deleted' in bgp:
return None
- bgp['protocol'] = 'bgp' # required for frr/vrf.route-map.frr.j2
- bgp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', bgp)
bgp['frr_bgpd_config'] = render_to_string('frr/bgpd.frr.j2', bgp)
-
return None
def apply(bgp):
bgp_daemon = 'bgpd'
- zebra_daemon = 'zebra'
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
- # The route-map used for the FIB (zebra) is part of the zebra daemon
- frr_cfg.load_configuration(zebra_daemon)
- frr_cfg.modify_section(r'(\s+)?ip protocol bgp route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)')
- if 'frr_zebra_config' in bgp:
- frr_cfg.add_before(frr.default_add_before, bgp['frr_zebra_config'])
- frr_cfg.commit_configuration(zebra_daemon)
-
# Generate empty helper string which can be ammended to FRR commands, it
# will be either empty (default VRF) or contain the "vrf <name" statement
vrf = ''
if 'vrf' in bgp:
vrf = ' vrf ' + bgp['vrf']
frr_cfg.load_configuration(bgp_daemon)
frr_cfg.modify_section(f'^router bgp \d+{vrf}', stop_pattern='^exit', remove_stop_mark=True)
if 'frr_bgpd_config' in bgp:
frr_cfg.add_before(frr.default_add_before, bgp['frr_bgpd_config'])
frr_cfg.commit_configuration(bgp_daemon)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/conf_mode/protocols_eigrp.py b/src/conf_mode/protocols_eigrp.py
index 6e75e34ff..609b39065 100755
--- a/src/conf_mode/protocols_eigrp.py
+++ b/src/conf_mode/protocols_eigrp.py
@@ -1,121 +1,111 @@
#!/usr/bin/env python3
#
# Copyright (C) 2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from sys import exit
from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.template import render_to_string
from vyos import ConfigError
from vyos import frr
from vyos import airbag
airbag.enable()
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
vrf = None
if len(argv) > 1:
vrf = argv[1]
base_path = ['protocols', 'eigrp']
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'eigrp'] or base_path
eigrp = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
# instead of the VRF instance.
if vrf: eigrp.update({'vrf' : vrf})
if not conf.exists(base):
eigrp.update({'deleted' : ''})
if not vrf:
# We are running in the default VRF context, thus we can not delete
# our main EIGRP instance if there are dependent EIGRP VRF instances.
eigrp['dependent_vrfs'] = conf.get_config_dict(['vrf', 'name'],
key_mangling=('-', '_'),
get_first_key=True,
no_tag_node_value_mangle=True)
return eigrp
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify().
#
# XXX: one MUST always call this without the key_mangling() option! See
# vyos.configverify.verify_common_route_maps() for more information.
tmp = conf.get_config_dict(['policy'])
# Merge policy dict into "regular" config dict
eigrp = dict_merge(tmp, eigrp)
return eigrp
def verify(eigrp):
pass
def generate(eigrp):
if not eigrp or 'deleted' in eigrp:
return None
- eigrp['protocol'] = 'eigrp' # required for frr/vrf.route-map.frr.j2
- eigrp['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', eigrp)
eigrp['frr_eigrpd_config'] = render_to_string('frr/eigrpd.frr.j2', eigrp)
def apply(eigrp):
eigrp_daemon = 'eigrpd'
- zebra_daemon = 'zebra'
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
- # The route-map used for the FIB (zebra) is part of the zebra daemon
- frr_cfg.load_configuration(zebra_daemon)
- frr_cfg.modify_section(r'(\s+)?ip protocol eigrp route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)')
- if 'frr_zebra_config' in eigrp:
- frr_cfg.add_before(frr.default_add_before, eigrp['frr_zebra_config'])
- frr_cfg.commit_configuration(zebra_daemon)
-
# Generate empty helper string which can be ammended to FRR commands, it
# will be either empty (default VRF) or contain the "vrf <name" statement
vrf = ''
if 'vrf' in eigrp:
vrf = ' vrf ' + eigrp['vrf']
frr_cfg.load_configuration(eigrp_daemon)
frr_cfg.modify_section(f'^router eigrp \d+{vrf}', stop_pattern='^exit', remove_stop_mark=True)
if 'frr_eigrpd_config' in eigrp:
frr_cfg.add_before(frr.default_add_before, eigrp['frr_eigrpd_config'])
frr_cfg.commit_configuration(eigrp_daemon)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
index cb8ea3be4..af2937db8 100755
--- a/src/conf_mode/protocols_isis.py
+++ b/src/conf_mode/protocols_isis.py
@@ -1,284 +1,274 @@
#!/usr/bin/env python3
#
# Copyright (C) 2020-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from sys import exit
from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configdict import node_changed
from vyos.configverify import verify_common_route_maps
from vyos.configverify import verify_interface_exists
from vyos.ifconfig import Interface
from vyos.util import dict_search
from vyos.util import get_interface_config
from vyos.template import render_to_string
from vyos.xml import defaults
from vyos import ConfigError
from vyos import frr
from vyos import airbag
airbag.enable()
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
vrf = None
if len(argv) > 1:
vrf = argv[1]
base_path = ['protocols', 'isis']
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'isis'] or base_path
isis = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True)
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
# instead of the VRF instance.
if vrf: isis['vrf'] = vrf
# FRR has VRF support for different routing daemons. As interfaces belong
# to VRFs - or the global VRF, we need to check for changed interfaces so
# that they will be properly rendered for the FRR config. Also this eases
# removal of interfaces from the running configuration.
interfaces_removed = node_changed(conf, base + ['interface'])
if interfaces_removed:
isis['interface_removed'] = list(interfaces_removed)
# Bail out early if configuration tree does not exist
if not conf.exists(base):
isis.update({'deleted' : ''})
return isis
# We have gathered the dict representation of the CLI, but there are default
# options which we need to update into the dictionary retrived.
# XXX: Note that we can not call defaults(base), as defaults does not work
# on an instance of a tag node. As we use the exact same CLI definition for
# both the non-vrf and vrf version this is absolutely safe!
default_values = defaults(base_path)
# merge in default values
isis = dict_merge(default_values, isis)
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify().
#
# XXX: one MUST always call this without the key_mangling() option! See
# vyos.configverify.verify_common_route_maps() for more information.
tmp = conf.get_config_dict(['policy'])
# Merge policy dict into "regular" config dict
isis = dict_merge(tmp, isis)
return isis
def verify(isis):
# bail out early - looks like removal from running config
if not isis or 'deleted' in isis:
return None
if 'net' not in isis:
raise ConfigError('Network entity is mandatory!')
# last byte in IS-IS area address must be 0
tmp = isis['net'].split('.')
if int(tmp[-1]) != 0:
raise ConfigError('Last byte of IS-IS network entity title must always be 0!')
verify_common_route_maps(isis)
# If interface not set
if 'interface' not in isis:
raise ConfigError('Interface used for routing updates is mandatory!')
for interface in isis['interface']:
verify_interface_exists(interface)
# Interface MTU must be >= configured lsp-mtu
mtu = Interface(interface).get_mtu()
area_mtu = isis['lsp_mtu']
# Recommended maximum PDU size = interface MTU - 3 bytes
recom_area_mtu = mtu - 3
if mtu < int(area_mtu) or int(area_mtu) > recom_area_mtu:
raise ConfigError(f'Interface {interface} has MTU {mtu}, ' \
f'current area MTU is {area_mtu}! \n' \
f'Recommended area lsp-mtu {recom_area_mtu} or less ' \
'(calculated on MTU size).')
if 'vrf' in isis:
# If interface specific options are set, we must ensure that the
# interface is bound to our requesting VRF. Due to the VyOS
# priorities the interface is bound to the VRF after creation of
# the VRF itself, and before any routing protocol is configured.
vrf = isis['vrf']
tmp = get_interface_config(interface)
if 'master' not in tmp or tmp['master'] != vrf:
raise ConfigError(f'Interface {interface} is not a member of VRF {vrf}!')
# If md5 and plaintext-password set at the same time
for password in ['area_password', 'domain_password']:
if password in isis:
if {'md5', 'plaintext_password'} <= set(isis[password]):
tmp = password.replace('_', '-')
raise ConfigError(f'Can use either md5 or plaintext-password for {tmp}!')
# If one param from delay set, but not set others
if 'spf_delay_ietf' in isis:
required_timers = ['holddown', 'init_delay', 'long_delay', 'short_delay', 'time_to_learn']
exist_timers = []
for elm_timer in required_timers:
if elm_timer in isis['spf_delay_ietf']:
exist_timers.append(elm_timer)
exist_timers = set(required_timers).difference(set(exist_timers))
if len(exist_timers) > 0:
raise ConfigError('All types of spf-delay must be configured. Missing: ' + ', '.join(exist_timers).replace('_', '-'))
# If Redistribute set, but level don't set
if 'redistribute' in isis:
proc_level = isis.get('level','').replace('-','_')
for afi in ['ipv4', 'ipv6']:
if afi not in isis['redistribute']:
continue
for proto, proto_config in isis['redistribute'][afi].items():
if 'level_1' not in proto_config and 'level_2' not in proto_config:
raise ConfigError(f'Redistribute level-1 or level-2 should be specified in ' \
f'"protocols isis {process} redistribute {afi} {proto}"!')
for redistr_level, redistr_config in proto_config.items():
if proc_level and proc_level != 'level_1_2' and proc_level != redistr_level:
raise ConfigError(f'"protocols isis {process} redistribute {afi} {proto} {redistr_level}" ' \
f'can not be used with \"protocols isis {process} level {proc_level}\"')
# Segment routing checks
if dict_search('segment_routing.global_block', isis):
g_high_label_value = dict_search('segment_routing.global_block.high_label_value', isis)
g_low_label_value = dict_search('segment_routing.global_block.low_label_value', isis)
# If segment routing global block high or low value is blank, throw error
if not (g_low_label_value or g_high_label_value):
raise ConfigError('Segment routing global-block requires both low and high value!')
# If segment routing global block low value is higher than the high value, throw error
if int(g_low_label_value) > int(g_high_label_value):
raise ConfigError('Segment routing global-block low value must be lower than high value')
if dict_search('segment_routing.local_block', isis):
if dict_search('segment_routing.global_block', isis) == None:
raise ConfigError('Segment routing local-block requires global-block to be configured!')
l_high_label_value = dict_search('segment_routing.local_block.high_label_value', isis)
l_low_label_value = dict_search('segment_routing.local_block.low_label_value', isis)
# If segment routing local-block high or low value is blank, throw error
if not (l_low_label_value or l_high_label_value):
raise ConfigError('Segment routing local-block requires both high and low value!')
# If segment routing local-block low value is higher than the high value, throw error
if int(l_low_label_value) > int(l_high_label_value):
raise ConfigError('Segment routing local-block low value must be lower than high value')
# local-block most live outside global block
global_range = range(int(g_low_label_value), int(g_high_label_value) +1)
local_range = range(int(l_low_label_value), int(l_high_label_value) +1)
# Check for overlapping ranges
if list(set(global_range) & set(local_range)):
raise ConfigError(f'Segment-Routing Global Block ({g_low_label_value}/{g_high_label_value}) '\
f'conflicts with Local Block ({l_low_label_value}/{l_high_label_value})!')
-
+
# Check for a blank or invalid value per prefix
if dict_search('segment_routing.prefix', isis):
for prefix, prefix_config in isis['segment_routing']['prefix'].items():
if 'absolute' in prefix_config:
if prefix_config['absolute'].get('value') is None:
raise ConfigError(f'Segment routing prefix {prefix} absolute value cannot be blank.')
elif 'index' in prefix_config:
if prefix_config['index'].get('value') is None:
raise ConfigError(f'Segment routing prefix {prefix} index value cannot be blank.')
# Check for explicit-null and no-php-flag configured at the same time per prefix
if dict_search('segment_routing.prefix', isis):
for prefix, prefix_config in isis['segment_routing']['prefix'].items():
if 'absolute' in prefix_config:
- if ("explicit_null" in prefix_config['absolute']) and ("no_php_flag" in prefix_config['absolute']):
+ if ("explicit_null" in prefix_config['absolute']) and ("no_php_flag" in prefix_config['absolute']):
raise ConfigError(f'Segment routing prefix {prefix} cannot have both explicit-null '\
f'and no-php-flag configured at the same time.')
elif 'index' in prefix_config:
if ("explicit_null" in prefix_config['index']) and ("no_php_flag" in prefix_config['index']):
raise ConfigError(f'Segment routing prefix {prefix} cannot have both explicit-null '\
f'and no-php-flag configured at the same time.')
return None
def generate(isis):
if not isis or 'deleted' in isis:
return None
- isis['protocol'] = 'isis' # required for frr/vrf.route-map.frr.j2
- isis['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', isis)
isis['frr_isisd_config'] = render_to_string('frr/isisd.frr.j2', isis)
return None
def apply(isis):
isis_daemon = 'isisd'
- zebra_daemon = 'zebra'
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
- # The route-map used for the FIB (zebra) is part of the zebra daemon
- frr_cfg.load_configuration(zebra_daemon)
- frr_cfg.modify_section('(\s+)?ip protocol isis route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)')
- if 'frr_zebra_config' in isis:
- frr_cfg.add_before(frr.default_add_before, isis['frr_zebra_config'])
- frr_cfg.commit_configuration(zebra_daemon)
-
# Generate empty helper string which can be ammended to FRR commands, it
# will be either empty (default VRF) or contain the "vrf <name" statement
vrf = ''
if 'vrf' in isis:
vrf = ' vrf ' + isis['vrf']
frr_cfg.load_configuration(isis_daemon)
frr_cfg.modify_section(f'^router isis VyOS{vrf}', stop_pattern='^exit', remove_stop_mark=True)
for key in ['interface', 'interface_removed']:
if key not in isis:
continue
for interface in isis[key]:
frr_cfg.modify_section(f'^interface {interface}{vrf}', stop_pattern='^exit', remove_stop_mark=True)
if 'frr_isisd_config' in isis:
frr_cfg.add_before(frr.default_add_before, isis['frr_isisd_config'])
frr_cfg.commit_configuration(isis_daemon)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index eb64afa0c..fbb876123 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -1,307 +1,298 @@
#!/usr/bin/env python3
#
# Copyright (C) 2021 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from sys import exit
from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configdict import node_changed
from vyos.configverify import verify_common_route_maps
from vyos.configverify import verify_route_map
from vyos.configverify import verify_interface_exists
from vyos.configverify import verify_access_list
from vyos.template import render_to_string
from vyos.util import dict_search
from vyos.util import get_interface_config
from vyos.xml import defaults
from vyos import ConfigError
from vyos import frr
from vyos import airbag
airbag.enable()
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
vrf = None
if len(argv) > 1:
vrf = argv[1]
base_path = ['protocols', 'ospf']
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'ospf'] or base_path
ospf = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True)
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
# instead of the VRF instance.
if vrf: ospf['vrf'] = vrf
# FRR has VRF support for different routing daemons. As interfaces belong
# to VRFs - or the global VRF, we need to check for changed interfaces so
# that they will be properly rendered for the FRR config. Also this eases
# removal of interfaces from the running configuration.
interfaces_removed = node_changed(conf, base + ['interface'])
if interfaces_removed:
ospf['interface_removed'] = list(interfaces_removed)
# Bail out early if configuration tree does not exist
if not conf.exists(base):
ospf.update({'deleted' : ''})
return ospf
# We have gathered the dict representation of the CLI, but there are default
# options which we need to update into the dictionary retrived.
# XXX: Note that we can not call defaults(base), as defaults does not work
# on an instance of a tag node. As we use the exact same CLI definition for
# both the non-vrf and vrf version this is absolutely safe!
default_values = defaults(base_path)
# We have to cleanup the default dict, as default values could enable features
# which are not explicitly enabled on the CLI. Example: default-information
# originate comes with a default metric-type of 2, which will enable the
# entire default-information originate tree, even when not set via CLI so we
# need to check this first and probably drop that key.
if dict_search('default_information.originate', ospf) is None:
del default_values['default_information']
if dict_search('area.area_type.nssa', ospf) is None:
del default_values['area']['area_type']['nssa']
if 'mpls_te' not in ospf:
del default_values['mpls_te']
for protocol in ['babel', 'bgp', 'connected', 'isis', 'kernel', 'rip', 'static', 'table']:
# table is a tagNode thus we need to clean out all occurances for the
# default values and load them in later individually
if protocol == 'table':
del default_values['redistribute']['table']
continue
if dict_search(f'redistribute.{protocol}', ospf) is None:
del default_values['redistribute'][protocol]
# XXX: T2665: we currently have no nice way for defaults under tag nodes,
# clean them out and add them manually :(
del default_values['neighbor']
del default_values['area']['virtual_link']
del default_values['interface']
# merge in remaining default values
ospf = dict_merge(default_values, ospf)
if 'neighbor' in ospf:
default_values = defaults(base + ['neighbor'])
for neighbor in ospf['neighbor']:
ospf['neighbor'][neighbor] = dict_merge(default_values, ospf['neighbor'][neighbor])
if 'area' in ospf:
default_values = defaults(base + ['area', 'virtual-link'])
for area, area_config in ospf['area'].items():
if 'virtual_link' in area_config:
for virtual_link in area_config['virtual_link']:
ospf['area'][area]['virtual_link'][virtual_link] = dict_merge(
default_values, ospf['area'][area]['virtual_link'][virtual_link])
if 'interface' in ospf:
for interface in ospf['interface']:
# We need to reload the defaults on every pass b/c of
# hello-multiplier dependency on dead-interval
default_values = defaults(base + ['interface'])
# If hello-multiplier is set, we need to remove the default from
# dead-interval.
if 'hello_multiplier' in ospf['interface'][interface]:
del default_values['dead_interval']
ospf['interface'][interface] = dict_merge(default_values,
ospf['interface'][interface])
if 'redistribute' in ospf and 'table' in ospf['redistribute']:
default_values = defaults(base + ['redistribute', 'table'])
for table in ospf['redistribute']['table']:
ospf['redistribute']['table'][table] = dict_merge(default_values,
ospf['redistribute']['table'][table])
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify().
#
# XXX: one MUST always call this without the key_mangling() option! See
# vyos.configverify.verify_common_route_maps() for more information.
tmp = conf.get_config_dict(['policy'])
# Merge policy dict into "regular" config dict
ospf = dict_merge(tmp, ospf)
return ospf
def verify(ospf):
if not ospf:
return None
verify_common_route_maps(ospf)
# As we can have a default-information route-map, we need to validate it!
route_map_name = dict_search('default_information.originate.route_map', ospf)
if route_map_name: verify_route_map(route_map_name, ospf)
# Validate if configured Access-list exists
if 'area' in ospf:
for area, area_config in ospf['area'].items():
if 'import_list' in area_config:
acl_import = area_config['import_list']
if acl_import: verify_access_list(acl_import, ospf)
if 'export_list' in area_config:
acl_export = area_config['export_list']
if acl_export: verify_access_list(acl_export, ospf)
if 'interface' in ospf:
for interface, interface_config in ospf['interface'].items():
verify_interface_exists(interface)
# One can not use dead-interval and hello-multiplier at the same
# time. FRR will only activate the last option set via CLI.
if {'hello_multiplier', 'dead_interval'} <= set(interface_config):
raise ConfigError(f'Can not use hello-multiplier and dead-interval ' \
f'concurrently for {interface}!')
# One can not use the "network <prefix> area <id>" command and an
# per interface area assignment at the same time. FRR will error
# out using: "Please remove all network commands first."
if 'area' in ospf and 'area' in interface_config:
for area, area_config in ospf['area'].items():
if 'network' in area_config:
raise ConfigError('Can not use OSPF interface area and area ' \
'network configuration at the same time!')
# If interface specific options are set, we must ensure that the
# interface is bound to our requesting VRF. Due to the VyOS
# priorities the interface is bound to the VRF after creation of
# the VRF itself, and before any routing protocol is configured.
if 'vrf' in ospf:
vrf = ospf['vrf']
tmp = get_interface_config(interface)
if 'master' not in tmp or tmp['master'] != vrf:
raise ConfigError(f'Interface {interface} is not a member of VRF {vrf}!')
# Segment routing checks
if dict_search('segment_routing.global_block', ospf):
g_high_label_value = dict_search('segment_routing.global_block.high_label_value', ospf)
g_low_label_value = dict_search('segment_routing.global_block.low_label_value', ospf)
# If segment routing global block high or low value is blank, throw error
if not (g_low_label_value or g_high_label_value):
raise ConfigError('Segment routing global-block requires both low and high value!')
# If segment routing global block low value is higher than the high value, throw error
if int(g_low_label_value) > int(g_high_label_value):
raise ConfigError('Segment routing global-block low value must be lower than high value')
if dict_search('segment_routing.local_block', ospf):
if dict_search('segment_routing.global_block', ospf) == None:
raise ConfigError('Segment routing local-block requires global-block to be configured!')
l_high_label_value = dict_search('segment_routing.local_block.high_label_value', ospf)
l_low_label_value = dict_search('segment_routing.local_block.low_label_value', ospf)
# If segment routing local-block high or low value is blank, throw error
if not (l_low_label_value or l_high_label_value):
raise ConfigError('Segment routing local-block requires both high and low value!')
# If segment routing local-block low value is higher than the high value, throw error
if int(l_low_label_value) > int(l_high_label_value):
raise ConfigError('Segment routing local-block low value must be lower than high value')
# local-block most live outside global block
global_range = range(int(g_low_label_value), int(g_high_label_value) +1)
local_range = range(int(l_low_label_value), int(l_high_label_value) +1)
# Check for overlapping ranges
if list(set(global_range) & set(local_range)):
raise ConfigError(f'Segment-Routing Global Block ({g_low_label_value}/{g_high_label_value}) '\
f'conflicts with Local Block ({l_low_label_value}/{l_high_label_value})!')
# Check for a blank or invalid value per prefix
if dict_search('segment_routing.prefix', ospf):
for prefix, prefix_config in ospf['segment_routing']['prefix'].items():
if 'index' in prefix_config:
if prefix_config['index'].get('value') is None:
raise ConfigError(f'Segment routing prefix {prefix} index value cannot be blank.')
# Check for explicit-null and no-php-flag configured at the same time per prefix
if dict_search('segment_routing.prefix', ospf):
for prefix, prefix_config in ospf['segment_routing']['prefix'].items():
if 'index' in prefix_config:
if ("explicit_null" in prefix_config['index']) and ("no_php_flag" in prefix_config['index']):
raise ConfigError(f'Segment routing prefix {prefix} cannot have both explicit-null '\
f'and no-php-flag configured at the same time.')
return None
def generate(ospf):
if not ospf or 'deleted' in ospf:
return None
- ospf['protocol'] = 'ospf' # required for frr/vrf.route-map.frr.j2
- ospf['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.j2', ospf)
ospf['frr_ospfd_config'] = render_to_string('frr/ospfd.frr.j2', ospf)
return None
def apply(ospf):
ospf_daemon = 'ospfd'
- zebra_daemon = 'zebra'
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
- # The route-map used for the FIB (zebra) is part of the zebra daemon
- frr_cfg.load_configuration(zebra_daemon)
- frr_cfg.modify_section('(\s+)?ip protocol ospf route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)')
- if 'frr_zebra_config' in ospf:
- frr_cfg.add_before(frr.default_add_before, ospf['frr_zebra_config'])
- frr_cfg.commit_configuration(zebra_daemon)
-
# Generate empty helper string which can be ammended to FRR commands, it
# will be either empty (default VRF) or contain the "vrf <name" statement
vrf = ''
if 'vrf' in ospf:
vrf = ' vrf ' + ospf['vrf']
frr_cfg.load_configuration(ospf_daemon)
frr_cfg.modify_section(f'^router ospf{vrf}', stop_pattern='^exit', remove_stop_mark=True)
for key in ['interface', 'interface_removed']:
if key not in ospf:
continue
for interface in ospf[key]:
frr_cfg.modify_section(f'^interface {interface}{vrf}', stop_pattern='^exit', remove_stop_mark=True)
if 'frr_ospfd_config' in ospf:
frr_cfg.add_before(frr.default_add_before, ospf['frr_ospfd_config'])
+
frr_cfg.commit_configuration(ospf_daemon)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py
index 1e2c02d03..ee1fdd399 100755
--- a/src/conf_mode/protocols_ospfv3.py
+++ b/src/conf_mode/protocols_ospfv3.py
@@ -1,198 +1,188 @@
#!/usr/bin/env python3
#
# Copyright (C) 2021-2023 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from sys import exit
from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configdict import node_changed
from vyos.configverify import verify_common_route_maps
from vyos.configverify import verify_route_map
from vyos.configverify import verify_interface_exists
from vyos.template import render_to_string
from vyos.ifconfig import Interface
from vyos.util import dict_search
from vyos.util import get_interface_config
from vyos.xml import defaults
from vyos import ConfigError
from vyos import frr
from vyos import airbag
airbag.enable()
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
vrf = None
if len(argv) > 1:
vrf = argv[1]
base_path = ['protocols', 'ospfv3']
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'ospfv3'] or base_path
ospfv3 = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
# Assign the name of our VRF context. This MUST be done before the return
# statement below, else on deletion we will delete the default instance
# instead of the VRF instance.
if vrf: ospfv3['vrf'] = vrf
# FRR has VRF support for different routing daemons. As interfaces belong
# to VRFs - or the global VRF, we need to check for changed interfaces so
# that they will be properly rendered for the FRR config. Also this eases
# removal of interfaces from the running configuration.
interfaces_removed = node_changed(conf, base + ['interface'])
if interfaces_removed:
ospfv3['interface_removed'] = list(interfaces_removed)
# Bail out early if configuration tree does not exist
if not conf.exists(base):
ospfv3.update({'deleted' : ''})
return ospfv3
# We have gathered the dict representation of the CLI, but there are default
# options which we need to update into the dictionary retrived.
# XXX: Note that we can not call defaults(base), as defaults does not work
# on an instance of a tag node. As we use the exact same CLI definition for
# both the non-vrf and vrf version this is absolutely safe!
default_values = defaults(base_path)
# We have to cleanup the default dict, as default values could enable features
# which are not explicitly enabled on the CLI. Example: default-information
# originate comes with a default metric-type of 2, which will enable the
# entire default-information originate tree, even when not set via CLI so we
# need to check this first and probably drop that key.
if dict_search('default_information.originate', ospfv3) is None:
del default_values['default_information']
# XXX: T2665: we currently have no nice way for defaults under tag nodes,
# clean them out and add them manually :(
del default_values['interface']
# merge in remaining default values
ospfv3 = dict_merge(default_values, ospfv3)
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify().
#
# XXX: one MUST always call this without the key_mangling() option! See
# vyos.configverify.verify_common_route_maps() for more information.
tmp = conf.get_config_dict(['policy'])
# Merge policy dict into "regular" config dict
ospfv3 = dict_merge(tmp, ospfv3)
return ospfv3
def verify(ospfv3):
if not ospfv3:
return None
verify_common_route_maps(ospfv3)
# As we can have a default-information route-map, we need to validate it!
route_map_name = dict_search('default_information.originate.route_map', ospfv3)
if route_map_name: verify_route_map(route_map_name, ospfv3)
if 'area' in ospfv3:
for area, area_config in ospfv3['area'].items():
if 'area_type' in area_config:
if len(area_config['area_type']) > 1:
raise ConfigError(f'Can only configure one area-type for OSPFv3 area "{area}"!')
if 'range' in area_config:
for range, range_config in area_config['range'].items():
if {'not_advertise', 'advertise'} <= range_config.keys():
raise ConfigError(f'"not-advertise" and "advertise" for "range {range}" cannot be both configured at the same time!')
if 'interface' in ospfv3:
for interface, interface_config in ospfv3['interface'].items():
verify_interface_exists(interface)
if 'ifmtu' in interface_config:
mtu = Interface(interface).get_mtu()
if int(interface_config['ifmtu']) > int(mtu):
raise ConfigError(f'OSPFv3 ifmtu can not exceed physical MTU of "{mtu}"')
# If interface specific options are set, we must ensure that the
# interface is bound to our requesting VRF. Due to the VyOS
# priorities the interface is bound to the VRF after creation of
# the VRF itself, and before any routing protocol is configured.
if 'vrf' in ospfv3:
vrf = ospfv3['vrf']
tmp = get_interface_config(interface)
if 'master' not in tmp or tmp['master'] != vrf:
raise ConfigError(f'Interface {interface} is not a member of VRF {vrf}!')
return None
def generate(ospfv3):
if not ospfv3 or 'deleted' in ospfv3:
return None
- ospfv3['protocol'] = 'ospf6' # required for frr/vrf.route-map.v6.frr.j2
- ospfv3['frr_zebra_config'] = render_to_string('frr/vrf.route-map.v6.frr.j2', ospfv3)
ospfv3['new_frr_config'] = render_to_string('frr/ospf6d.frr.j2', ospfv3)
return None
def apply(ospfv3):
ospf6_daemon = 'ospf6d'
- zebra_daemon = 'zebra'
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
- # The route-map used for the FIB (zebra) is part of the zebra daemon
- frr_cfg.load_configuration(zebra_daemon)
- frr_cfg.modify_section('(\s+)?ipv6 protocol ospf6 route-map [-a-zA-Z0-9.]+', stop_pattern='(\s|!)')
- if 'frr_zebra_config' in ospfv3:
- frr_cfg.add_before(frr.default_add_before, ospfv3['frr_zebra_config'])
- frr_cfg.commit_configuration(zebra_daemon)
-
# Generate empty helper string which can be ammended to FRR commands, it
# will be either empty (default VRF) or contain the "vrf <name" statement
vrf = ''
if 'vrf' in ospfv3:
vrf = ' vrf ' + ospfv3['vrf']
frr_cfg.load_configuration(ospf6_daemon)
frr_cfg.modify_section(f'^router ospf6{vrf}', stop_pattern='^exit', remove_stop_mark=True)
for key in ['interface', 'interface_removed']:
if key not in ospfv3:
continue
for interface in ospfv3[key]:
frr_cfg.modify_section(f'^interface {interface}{vrf}', stop_pattern='^exit', remove_stop_mark=True)
if 'new_frr_config' in ospfv3:
frr_cfg.add_before(frr.default_add_before, ospfv3['new_frr_config'])
frr_cfg.commit_configuration(ospf6_daemon)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)
diff --git a/src/conf_mode/protocols_static.py b/src/conf_mode/protocols_static.py
index 3eabf24bc..5122f60b2 100755
--- a/src/conf_mode/protocols_static.py
+++ b/src/conf_mode/protocols_static.py
@@ -1,133 +1,134 @@
#!/usr/bin/env python3
#
# Copyright (C) 2021-2023 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from sys import exit
from sys import argv
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configdict import get_dhcp_interfaces
from vyos.configdict import get_pppoe_interfaces
from vyos.configverify import verify_common_route_maps
from vyos.configverify import verify_vrf
from vyos.template import render
from vyos.template import render_to_string
from vyos import ConfigError
from vyos import frr
from vyos import airbag
airbag.enable()
config_file = '/etc/iproute2/rt_tables.d/vyos-static.conf'
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
vrf = None
if len(argv) > 1:
vrf = argv[1]
base_path = ['protocols', 'static']
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'static'] or base_path
static = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
# Assign the name of our VRF context
if vrf: static['vrf'] = vrf
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify().
#
# XXX: one MUST always call this without the key_mangling() option! See
# vyos.configverify.verify_common_route_maps() for more information.
tmp = conf.get_config_dict(['policy'])
# Merge policy dict into "regular" config dict
static = dict_merge(tmp, static)
# T3680 - get a list of all interfaces currently configured to use DHCP
tmp = get_dhcp_interfaces(conf, vrf)
if tmp: static.update({'dhcp' : tmp})
tmp = get_pppoe_interfaces(conf, vrf)
if tmp: static.update({'pppoe' : tmp})
return static
def verify(static):
verify_common_route_maps(static)
for route in ['route', 'route6']:
# if there is no route(6) key in the dictionary we can immediately
# bail out early
if route not in static:
continue
# When leaking routes to other VRFs we must ensure that the destination
# VRF exists
for prefix, prefix_options in static[route].items():
# both the interface and next-hop CLI node can have a VRF subnode,
# thus we check this using a for loop
for type in ['interface', 'next_hop']:
if type in prefix_options:
for interface, interface_config in prefix_options[type].items():
verify_vrf(interface_config)
if {'blackhole', 'reject'} <= set(prefix_options):
raise ConfigError(f'Can not use both blackhole and reject for '\
'prefix "{prefix}"!')
return None
def generate(static):
if not static:
return None
# Put routing table names in /etc/iproute2/rt_tables
render(config_file, 'iproute2/static.conf.j2', static)
static['new_frr_config'] = render_to_string('frr/staticd.frr.j2', static)
return None
def apply(static):
static_daemon = 'staticd'
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
+ frr_cfg.load_configuration(static_daemon)
if 'vrf' in static:
vrf = static['vrf']
frr_cfg.modify_section(f'^vrf {vrf}', stop_pattern='^exit', remove_stop_mark=True)
else:
frr_cfg.modify_section(r'^ip route .*')
frr_cfg.modify_section(r'^ipv6 route .*')
if 'new_frr_config' in static:
frr_cfg.add_before(frr.default_add_before, static['new_frr_config'])
frr_cfg.commit_configuration(static_daemon)
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 11, 10:04 AM (43 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3224894
Default Alt Text
(246 KB)

Event Timeline