diff options
41 files changed, 1101 insertions, 202 deletions
diff --git a/data/templates/frr/policy.frr.j2 b/data/templates/frr/policy.frr.j2 index 9b5e80aed..ed5876ae9 100644 --- a/data/templates/frr/policy.frr.j2 +++ b/data/templates/frr/policy.frr.j2 @@ -245,6 +245,10 @@ route-map {{ route_map }} {{ rule_config.action }} {{ rule }} {% if rule_config.match.peer is vyos_defined %} match peer {{ rule_config.match.peer }} {% endif %} +{% if rule_config.match.protocol is vyos_defined %} +{% set source_protocol = 'ospf6' if rule_config.match.protocol == 'ospfv3' else rule_config.match.protocol %} + match source-protocol {{ source_protocol }} +{% endif %} {% if rule_config.match.rpki is vyos_defined %} match rpki {{ rule_config.match.rpki }} {% endif %} diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2 index 1c64ac58b..8afd4a68a 100644 --- a/data/templates/frr/static_routes_macro.j2 +++ b/data/templates/frr/static_routes_macro.j2 @@ -18,7 +18,12 @@ {% endif %} {% if prefix_config.next_hop is vyos_defined and prefix_config.next_hop is not none %} {% for next_hop, next_hop_config in prefix_config.next_hop.items() if next_hop_config.disable is not defined %} -{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ next_hop_config.interface if next_hop_config.interface is vyos_defined }} {{ next_hop_config.distance if next_hop_config.distance is vyos_defined }} {{ 'nexthop-vrf ' ~ next_hop_config.vrf if next_hop_config.vrf is vyos_defined }} {{ 'bfd profile ' ~ next_hop_config.bfd.profile if next_hop_config.bfd.profile is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }} +{% if next_hop_config.bfd.multi_hop.source is vyos_defined %} +{% for source, source_config in next_hop_config.bfd.multi_hop.source.items() %} +{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} bfd multi-hop source {{ source }} profile {{ source_config.profile }} +{% endfor %} +{% endif %} {% endfor %} {% endif %} {% endmacro %} diff --git a/interface-definitions/include/static/static-route-bfd.xml.i b/interface-definitions/include/static/static-route-bfd.xml.i new file mode 100644 index 000000000..a05a08d12 --- /dev/null +++ b/interface-definitions/include/static/static-route-bfd.xml.i @@ -0,0 +1,37 @@ +<!-- include start from static/static-route-bfd.xml.i --> +<node name="bfd"> + <properties> + <help>BFD monitoring</help> + </properties> + <children> + #include <include/bfd/profile.xml.i> + <node name="multi-hop"> + <properties> + <help>Use BFD multi hop session</help> + </properties> + <children> + <tagNode name="source"> + <properties> + <help>Use source for BFD session</help> + <valueHelp> + <format>ipv4</format> + <description>IPv4 source address</description> + </valueHelp> + <valueHelp> + <format>ipv6</format> + <description>IPv6 source address</description> + </valueHelp> + <constraint> + <validator name="ipv4-address"/> + <validator name="ipv6-address"/> + </constraint> + </properties> + <children> + #include <include/bfd/profile.xml.i> + </children> + </tagNode> + </children> + </node> + </children> +</node> +<!-- include end -->
\ No newline at end of file diff --git a/interface-definitions/include/static/static-route.xml.i b/interface-definitions/include/static/static-route.xml.i index 268cfa005..29921a731 100644 --- a/interface-definitions/include/static/static-route.xml.i +++ b/interface-definitions/include/static/static-route.xml.i @@ -51,6 +51,7 @@ #include <include/static/static-route-distance.xml.i> #include <include/static/static-route-interface.xml.i> #include <include/static/static-route-vrf.xml.i> + #include <include/static/static-route-bfd.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/include/static/static-route6.xml.i b/interface-definitions/include/static/static-route6.xml.i index 1f8d54108..a83cc230b 100644 --- a/interface-definitions/include/static/static-route6.xml.i +++ b/interface-definitions/include/static/static-route6.xml.i @@ -50,6 +50,7 @@ #include <include/static/static-route-distance.xml.i> #include <include/static/static-route-interface.xml.i> #include <include/static/static-route-vrf.xml.i> + #include <include/static/static-route-bfd.xml.i> </children> </tagNode> </children> diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index 7d5fe79ef..02828c4f6 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -971,6 +971,65 @@ </constraint> </properties> </leafNode> + <leafNode name="protocol"> + <properties> + <help>Match protocol via which the route was learnt</help> + <completionHelp> + <list>babel bgp connected isis kernel ospf ospfv3 rip ripng static table vnc</list> + </completionHelp> + <valueHelp> + <format>babel</format> + <description>Babel routing protocol (Babel)</description> + </valueHelp> + <valueHelp> + <format>bgp</format> + <description>Border Gateway Protocol (BGP)</description> + </valueHelp> + <valueHelp> + <format>connected</format> + <description>Connected routes (directly attached subnet or host)</description> + </valueHelp> + <valueHelp> + <format>isis</format> + <description>Intermediate System to Intermediate System (IS-IS)</description> + </valueHelp> + <valueHelp> + <format>kernel</format> + <description>Kernel routes</description> + </valueHelp> + <valueHelp> + <format>ospf</format> + <description>Open Shortest Path First (OSPFv2)</description> + </valueHelp> + <valueHelp> + <format>ospfv3</format> + <description>Open Shortest Path First (IPv6) (OSPFv3)</description> + </valueHelp> + <valueHelp> + <format>rip</format> + <description>Routing Information Protocol (RIP)</description> + </valueHelp> + <valueHelp> + <format>ripng</format> + <description>Routing Information Protocol next-generation (IPv6) (RIPng)</description> + </valueHelp> + <valueHelp> + <format>static</format> + <description>Statically configured routes</description> + </valueHelp> + <valueHelp> + <format>table</format> + <description>Non-main Kernel Routing Table</description> + </valueHelp> + <valueHelp> + <format>vnc</format> + <description>Virtual Network Control (VNC)</description> + </valueHelp> + <constraint> + <regex>(babel|bgp|connected|isis|kernel|ospf|ospfv3|rip|ripng|static|table|vnc)</regex> + </constraint> + </properties> + </leafNode> <leafNode name="rpki"> <properties> <help>Match RPKI validation result</help> diff --git a/op-mode-definitions/counters.xml.in b/op-mode-definitions/counters.xml.in index 4bf08d201..f563cb9a0 100644 --- a/op-mode-definitions/counters.xml.in +++ b/op-mode-definitions/counters.xml.in @@ -19,7 +19,7 @@ <properties> <help>Clear all bonding interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -35,7 +35,7 @@ <properties> <help>Clear interface counters for a given bonding interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -48,7 +48,7 @@ <properties> <help>Clear all bridge interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -64,7 +64,7 @@ <properties> <help>Clear interface counters for a given bridge interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -77,7 +77,7 @@ <properties> <help>Clear all dummy interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -93,7 +93,7 @@ <properties> <help>Clear interface counters for a given dummy interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -106,7 +106,7 @@ <properties> <help>Clear all ethernet interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -122,7 +122,7 @@ <properties> <help>Clear interface counters for a given ethernet interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -135,7 +135,7 @@ <properties> <help>Clear all GENEVE interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -151,7 +151,7 @@ <properties> <help>Clear interface counters for a given GENEVE interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -164,7 +164,7 @@ <properties> <help>Clear all Input interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -180,7 +180,7 @@ <properties> <help>Clear interface counters for a given Input interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -193,7 +193,7 @@ <properties> <help>Clear all L2TPv3 interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -209,7 +209,7 @@ <properties> <help>Clear interface counters for a given L2TPv3 interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -222,7 +222,7 @@ <properties> <help>Clear all loopback interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -238,7 +238,7 @@ <properties> <help>Clear interface counters for a given loopback interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -251,7 +251,7 @@ <properties> <help>Clear all MACsec interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -267,7 +267,7 @@ <properties> <help>Clear interface counters for a given MACsec interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -280,7 +280,7 @@ <properties> <help>Clear all OpenVPN interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -296,7 +296,7 @@ <properties> <help>Clear interface counters for a given OpenVPN interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -309,7 +309,7 @@ <properties> <help>Clear all PPPoE interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -325,7 +325,7 @@ <properties> <help>Clear interface counters for a given PPPoE interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -338,7 +338,7 @@ <properties> <help>Clear all Pseudo-Ethernet interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -354,7 +354,7 @@ <properties> <help>Clear interface counters for a given Pseudo-Ethernet interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -367,7 +367,7 @@ <properties> <help>Clear all SSTP interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -383,7 +383,7 @@ <properties> <help>Clear interface counters for a given SSTP interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -396,7 +396,7 @@ <properties> <help>Clear all tunnel interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -412,7 +412,7 @@ <properties> <help>Clear interface counters for a given tunnel interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -425,7 +425,7 @@ <properties> <help>Clear all virtual-ethernet interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -441,7 +441,7 @@ <properties> <help>Clear interface counters for a given virtual-ethernet interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -454,7 +454,7 @@ <properties> <help>Clear all VTI interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -470,7 +470,7 @@ <properties> <help>Clear interface counters for a given VTI interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -483,7 +483,7 @@ <properties> <help>Clear all VXLAN interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -499,7 +499,7 @@ <properties> <help>Clear interface counters for a given VXLAN interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -512,7 +512,7 @@ <properties> <help>Clear all Wireguard interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </node> </children> </node> @@ -528,7 +528,7 @@ <properties> <help>Clear interface counters for a given Wireguard interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -541,7 +541,7 @@ <properties> <help>Clear all wireless interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </leafNode> </children> </node> @@ -557,7 +557,7 @@ <properties> <help>Clear counters for a given wireless interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> @@ -570,7 +570,7 @@ <properties> <help>Clear all WWAN interface counters</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_type "$3"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-type "$3"</command> </leafNode> </children> </node> @@ -586,7 +586,7 @@ <properties> <help>Clear counters for a given WWAN interface</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf_name "$4"</command> + <command>sudo ${vyos_op_scripts_dir}/interfaces.py clear_counters --intf-name "$4"</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/generate-system-login-user.xml.in b/op-mode-definitions/generate-system-login-user.xml.in index d0519b6bd..237a13610 100755 --- a/op-mode-definitions/generate-system-login-user.xml.in +++ b/op-mode-definitions/generate-system-login-user.xml.in @@ -35,19 +35,19 @@ <properties>
<help>Duration of single time interval</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "$9"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "$9"</command>
<children>
<tagNode name="rate-time">
<properties>
<help>The number of digits in the one-time password</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "$9" --rate_time "${11}" </command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "$9" --rate-time "${11}" </command>
<children>
<tagNode name="window-size">
<properties>
<help>The number of digits in the one-time password</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "$9" --rate_time "${11}" --window_size "${13}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "$9" --rate-time "${11}" --window-size "${13}"</command>
</tagNode>
</children>
</tagNode>
@@ -57,19 +57,19 @@ <properties>
<help>The number of digits in the one-time password</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --window_size "${9}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --window-size "${9}"</command>
<children>
<tagNode name="rate-limit">
<properties>
<help>Duration of single time interval</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "${11}" --window_size "${9}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "${11}" --window-size "${9}"</command>
<children>
<tagNode name="rate-time">
<properties>
<help>Duration of single time interval</help>
</properties>
- <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate_limit "${11}" --rate_time "${13}" --window_size "${9}"</command>
+ <command>sudo ${vyos_op_scripts_dir}/generate_system_login_user.py --username "$5" --rate-limit "${11}" --rate-time "${13}" --window-size "${9}"</command>
</tagNode>
</children>
</tagNode>
diff --git a/op-mode-definitions/openvpn.xml.in b/op-mode-definitions/openvpn.xml.in index 94647af02..f205b0026 100644 --- a/op-mode-definitions/openvpn.xml.in +++ b/op-mode-definitions/openvpn.xml.in @@ -37,13 +37,13 @@ <properties> <help>Show OpenVPN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=openvpn</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=openvpn</command> <children> <leafNode name="detail"> <properties> <help>Show detailed OpenVPN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=openvpn</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=openvpn</command> </leafNode> </children> </node> @@ -54,7 +54,7 @@ <script>sudo ${vyos_completion_dir}/list_interfaces --type openvpn</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name=$4</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name=$4</command> <children> <tagNode name="user"> <properties> @@ -95,7 +95,7 @@ <properties> <help>Show summary of specified OpenVPN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4"</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4"</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/reboot.xml.in b/op-mode-definitions/reboot.xml.in index 6414742d9..d5a71f561 100644 --- a/op-mode-definitions/reboot.xml.in +++ b/op-mode-definitions/reboot.xml.in @@ -25,7 +25,7 @@ <list><Minutes></list> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot_in $3 $4</command> + <command>sudo ${vyos_op_scripts_dir}/powerctrl.py --yes --reboot-in $3 $4</command> </tagNode> <tagNode name="at"> <properties> diff --git a/op-mode-definitions/show-acceleration.xml.in b/op-mode-definitions/show-acceleration.xml.in index 6fd3babf5..fccfba5e3 100644 --- a/op-mode-definitions/show-acceleration.xml.in +++ b/op-mode-definitions/show-acceleration.xml.in @@ -21,7 +21,7 @@ <properties> <help>Show QAT information for a given acceleration device</help> <completionHelp> - <script>${vyos_op_scripts_dir}/show_acceleration.py --dev_list</script> + <script>${vyos_op_scripts_dir}/show_acceleration.py --dev-list</script> </completionHelp> </properties> <children> diff --git a/op-mode-definitions/show-bfd.xml.in b/op-mode-definitions/show-bfd.xml.in index 39e42e6ec..87d672e04 100644 --- a/op-mode-definitions/show-bfd.xml.in +++ b/op-mode-definitions/show-bfd.xml.in @@ -49,6 +49,19 @@ </leafNode> </children> </node> + <node name="static"> + <properties> + <help>Show route Routing Table</help> + </properties> + <children> + <leafNode name="routes"> + <properties> + <help>Showing BFD monitored static routes</help> + </properties> + <command>vtysh -c "show bfd static route"</command> + </leafNode> + </children> + </node> </children> </node> </children> diff --git a/op-mode-definitions/show-interfaces-bonding.xml.in b/op-mode-definitions/show-interfaces-bonding.xml.in index c41e7bd5f..aa224e6cf 100644 --- a/op-mode-definitions/show-interfaces-bonding.xml.in +++ b/op-mode-definitions/show-interfaces-bonding.xml.in @@ -11,13 +11,13 @@ <path>interfaces bonding</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=bonding</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=bonding</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified bonding interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=bonding</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=bonding</command> </leafNode> <leafNode name="detail"> <properties> @@ -38,13 +38,13 @@ <path>interfaces bonding ${COMP_WORDS[3]} vif</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=bonding</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4.$6" --intf-type=bonding</command> <children> <leafNode name="brief"> <properties> <help>Show summary of specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=bonding</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4.$6" --intf-type=bonding</command> </leafNode> </children> </tagNode> @@ -60,13 +60,13 @@ <properties> <help>Show Bonding interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=bonding</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=bonding</command> <children> <leafNode name="detail"> <properties> <help>Show detailed bonding interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=bonding</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=bonding</command> </leafNode> <leafNode name="slaves"> <properties> diff --git a/op-mode-definitions/show-interfaces-bridge.xml.in b/op-mode-definitions/show-interfaces-bridge.xml.in index 22cd3ee67..dc813682d 100644 --- a/op-mode-definitions/show-interfaces-bridge.xml.in +++ b/op-mode-definitions/show-interfaces-bridge.xml.in @@ -11,13 +11,13 @@ <path>interfaces bridge</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=bridge</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=bridge</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified bridge interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=bridge</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=bridge</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show Bridge interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=bridge</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=bridge</command> <children> <leafNode name="detail"> <properties> <help>Show detailed bridge interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=bridge</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=bridge</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-dummy.xml.in b/op-mode-definitions/show-interfaces-dummy.xml.in index 958d3483d..b8ec7da91 100644 --- a/op-mode-definitions/show-interfaces-dummy.xml.in +++ b/op-mode-definitions/show-interfaces-dummy.xml.in @@ -11,13 +11,13 @@ <path>interfaces dummy</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=dummy</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=dummy</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified dummy interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=dummy</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=dummy</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show Dummy interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=dummy</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=dummy</command> <children> <leafNode name="detail"> <properties> <help>Show detailed dummy interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=dummy</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=dummy</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-ethernet.xml.in b/op-mode-definitions/show-interfaces-ethernet.xml.in index 81759c2b6..7c12d6084 100644 --- a/op-mode-definitions/show-interfaces-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-ethernet.xml.in @@ -11,13 +11,13 @@ <path>interfaces ethernet</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=ethernet</command> </leafNode> <leafNode name="identify"> <properties> @@ -58,13 +58,13 @@ <path>interfaces ethernet ${COMP_WORDS[3]} vif</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4.$6" --intf-type=ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4.$6" --intf-type=ethernet</command> </leafNode> </children> </tagNode> @@ -80,13 +80,13 @@ <properties> <help>Show Ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=ethernet</command> <children> <leafNode name="detail"> <properties> <help>Show detailed ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=ethernet</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-geneve.xml.in b/op-mode-definitions/show-interfaces-geneve.xml.in index 3cf45878d..d3d188031 100644 --- a/op-mode-definitions/show-interfaces-geneve.xml.in +++ b/op-mode-definitions/show-interfaces-geneve.xml.in @@ -11,13 +11,13 @@ <path>interfaces geneve</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=geneve</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=geneve</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified GENEVE interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=geneve</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=geneve</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show GENEVE interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=geneve</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=geneve</command> <children> <leafNode name="detail"> <properties> <help>Show detailed GENEVE interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=geneve</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=geneve</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-input.xml.in b/op-mode-definitions/show-interfaces-input.xml.in index 5d93dcee6..e5d420056 100644 --- a/op-mode-definitions/show-interfaces-input.xml.in +++ b/op-mode-definitions/show-interfaces-input.xml.in @@ -11,13 +11,13 @@ <path>interfaces input</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=input</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=input</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified input interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=input</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=input</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show Input (ifb) interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=input</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=input</command> <children> <leafNode name="detail"> <properties> <help>Show detailed input interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=input</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=input</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-l2tpv3.xml.in b/op-mode-definitions/show-interfaces-l2tpv3.xml.in index 713e36dac..2d165171c 100644 --- a/op-mode-definitions/show-interfaces-l2tpv3.xml.in +++ b/op-mode-definitions/show-interfaces-l2tpv3.xml.in @@ -11,13 +11,13 @@ <path>interfaces l2tpv3</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=l2tpv3</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=l2tpv3</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified L2TPv3 interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=l2tpv3</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=l2tpv3</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show L2TPv3 interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=l2tpv3</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=l2tpv3</command> <children> <leafNode name="detail"> <properties> <help>Show detailed L2TPv3 interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=l2tpv3</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=l2tpv3</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-loopback.xml.in b/op-mode-definitions/show-interfaces-loopback.xml.in index a24151cc3..d341a6359 100644 --- a/op-mode-definitions/show-interfaces-loopback.xml.in +++ b/op-mode-definitions/show-interfaces-loopback.xml.in @@ -11,13 +11,13 @@ <path>interfaces loopback</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=loopback</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=loopback</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified Loopback interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=loopback</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=loopback</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show Loopback interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=loopback</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=loopback</command> <children> <leafNode name="detail"> <properties> <help>Show detailed Loopback interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=loopback</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=loopback</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-pppoe.xml.in b/op-mode-definitions/show-interfaces-pppoe.xml.in index a34473148..1c6e0b83e 100644 --- a/op-mode-definitions/show-interfaces-pppoe.xml.in +++ b/op-mode-definitions/show-interfaces-pppoe.xml.in @@ -11,7 +11,7 @@ <path>interfaces pppoe</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=pppoe</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=pppoe</command> <children> <leafNode name="log"> <properties> @@ -34,13 +34,13 @@ <properties> <help>Show PPPoE interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=pppoe</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=pppoe</command> <children> <leafNode name="detail"> <properties> <help>Show detailed PPPoE interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=pppoe</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=pppoe</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in b/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in index cb62639ee..4ab2a5fbb 100644 --- a/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-pseudo-ethernet.xml.in @@ -11,13 +11,13 @@ <path>interfaces pseudo-ethernet</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=pseudo-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=pseudo-ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified pseudo-ethernet/MACvlan interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=pseudo-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=pseudo-ethernet</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show Pseudo-Ethernet/MACvlan interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=pseudo-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=pseudo-ethernet</command> <children> <leafNode name="detail"> <properties> <help>Show detailed pseudo-ethernet/MACvlan interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=pseudo-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=pseudo-ethernet</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-sstpc.xml.in b/op-mode-definitions/show-interfaces-sstpc.xml.in index a619a9fd2..307276f72 100644 --- a/op-mode-definitions/show-interfaces-sstpc.xml.in +++ b/op-mode-definitions/show-interfaces-sstpc.xml.in @@ -11,7 +11,7 @@ <path>interfaces sstpc</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=sstpc</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=sstpc</command> <children> <leafNode name="log"> <properties> @@ -34,13 +34,13 @@ <properties> <help>Show SSTP client interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=sstpc</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=sstpc</command> <children> <leafNode name="detail"> <properties> <help>Show detailed SSTP client interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=sstpc</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=sstpc</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-tunnel.xml.in b/op-mode-definitions/show-interfaces-tunnel.xml.in index 10e10e655..b99b0cbb2 100644 --- a/op-mode-definitions/show-interfaces-tunnel.xml.in +++ b/op-mode-definitions/show-interfaces-tunnel.xml.in @@ -11,13 +11,13 @@ <path>interfaces tunnel</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=tunnel</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=tunnel</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified tunnel interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=tunnel</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=tunnel</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show Tunnel interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=tunnel</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=tunnel</command> <children> <leafNode name="detail"> <properties> <help>Show detailed tunnel interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=tunnel</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=tunnel</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in b/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in index c743492fb..18ae806b7 100644 --- a/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in +++ b/op-mode-definitions/show-interfaces-virtual-ethernet.xml.in @@ -11,13 +11,13 @@ <path>interfaces virtual-ethernet</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=virtual-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=virtual-ethernet</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified virtual-ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=virtual-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=virtual-ethernet</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show virtual-ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=virtual-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=virtual-ethernet</command> <children> <leafNode name="detail"> <properties> <help>Show detailed virtual-ethernet interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=virtual-ethernet</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=virtual-ethernet</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-vti.xml.in b/op-mode-definitions/show-interfaces-vti.xml.in index d532894b7..ae5cfeb9c 100644 --- a/op-mode-definitions/show-interfaces-vti.xml.in +++ b/op-mode-definitions/show-interfaces-vti.xml.in @@ -11,13 +11,13 @@ <path>interfaces vti</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=vti</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=vti</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified vti interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=vti</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=vti</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show VTI interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=vti</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=vti</command> <children> <leafNode name="detail"> <properties> <help>Show detailed vti interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=vti</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=vti</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-vxlan.xml.in b/op-mode-definitions/show-interfaces-vxlan.xml.in index fde832551..fd729b986 100644 --- a/op-mode-definitions/show-interfaces-vxlan.xml.in +++ b/op-mode-definitions/show-interfaces-vxlan.xml.in @@ -11,13 +11,13 @@ <path>interfaces vxlan</path> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=vxlan</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=vxlan</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified VXLAN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=vxlan</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=vxlan</command> </leafNode> </children> </tagNode> @@ -25,13 +25,13 @@ <properties> <help>Show VXLAN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=vxlan</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=vxlan</command> <children> <leafNode name="detail"> <properties> <help>Show detailed VXLAN interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=vxlan</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=vxlan</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-wireguard.xml.in b/op-mode-definitions/show-interfaces-wireguard.xml.in index d045beafc..bab7f19c8 100644 --- a/op-mode-definitions/show-interfaces-wireguard.xml.in +++ b/op-mode-definitions/show-interfaces-wireguard.xml.in @@ -11,7 +11,7 @@ <script>${vyos_completion_dir}/list_interfaces --type wireguard</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireguard</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=wireguard</command> <children> <leafNode name="allowed-ips"> <properties> @@ -49,13 +49,13 @@ <properties> <help>Show WireGuard interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=wireguard</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=wireguard</command> <children> <leafNode name="detail"> <properties> <help>Show detailed Wireguard interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=wireguard</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=wireguard</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/show-interfaces-wireless.xml.in b/op-mode-definitions/show-interfaces-wireless.xml.in index f39d402f1..27c0f43db 100644 --- a/op-mode-definitions/show-interfaces-wireless.xml.in +++ b/op-mode-definitions/show-interfaces-wireless.xml.in @@ -8,13 +8,13 @@ <properties> <help>Show Wireless (WLAN) interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=wireless</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=wireless</command> <children> <leafNode name="detail"> <properties> <help>Show detailed wireless interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=wireless</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=wireless</command> </leafNode> <leafNode name="info"> <properties> @@ -31,13 +31,13 @@ <script>${vyos_completion_dir}/list_interfaces --type wireless</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wireless</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=wireless</command> <children> <leafNode name="brief"> <properties> <help>Show summary of the specified wireless interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4" --intf_type=wireless</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4" --intf-type=wireless</command> </leafNode> <node name="scan"> <properties> @@ -63,13 +63,13 @@ <properties> <help>Show specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4.$6" --intf_type=wireless</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4.$6" --intf-type=wireless</command> <children> <leafNode name="brief"> <properties> <help>Show summary of specified virtual network interface (vif) information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_name="$4.$6" --intf_type=wireless</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-name="$4.$6" --intf-type=wireless</command> </leafNode> </children> </tagNode> diff --git a/op-mode-definitions/show-interfaces-wwan.xml.in b/op-mode-definitions/show-interfaces-wwan.xml.in index 17d4111a9..2707c0d8e 100644 --- a/op-mode-definitions/show-interfaces-wwan.xml.in +++ b/op-mode-definitions/show-interfaces-wwan.xml.in @@ -12,7 +12,7 @@ <script>cd /sys/class/net; ls -d wwan*</script> </completionHelp> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_name="$4" --intf_type=wirelessmodem</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-name="$4" --intf-type=wirelessmodem</command> <children> <leafNode name="capabilities"> <properties> @@ -86,13 +86,13 @@ <properties> <help>Show Wireless Modem (WWAN) interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf_type=wirelessmodem</command> + <command>${vyos_op_scripts_dir}/interfaces.py show_summary --intf-type=wirelessmodem</command> <children> <leafNode name="detail"> <properties> <help>Show detailed Wireless Modem (WWAN( interface information</help> </properties> - <command>${vyos_op_scripts_dir}/interfaces.py show --intf_type=wirelessmodem</command> + <command>${vyos_op_scripts_dir}/interfaces.py show --intf-type=wirelessmodem</command> </leafNode> </children> </node> diff --git a/op-mode-definitions/vpn-ipsec.xml.in b/op-mode-definitions/vpn-ipsec.xml.in index 1eb5a3709..c7ba780a3 100644 --- a/op-mode-definitions/vpn-ipsec.xml.in +++ b/op-mode-definitions/vpn-ipsec.xml.in @@ -35,7 +35,7 @@ <list><x.x.x.x> <h:h:h:h:h:h:h:h></list> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_profile_dst --profile="$5" --tunnel="$7" --nbma_dst="$9"</command> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_profile_dst --profile="$5" --tunnel="$7" --nbma-dst="$9"</command> </tagNode> </children> <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_profile_all --profile="$5" --tunnel="$7"</command> @@ -219,7 +219,7 @@ <properties> <help>Show detail active IKEv2 RA sessions by connection-id</help> </properties> - <command>if systemctl is-active --quiet strongswan ; then sudo ${vyos_op_scripts_dir}/ipsec.py show_ra_detail --conn_id="$6"; else echo "IPsec process not running" ; fi</command> + <command>if systemctl is-active --quiet strongswan ; then sudo ${vyos_op_scripts_dir}/ipsec.py show_ra_detail --conn-id="$6"; else echo "IPsec process not running" ; fi</command> </tagNode> <node name="summary"> <properties> diff --git a/python/vyos/opmode.py b/python/vyos/opmode.py index d7172a0b5..230a85541 100644 --- a/python/vyos/opmode.py +++ b/python/vyos/opmode.py @@ -209,6 +209,11 @@ def run(module): for opt in type_hints: th = type_hints[opt] + # Function argument names use underscores as separators + # but command-line options should use hyphens + # Without this, we'd get options like "--foo_bar" + opt = re.sub(r'_', '-', opt) + if _get_arg_type(th) == bool: subparser.add_argument(f"--{opt}", action='store_true') else: diff --git a/python/vyos/utils/__init__.py b/python/vyos/utils/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/python/vyos/utils/__init__.py diff --git a/python/vyos/utils/dict.py b/python/vyos/utils/dict.py new file mode 100644 index 000000000..66b40d92b --- /dev/null +++ b/python/vyos/utils/dict.py @@ -0,0 +1,235 @@ +# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see <http://www.gnu.org/licenses/>. + + +def colon_separated_to_dict(data_string, uniquekeys=False): + """ Converts a string containing newline-separated entries + of colon-separated key-value pairs into a dict. + + Such files are common in Linux /proc filesystem + + Args: + data_string (str): data string + uniquekeys (bool): whether to insist that keys are unique or not + + Returns: dict + + Raises: + ValueError: if uniquekeys=True and the data string has + duplicate keys. + + Note: + If uniquekeys=True, then dict entries are always strings, + otherwise they are always lists of strings. + """ + import re + key_value_re = re.compile('([^:]+)\s*\:\s*(.*)') + + data_raw = re.split('\n', data_string) + + data = {} + + for l in data_raw: + l = l.strip() + if l: + match = re.match(key_value_re, l) + if match and (len(match.groups()) == 2): + key = match.groups()[0].strip() + value = match.groups()[1].strip() + else: + raise ValueError(f"""Line "{l}" could not be parsed a colon-separated pair """, l) + if key in data.keys(): + if uniquekeys: + raise ValueError("Data string has duplicate keys: {0}".format(key)) + else: + data[key].append(value) + else: + if uniquekeys: + data[key] = value + else: + data[key] = [value] + else: + pass + + return data + +def _mangle_dict_keys(data, regex, replacement, abs_path=[], no_tag_node_value_mangle=False, mod=0): + """ Mangles dict keys according to a regex and replacement character. + Some libraries like Jinja2 do not like certain characters in dict keys. + This function can be used for replacing all offending characters + with something acceptable. + + Args: + data (dict): Original dict to mangle + + Returns: dict + """ + from vyos.xml import is_tag + + new_dict = {} + + for key in data.keys(): + save_mod = mod + save_path = abs_path[:] + + abs_path.append(key) + + if not is_tag(abs_path): + new_key = re.sub(regex, replacement, key) + else: + if mod%2: + new_key = key + else: + new_key = re.sub(regex, replacement, key) + if no_tag_node_value_mangle: + mod += 1 + + value = data[key] + + if isinstance(value, dict): + new_dict[new_key] = _mangle_dict_keys(value, regex, replacement, abs_path=abs_path, mod=mod, no_tag_node_value_mangle=no_tag_node_value_mangle) + else: + new_dict[new_key] = value + + mod = save_mod + abs_path = save_path[:] + + return new_dict + +def mangle_dict_keys(data, regex, replacement, abs_path=[], no_tag_node_value_mangle=False): + return _mangle_dict_keys(data, regex, replacement, abs_path=abs_path, no_tag_node_value_mangle=no_tag_node_value_mangle, mod=0) + +def _get_sub_dict(d, lpath): + k = lpath[0] + if k not in d.keys(): + return {} + c = {k: d[k]} + lpath = lpath[1:] + if not lpath: + return c + elif not isinstance(c[k], dict): + return {} + return _get_sub_dict(c[k], lpath) + +def get_sub_dict(source, lpath, get_first_key=False): + """ Returns the sub-dict of a nested dict, defined by path of keys. + + Args: + source (dict): Source dict to extract from + lpath (list[str]): sequence of keys + + Returns: source, if lpath is empty, else + {key : source[..]..[key]} for key the last element of lpath, if exists + {} otherwise + """ + if not isinstance(source, dict): + raise TypeError("source must be of type dict") + if not isinstance(lpath, list): + raise TypeError("path must be of type list") + if not lpath: + return source + + ret = _get_sub_dict(source, lpath) + + if get_first_key and lpath and ret: + tmp = next(iter(ret.values())) + if not isinstance(tmp, dict): + raise TypeError("Data under node is not of type dict") + ret = tmp + + return ret + +def dict_search(path, dict_object): + """ Traverse Python dictionary (dict_object) delimited by dot (.). + Return value of key if found, None otherwise. + + This is faster implementation then jmespath.search('foo.bar', dict_object)""" + if not isinstance(dict_object, dict) or not path: + return None + + parts = path.split('.') + inside = parts[:-1] + if not inside: + if path not in dict_object: + return None + return dict_object[path] + c = dict_object + for p in parts[:-1]: + c = c.get(p, {}) + return c.get(parts[-1], None) + +def dict_search_args(dict_object, *path): + # Traverse dictionary using variable arguments + # Added due to above function not allowing for '.' in the key names + # Example: dict_search_args(some_dict, 'key', 'subkey', 'subsubkey', ...) + if not isinstance(dict_object, dict) or not path: + return None + + for item in path: + if item not in dict_object: + return None + dict_object = dict_object[item] + return dict_object + +def dict_search_recursive(dict_object, key, path=[]): + """ Traverse a dictionary recurisvely and return the value of the key + we are looking for. + + Thankfully copied from https://stackoverflow.com/a/19871956 + + Modified to yield optional path to found keys + """ + if isinstance(dict_object, list): + for i in dict_object: + new_path = path + [i] + for x in dict_search_recursive(i, key, new_path): + yield x + elif isinstance(dict_object, dict): + if key in dict_object: + new_path = path + [key] + yield dict_object[key], new_path + for k, j in dict_object.items(): + new_path = path + [k] + for x in dict_search_recursive(j, key, new_path): + yield x + +def dict_to_list(d, save_key_to=None): + """ Convert a dict to a list of dicts. + + Optionally, save the original key of the dict inside + dicts stores in that list. + """ + def save_key(i, k): + if isinstance(i, dict): + i[save_key_to] = k + return + elif isinstance(i, list): + for _i in i: + save_key(_i, k) + else: + raise ValueError(f"Cannot save the key: the item is {type(i)}, not a dict") + + collect = [] + + for k,_ in d.items(): + item = d[k] + if save_key_to is not None: + save_key(item, k) + if isinstance(item, list): + collect += item + else: + collect.append(item) + + return collect diff --git a/smoketest/configs/vrf-bgp-pppoe-underlay b/smoketest/configs/vrf-bgp-pppoe-underlay new file mode 100644 index 000000000..cba35eab1 --- /dev/null +++ b/smoketest/configs/vrf-bgp-pppoe-underlay @@ -0,0 +1,473 @@ +interfaces { + bridge br50 { + address 192.168.0.1/24 + member { + interface eth0.50 { + } + interface eth2 { + } + interface eth3 { + } + } + } + dummy dum0 { + address 100.64.51.252/32 + address 2001:db8:200:ffff::1/128 + vrf vyos-test-01 + } + ethernet eth0 { + offload { + gro + gso + rps + sg + tso + } + ring-buffer { + rx 256 + tx 256 + } + vif 5 { + address 2001:db8:200:f0::114/64 + address 100.64.50.121/28 + vrf vyos-test-01 + } + vif 10 { + address 2001:db8:200:10::ffff/64 + address 2001:db8:200::ffff/64 + address 100.64.50.62/26 + vrf vyos-test-01 + } + vif 15 { + address 100.64.50.78/28 + address 2001:db8:200:15::ffff/64 + vrf vyos-test-01 + } + vif 50 { + description "Member of bridge br50" + } + vif 110 { + address 100.64.51.190/27 + address 100.64.51.158/28 + address 2001:db8:200:101::ffff/64 + vrf vyos-test-01 + } + vif 410 { + address 100.64.51.206/28 + address 2001:db8:200:104::ffff/64 + vrf vyos-test-01 + } + vif 500 { + address 100.64.51.238/28 + address 2001:db8:200:50::ffff/64 + vrf vyos-test-01 + } + vif 520 { + address 100.64.50.190/28 + address 2001:db8:200:520::ffff/64 + vrf vyos-test-01 + } + vif 666 { + address 2001:db8:200:ff::101:1/112 + address 100.64.51.223/31 + vrf vyos-test-01 + } + vif 800 { + address 2001:db8:200:ff::104:1/112 + address 100.64.51.212/31 + vrf vyos-test-01 + } + vif 810 { + address 100.64.51.30/27 + address 2001:db8:200:102::ffff/64 + vrf vyos-test-01 + } + } + ethernet eth1 { + offload { + gro + gso + rps + sg + tso + } + ring-buffer { + rx 256 + tx 256 + } + } + ethernet eth2 { + offload { + gro + gso + sg + tso + } + } + ethernet eth3 { + offload { + gro + gso + sg + tso + } + } + loopback lo { + } + pppoe pppoe7 { + authentication { + password vyos + username vyos + } + dhcpv6-options { + pd 0 { + interface br50 { + address 1 + } + length 56 + } + } + ip { + adjust-mss 1452 + } + ipv6 { + address { + autoconf + } + adjust-mss 1432 + } + mtu 1492 + no-peer-dns + source-interface eth1 + } + virtual-ethernet veth0 { + address 100.64.51.220/31 + address 2001:db8:200:ff::105:1/112 + description "Core: connect vyos-test-01 and default VRF" + peer-name veth1 + } + virtual-ethernet veth1 { + address 100.64.51.221/31 + address 2001:db8:200:ff::105:2/112 + description "Core: connect vyos-test-01 and default VRF" + peer-name veth0 + vrf vyos-test-01 + } + wireguard wg500 { + address 100.64.51.209/31 + mtu 1500 + peer A { + address 192.0.2.1 + allowed-ips 0.0.0.0/0 + port 5500 + public-key KGSXF4QckzGe7f7CT+r6VZ5brOD/pVYk8yvrxOQ+X0Y= + } + port 5500 + private-key iLJh6Me6AdPJtNv3dgGhUbtyFxExxmNU4v0Fs6YE2Xc= + vrf vyos-test-01 + } + wireguard wg501 { + address 2001:db8:200:ff::102:2/112 + mtu 1500 + peer A { + address 2001:db8:300::1 + allowed-ips ::/0 + port 5501 + public-key OF+1OJ+VfQ0Yw1mgVtQ2ion4CnAdy8Bvx7yEiO4+Pn8= + } + port 5501 + private-key 0MP5X0PW58O4q2LDpuIXgZ0ySyAoWH8/kdpvQccCbUU= + vrf vyos-test-01 + } + wireguard wg666 { + address 172.29.0.0/31 + mtu 1500 + peer B { + allowed-ips 0.0.0.0/0 + public-key 2HT+RfwcqJMYNYzdmtmpem8Ht0dL37o31APHVwmh024= + } + port 50666 + private-key zvPnp2MLAoX7SotuHLFLDyy4sdlD7ttbD1xNEqA3mkU= + } +} +nat { + source { + rule 100 { + outbound-interface pppoe7 + source { + address 192.168.0.0/24 + } + translation { + address masquerade + } + } + } +} +policy { + prefix-list AS100-origin-v4 { + rule 10 { + action permit + prefix 100.64.0.0/12 + } + rule 100 { + action permit + prefix 0.0.0.0/0 + } + } + prefix-list AS200-origin-v4 { + rule 10 { + action permit + prefix 10.0.0.0/8 + } + rule 20 { + action permit + prefix 172.16.0.0/12 + } + + } + prefix-list6 AS100-origin-v6 { + rule 10 { + action permit + prefix 2001:db8:200::/40 + } + } + prefix-list6 AS200-origin-v6 { + rule 10 { + action permit + prefix 2001:db8:100::/40 + } + } +} +protocols { + static { + route 192.0.2.255/32 { + interface pppoe7 { + } + } + route 100.64.50.0/23 { + next-hop 100.64.51.221 { + } + } + route6 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff/128 { + interface pppoe7 { + } + } + } +} +qos { + interface pppoe7 { + egress isp-out + } + policy { + shaper isp-out { + bandwidth 38mbit + default { + bandwidth 100% + burst 15k + queue-limit 1000 + queue-type fq-codel + } + } + } +} +service { + router-advert { + interface br50 { + prefix ::/64 { + preferred-lifetime 2700 + valid-lifetime 5400 + } + } + interface eth0.500 { + default-preference high + name-server 2001:db8:200::1 + name-server 2001:db8:200::2 + prefix 2001:db8:200:50::/64 { + valid-lifetime infinity + } + } + interface eth0.520 { + default-preference high + name-server 2001:db8:200::1 + name-server 2001:db8:200::2 + prefix 2001:db8:200:520::/64 { + valid-lifetime infinity + } + } + } + ssh { + disable-host-validation + dynamic-protection { + allow-from 100.64.0.0/10 + allow-from 2001:db8:200::/40 + } + } +} +system { + config-management { + commit-revisions 100 + } + conntrack { + modules { + ftp + h323 + nfs + pptp + sip + sqlnet + tftp + } + } + console { + device ttyS0 { + speed 115200 + } + } + domain-name vyos.net + host-name vyos + login { + user vyos { + authentication { + encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 + plaintext-password "" + } + } + } + name-server 192.168.0.1 + syslog { + global { + facility all { + level info + } + facility protocols { + level debug + } + } + } + time-zone Europe/Berlin +} +vrf { + bind-to-all + name vyos-test-01 { + protocols { + bgp { + address-family { + ipv4-unicast { + network 100.64.50.0/23 { + } + } + ipv6-unicast { + network 2001:db8:200:ffff::1/128 { + } + } + } + neighbor 100.64.51.208 { + peer-group AS100v4 + } + neighbor 100.64.51.222 { + address-family { + ipv4-unicast { + default-originate { + } + maximum-prefix 10 + prefix-list { + export AS100-origin-v4 + import AS200-origin-v4 + } + soft-reconfiguration { + inbound + } + } + } + capability { + dynamic + } + remote-as 200 + } + neighbor 100.64.51.251 { + peer-group AS100v4 + shutdown + } + neighbor 100.64.51.254 { + peer-group AS100v4 + shutdown + } + neighbor 2001:db8:200:ffff::2 { + peer-group AS100v6 + shutdown + } + neighbor 2001:db8:200:ffff::a { + peer-group AS100v6 + } + neighbor 2001:db8:200:ff::101:2 { + address-family { + ipv6-unicast { + maximum-prefix 10 + prefix-list { + export AS100-origin-v6 + import AS200-origin-v6 + } + soft-reconfiguration { + inbound + } + } + } + capability { + dynamic + } + remote-as 200 + } + peer-group AS100v4 { + address-family { + ipv4-unicast { + nexthop-self { + } + } + } + capability { + dynamic + } + remote-as internal + update-source dum0 + } + peer-group AS100v6 { + address-family { + ipv6-unicast { + nexthop-self { + } + } + } + capability { + dynamic + } + remote-as internal + update-source dum0 + } + system-as 100 + } + static { + route 192.168.0.0/24 { + next-hop 100.64.51.220 { + } + } + route 100.64.50.0/23 { + blackhole { + } + } + route 100.64.51.32/27 { + next-hop 100.64.51.5 { + } + } + route6 2001:db8:2fe:ffff::/64 { + next-hop 2001:db8:200:102::5 { + } + } + } + } + table 1000 + } +} + +// Warning: Do not remove the following line. +// vyos-config-version: "bgp@3:broadcast-relay@1:cluster@1:config-management@1:conntrack@3:conntrack-sync@2:container@1:dhcp-relay@2:dhcp-server@6:dhcpv6-server@1:dns-forwarding@3:firewall@9:flow-accounting@1:https@4:ids@1:interfaces@28:ipoe-server@1:ipsec@12:isis@2:l2tp@4:lldp@1:mdns@1:monitoring@1:nat@5:nat66@1:ntp@2:openconnect@2:ospf@1:policy@5:pppoe-server@6:pptp@2:qos@2:quagga@10:rpki@1:salt@1:snmp@3:ssh@2:sstp@4:system@25:vrf@3:vrrp@3:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2" +// Release version: 1.4-rolling-202303160317 diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 3a4ef666a..f35cdaa4c 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2021-2022 VyOS maintainers and contributors +# 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 @@ -1071,6 +1071,22 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): }, }, }, + 'match-protocol' : { + 'rule' : { + '10' : { + 'action' : 'permit', + 'match' : { + 'protocol' : 'static', + }, + }, + '20' : { + 'action' : 'permit', + 'match' : { + 'protocol' : 'bgp', + }, + }, + }, + }, 'relative-metric' : { 'rule' : { '10' : { @@ -1202,6 +1218,8 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): self.cli_set(path + ['rule', rule, 'match', 'rpki', 'notfound']) if 'rpki-valid' in rule_config['match']: self.cli_set(path + ['rule', rule, 'match', 'rpki', 'valid']) + if 'protocol' in rule_config['match']: + self.cli_set(path + ['rule', rule, 'match', 'protocol', rule_config['match']['protocol']]) if 'tag' in rule_config['match']: self.cli_set(path + ['rule', rule, 'match', 'tag', rule_config['match']['tag']]) @@ -1368,6 +1386,9 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase): if 'peer' in rule_config['match']: tmp = f'match peer {rule_config["match"]["peer"]}' self.assertIn(tmp, config) + if 'protocol' in rule_config['match']: + tmp = f'match source-protocol {rule_config["match"]["protocol"]}' + self.assertIn(tmp, config) if 'rpki-invalid' in rule_config['match']: tmp = f'match rpki invalid' self.assertIn(tmp, config) diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py index 706663ce5..275f1a1df 100755 --- a/smoketest/scripts/cli/test_protocols_static.py +++ b/smoketest/scripts/cli/test_protocols_static.py @@ -31,6 +31,8 @@ routes = { '192.0.2.100' : { 'distance' : '100' }, '192.0.2.110' : { 'distance' : '110', 'interface' : 'eth0' }, '192.0.2.120' : { 'distance' : '120', 'disable' : '' }, + '192.0.2.130' : { 'bfd' : '' }, + '192.0.2.140' : { 'bfd_source' : '192.0.2.10' }, }, 'interface' : { 'eth0' : { 'distance' : '130' }, @@ -67,6 +69,8 @@ routes = { '2001:db8::1' : { 'distance' : '10' }, '2001:db8::2' : { 'distance' : '20', 'interface' : 'eth0' }, '2001:db8::3' : { 'distance' : '30', 'disable' : '' }, + '2001:db8::4' : { 'bfd' : '' }, + '2001:db8::5' : { 'bfd_source' : '2001:db8::ffff' }, }, 'interface' : { 'eth0' : { 'distance' : '40', 'vrf' : 'black' }, @@ -117,6 +121,7 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): self.cli_commit() def test_01_static(self): + bfd_profile = 'vyos-test' for route, route_config in routes.items(): route_type = 'route' if is_ipv6(route): @@ -133,6 +138,10 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): self.cli_set(base + ['next-hop', next_hop, 'interface', next_hop_config['interface']]) if 'vrf' in next_hop_config: self.cli_set(base + ['next-hop', next_hop, 'vrf', next_hop_config['vrf']]) + if 'bfd' in next_hop_config: + self.cli_set(base + ['next-hop', next_hop, 'bfd', 'profile', bfd_profile ]) + if 'bfd_source' in next_hop_config: + self.cli_set(base + ['next-hop', next_hop, 'bfd', 'multi-hop', 'source', next_hop_config['bfd_source'], 'profile', bfd_profile]) if 'interface' in route_config: @@ -187,6 +196,10 @@ class TestProtocolsStatic(VyOSUnitTestSHIM.TestCase): tmp += ' ' + next_hop_config['distance'] if 'vrf' in next_hop_config: tmp += ' nexthop-vrf ' + next_hop_config['vrf'] + if 'bfd' in next_hop_config: + tmp += ' bfd profile ' + bfd_profile + if 'bfd_source' in next_hop_config: + tmp += ' bfd multi-hop source ' + next_hop_config['bfd_source'] + ' profile ' + bfd_profile if 'disable' in next_hop_config: self.assertNotIn(tmp, frrconfig) diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py index af2937db8..ecca87db0 100755 --- a/src/conf_mode/protocols_isis.py +++ b/src/conf_mode/protocols_isis.py @@ -129,7 +129,7 @@ def verify(isis): 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}!') + 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']: diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py index fbb876123..b73483470 100755 --- a/src/conf_mode/protocols_ospf.py +++ b/src/conf_mode/protocols_ospf.py @@ -196,7 +196,7 @@ def verify(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}!') + raise ConfigError(f'Interface "{interface}" is not a member of VRF "{vrf}"!') # Segment routing checks if dict_search('segment_routing.global_block', ospf): diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py index ee1fdd399..cb21bd83c 100755 --- a/src/conf_mode/protocols_ospfv3.py +++ b/src/conf_mode/protocols_ospfv3.py @@ -138,7 +138,7 @@ def verify(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}!') + raise ConfigError(f'Interface "{interface}" is not a member of VRF "{vrf}"!') return None diff --git a/src/op_mode/bgp.py b/src/op_mode/bgp.py index 3f6d45dd7..af9ea788b 100755 --- a/src/op_mode/bgp.py +++ b/src/op_mode/bgp.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 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 @@ -15,101 +15,133 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # # Purpose: -# Displays bgp neighbors information. -# Used by the "show bgp (vrf <tag>) ipv4|ipv6 neighbors" commands. +# Displays BGP neighbors and tables information. import re import sys import typing -import jmespath from jinja2 import Template -from humps import decamelize - -from vyos.configquery import ConfigTreeQuery import vyos.opmode -ArgFamily = typing.Literal['inet', 'inet6'] - frr_command_template = Template(""" -{% if family %} - show bgp - {{ 'vrf ' ~ vrf if vrf else '' }} - {{ 'ipv6' if family == 'inet6' else 'ipv4'}} - {{ 'neighbor ' ~ peer if peer else 'summary' }} +show bgp + +{## VRF and family modifiers that may precede any options ##} + +{% if vrf %} + vrf {{vrf}} +{% endif %} + +{% if family == "inet" %} + ipv4 +{% elif family == "inet6" %} + ipv6 +{% elif family == "l2vpn" %} + l2vpn evpn +{% endif %} + +{% if family_modifier == "unicast" %} + unicast +{% elif family_modifier == "multicast" %} + multicast +{% elif family_modifier == "flowspec" %} + flowspec +{% elif family_modifier == "vpn" %} + vpn +{% endif %} + +{## Mutually exclusive query parameters ##} + +{# Network prefix #} +{% if prefix %} + {{prefix}} + + {% if longer_prefixes %} + longer-prefixes + {% elif best_path %} + bestpath + {% endif %} {% endif %} +{# Regex #} +{% if regex %} + regex {{regex}} +{% endif %} + +{## Raw modifier ##} + {% if raw %} json {% endif %} """) +ArgFamily = typing.Literal['inet', 'inet6', 'l2vpn'] +ArgFamilyModifier = typing.Literal['unicast', 'labeled_unicast', 'multicast', 'vpn', 'flowspec'] + +def show_summary(raw: bool): + from vyos.util import cmd + + if raw: + from json import loads + + output = cmd(f"vtysh -c 'show bgp summary json'").strip() -def _verify(func): - """Decorator checks if BGP config exists - BGP configuration can be present under vrf <tag> - If we do npt get arg 'peer' then it can be 'bgp summary' - """ - from functools import wraps - - @wraps(func) - def _wrapper(*args, **kwargs): - config = ConfigTreeQuery() - afi = 'ipv6' if kwargs.get('family') == 'inet6' else 'ipv4' - global_vrfs = ['all', 'default'] - peer = kwargs.get('peer') - vrf = kwargs.get('vrf') - unconf_message = f'BGP or neighbor is not configured' - # Add option to check the specific neighbor if we have arg 'peer' - peer_opt = f'neighbor {peer} address-family {afi}-unicast' if peer else '' - vrf_opt = '' - if vrf and vrf not in global_vrfs: - vrf_opt = f'vrf name {vrf}' - # Check if config does not exist - if not config.exists(f'{vrf_opt} protocols bgp {peer_opt}'): - raise vyos.opmode.UnconfiguredSubsystem(unconf_message) - return func(*args, **kwargs) - - return _wrapper - - -@_verify -def show_neighbors(raw: bool, - family: ArgFamily, - peer: typing.Optional[str], - vrf: typing.Optional[str]): - kwargs = dict(locals()) - frr_command = frr_command_template.render(kwargs) - frr_command = re.sub(r'\s+', ' ', frr_command) + # FRR 8.5 correctly returns an empty object when BGP is not running, + # we don't need to do anything special here + return loads(output) + else: + output = cmd(f"vtysh -c 'show bgp summary'") + return output +def show_neighbors(raw: bool): from vyos.util import cmd - output = cmd(f"vtysh -c '{frr_command}'") + from vyos.utils.dict import dict_to_list if raw: from json import loads - data = loads(output) - # Get list of the peers - peers = jmespath.search('*.peers | [0]', data) - if peers: - # Create new dict, delete old key 'peers' - # add key 'peers' neighbors to the list - list_peers = [] - new_dict = jmespath.search('* | [0]', data) - if 'peers' in new_dict: - new_dict.pop('peers') - - for neighbor, neighbor_options in peers.items(): - neighbor_options['neighbor'] = neighbor - list_peers.append(neighbor_options) - new_dict['peers'] = list_peers - return decamelize(new_dict) - data = jmespath.search('* | [0]', data) - return decamelize(data) + output = cmd(f"vtysh -c 'show bgp neighbors json'").strip() + d = loads(output) + return dict_to_list(d, save_key_to="neighbor") else: + output = cmd(f"vtysh -c 'show bgp neighbors'") return output +def show(raw: bool, + family: ArgFamily, + family_modifier: ArgFamilyModifier, + prefix: typing.Optional[str], + longer_prefixes: typing.Optional[bool], + best_path: typing.Optional[bool], + regex: typing.Optional[str], + vrf: typing.Optional[str]): + from vyos.utils.dict import dict_to_list + + if (longer_prefixes or best_path) and (prefix is None): + raise ValueError("longer_prefixes and best_path can only be used when prefix is given") + elif (family == "l2vpn") and (family_modifier is not None): + raise ValueError("l2vpn family does not accept any modifiers") + else: + kwargs = dict(locals()) + + frr_command = frr_command_template.render(kwargs) + frr_command = re.sub(r'\s+', ' ', frr_command) + + from vyos.util import cmd + output = cmd(f"vtysh -c '{frr_command}'") + + if raw: + from json import loads + d = loads(output) + if not ("routes" in d): + raise vyos.opmode.InternalError("FRR returned a BGP table with no routes field") + d = d["routes"] + routes = dict_to_list(d, save_key_to="route_key") + return routes + else: + return output if __name__ == '__main__': try: |