summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--data/configd-include.json2
-rw-r--r--data/templates/accel-ppp/l2tp.config.tmpl1
-rw-r--r--data/templates/frr/bgpd.frr.tmpl68
-rw-r--r--data/templates/frr/ospf6d.frr.tmpl (renamed from data/templates/frr/ospfv3.frr.tmpl)0
-rw-r--r--data/templates/frr/ospfd.frr.tmpl (renamed from data/templates/frr/ospf.frr.tmpl)25
-rw-r--r--data/templates/frr/policy.frr.tmpl3
-rw-r--r--data/templates/frr/static_routes_macro.j22
-rw-r--r--data/templates/frr/vrf-vni.frr.tmpl7
-rw-r--r--data/templates/frr/vrf.frr.tmpl9
-rw-r--r--data/templates/https/nginx.default.tmpl2
-rw-r--r--data/templates/ipsec/swanctl/peer.tmpl4
-rw-r--r--data/templates/ipsec/swanctl/profile.tmpl2
-rw-r--r--data/templates/ipsec/swanctl/remote_access.tmpl2
-rw-r--r--data/templates/ndppd/ndppd.conf.tmpl (renamed from data/templates/proxy-ndp/ndppd.conf.tmpl)8
-rw-r--r--data/templates/openvpn/server.conf.tmpl19
-rw-r--r--data/templates/pppoe/ipv6-up.script.tmpl37
-rw-r--r--data/templates/pppoe/peer.tmpl34
-rw-r--r--debian/control1
-rwxr-xr-xdebian/rules4
-rw-r--r--debian/vyos-1x.install2
-rw-r--r--interface-definitions/bcast-relay.xml.in13
-rw-r--r--interface-definitions/containers.xml.in59
-rw-r--r--interface-definitions/firewall-options.xml.in50
-rw-r--r--interface-definitions/https.xml.in1
-rw-r--r--interface-definitions/include/bgp/afi-export-import.xml.i41
-rw-r--r--interface-definitions/include/bgp/afi-l2vpn-common.xml.i44
-rw-r--r--interface-definitions/include/bgp/afi-label.xml.i36
-rw-r--r--interface-definitions/include/bgp/afi-path-limit.xml.i14
-rw-r--r--interface-definitions/include/bgp/afi-rd.xml.i28
-rw-r--r--interface-definitions/include/bgp/afi-route-map-export-import.xml.i34
-rw-r--r--interface-definitions/include/bgp/afi-route-map-vpn.xml.i17
-rw-r--r--interface-definitions/include/bgp/afi-route-map.xml.i33
-rw-r--r--interface-definitions/include/bgp/afi-route-target-vpn.xml.i52
-rw-r--r--interface-definitions/include/bgp/protocol-common-config.xml.i40
-rw-r--r--interface-definitions/include/bgp/route-distinguisher.xml.i2
-rw-r--r--interface-definitions/include/bgp/route-target.xml.i45
-rw-r--r--interface-definitions/include/conntrack-module-disable.xml.i8
-rw-r--r--interface-definitions/include/interface/adjust-mss.xml.i23
-rw-r--r--interface-definitions/include/interface/arp-cache-timeout.xml.i (renamed from interface-definitions/include/interface/interface-arp-cache-timeout.xml.i)2
-rw-r--r--interface-definitions/include/interface/description.xml.i (renamed from interface-definitions/include/interface/interface-description.xml.i)2
-rw-r--r--interface-definitions/include/interface/dial-on-demand.xml.i (renamed from interface-definitions/include/interface/interface-dial-on-demand.xml.i)2
-rw-r--r--interface-definitions/include/interface/disable-arp-filter.xml.i (renamed from interface-definitions/include/interface/interface-disable-arp-filter.xml.i)2
-rw-r--r--interface-definitions/include/interface/disable-forwarding.xml.i8
-rw-r--r--interface-definitions/include/interface/disable-link-detect.xml.i (renamed from interface-definitions/include/interface/interface-disable-link-detect.xml.i)2
-rw-r--r--interface-definitions/include/interface/disable.xml.i (renamed from interface-definitions/include/interface/interface-disable.xml.i)2
-rw-r--r--interface-definitions/include/interface/eapol.xml.i (renamed from interface-definitions/include/interface/interface-eapol.xml.i)2
-rw-r--r--interface-definitions/include/interface/enable-arp-accept.xml.i (renamed from interface-definitions/include/interface/interface-enable-arp-accept.xml.i)2
-rw-r--r--interface-definitions/include/interface/enable-arp-announce.xml.i (renamed from interface-definitions/include/interface/interface-enable-arp-announce.xml.i)2
-rw-r--r--interface-definitions/include/interface/enable-arp-ignore.xml.i (renamed from interface-definitions/include/interface/interface-enable-arp-ignore.xml.i)2
-rw-r--r--interface-definitions/include/interface/enable-proxy-arp.xml.i (renamed from interface-definitions/include/interface/interface-enable-proxy-arp.xml.i)2
-rw-r--r--interface-definitions/include/interface/hw-id.xml.i (renamed from interface-definitions/include/interface/interface-hw-id.xml.i)2
-rw-r--r--interface-definitions/include/interface/interface-disable-forwarding.xml.i8
-rw-r--r--interface-definitions/include/interface/interface-ipv4-options.xml.i18
-rw-r--r--interface-definitions/include/interface/ipv4-options.xml.i19
-rw-r--r--interface-definitions/include/interface/ipv6-disable-forwarding.xml.i8
-rw-r--r--interface-definitions/include/interface/ipv6-options.xml.i (renamed from interface-definitions/include/interface/interface-ipv6-options.xml.i)5
-rw-r--r--interface-definitions/include/interface/mac.xml.i (renamed from interface-definitions/include/interface/interface-mac.xml.i)2
-rw-r--r--interface-definitions/include/interface/mirror.xml.i (renamed from interface-definitions/include/interface/interface-mirror.xml.i)2
-rw-r--r--interface-definitions/include/interface/mtu-1200-16000.xml.i (renamed from interface-definitions/include/interface/interface-mtu-1200-16000.xml.i)2
-rw-r--r--interface-definitions/include/interface/mtu-1450-16000.xml.i (renamed from interface-definitions/include/interface/interface-mtu-1450-16000.xml.i)2
-rw-r--r--interface-definitions/include/interface/mtu-64-8024.xml.i (renamed from interface-definitions/include/interface/interface-mtu-64-8024.xml.i)2
-rw-r--r--interface-definitions/include/interface/mtu-68-1500.xml.i (renamed from interface-definitions/include/interface/interface-mtu-68-1500.xml.i)2
-rw-r--r--interface-definitions/include/interface/mtu-68-16000.xml.i (renamed from interface-definitions/include/interface/interface-mtu-68-16000.xml.i)2
-rw-r--r--interface-definitions/include/interface/parameters-dont-fragment.xml.i (renamed from interface-definitions/include/interface/interface-parameters-dont-fragment.xml.i)2
-rw-r--r--interface-definitions/include/interface/parameters-flowlabel.xml.i (renamed from interface-definitions/include/interface/interface-parameters-flowlabel.xml.i)2
-rw-r--r--interface-definitions/include/interface/parameters-key.xml.i (renamed from interface-definitions/include/interface/interface-parameters-key.xml.i)2
-rw-r--r--interface-definitions/include/interface/parameters-tos.xml.i (renamed from interface-definitions/include/interface/interface-parameters-tos.xml.i)0
-rw-r--r--interface-definitions/include/interface/parameters-ttl.xml.i (renamed from interface-definitions/include/interface/interface-parameters-ttl.xml.i)2
-rw-r--r--interface-definitions/include/interface/proxy-arp-pvlan.xml.i (renamed from interface-definitions/include/interface/interface-proxy-arp-pvlan.xml.i)2
-rw-r--r--interface-definitions/include/interface/source-validation.xml.i (renamed from interface-definitions/include/interface/interface-source-validation.xml.i)2
-rw-r--r--interface-definitions/include/interface/vif-s.xml.i32
-rw-r--r--interface-definitions/include/interface/vif.xml.i16
-rw-r--r--interface-definitions/include/interface/vrf.xml.i (renamed from interface-definitions/include/interface/interface-vrf.xml.i)2
-rw-r--r--interface-definitions/include/interface/xdp.xml.i (renamed from interface-definitions/include/interface/interface-xdp.xml.i)2
-rw-r--r--interface-definitions/include/isis/protocol-common-config.xml.i24
-rw-r--r--interface-definitions/include/isis/redistribute-ipv4.xml.i42
-rw-r--r--interface-definitions/include/isis/redistribute-ipv6.xml.i42
-rw-r--r--interface-definitions/include/isis/redistribute-level-1-2.xml.i20
-rw-r--r--interface-definitions/include/ospf/protocol-common-config.xml.i17
-rw-r--r--interface-definitions/include/port-number.xml.i1
-rw-r--r--interface-definitions/include/pppoe-access-concentrator.xml.i11
-rw-r--r--interface-definitions/interfaces-bonding.xml.in20
-rw-r--r--interface-definitions/interfaces-bridge.xml.in18
-rw-r--r--interface-definitions/interfaces-dummy.xml.in8
-rw-r--r--interface-definitions/interfaces-ethernet.xml.in24
-rw-r--r--interface-definitions/interfaces-geneve.xml.in20
-rw-r--r--interface-definitions/interfaces-l2tpv3.xml.in14
-rw-r--r--interface-definitions/interfaces-loopback.xml.in4
-rw-r--r--interface-definitions/interfaces-macsec.xml.in12
-rw-r--r--interface-definitions/interfaces-openvpn.xml.in28
-rw-r--r--interface-definitions/interfaces-pppoe.xml.in45
-rw-r--r--interface-definitions/interfaces-pseudo-ethernet.xml.in16
-rw-r--r--interface-definitions/interfaces-tunnel.xml.in22
-rw-r--r--interface-definitions/interfaces-vti.xml.in10
-rw-r--r--interface-definitions/interfaces-vxlan.xml.in33
-rw-r--r--interface-definitions/interfaces-wireguard.xml.in25
-rw-r--r--interface-definitions/interfaces-wireless.xml.in16
-rw-r--r--interface-definitions/interfaces-wwan.xml.in16
-rw-r--r--interface-definitions/ntp.xml.in2
-rw-r--r--interface-definitions/policy-local-route.xml.in12
-rw-r--r--interface-definitions/policy.xml.in60
-rw-r--r--interface-definitions/service_console-server.xml.in2
-rw-r--r--interface-definitions/service_pppoe-server.xml.in10
-rw-r--r--interface-definitions/service_webproxy.xml.in13
-rw-r--r--interface-definitions/snmp.xml.in2
-rw-r--r--interface-definitions/ssh.xml.in2
-rw-r--r--interface-definitions/system-conntrack.xml.in72
-rw-r--r--interface-definitions/system-login.xml.in2
-rw-r--r--interface-definitions/system-proxy.xml.in13
-rw-r--r--interface-definitions/system-syslog.xml.in14
-rw-r--r--interface-definitions/tftp-server.xml.in11
-rw-r--r--interface-definitions/vpn_ipsec.xml.in12
-rw-r--r--interface-definitions/vpn_l2tp.xml.in1
-rw-r--r--interface-definitions/vpn_sstp.xml.in2
-rw-r--r--interface-definitions/vrf.xml.in19
-rw-r--r--interface-definitions/vrrp.xml.in4
-rw-r--r--op-mode-definitions/containers.xml.in71
-rw-r--r--op-mode-definitions/dns-forwarding.xml.in3
-rw-r--r--op-mode-definitions/generate-ipsec-profile.xml.in31
-rw-r--r--op-mode-definitions/include/bgp/afi-common.xml.i24
-rw-r--r--op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i14
-rw-r--r--op-mode-definitions/include/bgp/afi-ipv4-ipv6-vpn.xml.i23
-rw-r--r--op-mode-definitions/include/bgp/exact-match.xml.i8
-rw-r--r--op-mode-definitions/include/bgp/show-bgp-common.xml.i2
-rw-r--r--op-mode-definitions/ipv4-route.xml.in6
-rw-r--r--op-mode-definitions/ipv6-route.xml.in6
-rw-r--r--op-mode-definitions/monitor-protocol.xml.in10
-rw-r--r--op-mode-definitions/nhrp.xml.in4
-rw-r--r--op-mode-definitions/openvpn.xml.in6
-rw-r--r--op-mode-definitions/pppoe-server.xml.in3
-rw-r--r--op-mode-definitions/reset-conntrack.xml.in3
-rw-r--r--op-mode-definitions/reset-vpn.xml.in3
-rw-r--r--op-mode-definitions/restart-frr.xml.in110
-rw-r--r--op-mode-definitions/show-system.xml.in6
-rw-r--r--op-mode-definitions/show-vpn.xml.in20
-rw-r--r--op-mode-definitions/terminal.xml.in8
-rw-r--r--op-mode-definitions/vpn-ipsec.xml.in8
-rw-r--r--python/vyos/configdict.py8
-rw-r--r--python/vyos/configverify.py4
-rw-r--r--python/vyos/defaults.py3
-rw-r--r--python/vyos/ifconfig/bridge.py1
-rwxr-xr-xpython/vyos/ifconfig/interface.py95
-rw-r--r--python/vyos/ifconfig/pppoe.py114
-rw-r--r--python/vyos/ifconfig/section.py12
-rw-r--r--python/vyos/ifconfig/tunnel.py28
-rw-r--r--python/vyos/ifconfig/wireguard.py27
-rw-r--r--python/vyos/migrator.py18
-rw-r--r--python/vyos/systemversions.py28
-rw-r--r--python/vyos/template.py2
-rw-r--r--python/vyos/util.py23
-rw-r--r--python/vyos/xml/__init__.py2
-rw-r--r--python/vyos/xml/definition.py6
-rw-r--r--python/vyos/xml/kw.py1
-rw-r--r--python/vyos/xml/load.py17
-rwxr-xr-xscripts/build-command-op-templates41
-rwxr-xr-xscripts/build-component-versions47
-rwxr-xr-xscripts/override-default38
-rw-r--r--smoketest/configs/isis-small1
-rw-r--r--smoketest/scripts/cli/base_interfaces_test.py46
-rw-r--r--smoketest/scripts/cli/base_vyostest_shim.py25
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_pppoe.py120
-rwxr-xr-xsmoketest/scripts/cli/test_nat66.py9
-rwxr-xr-xsmoketest/scripts/cli/test_policy.py53
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py61
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospf.py45
-rwxr-xr-xsmoketest/scripts/cli/test_service_ssh.py7
-rwxr-xr-xsmoketest/scripts/cli/test_system_conntrack.py23
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_ipsec.py11
-rwxr-xr-xsrc/conf_mode/conntrack.py11
-rwxr-xr-xsrc/conf_mode/containers.py199
-rwxr-xr-xsrc/conf_mode/firewall_options.py150
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py5
-rwxr-xr-xsrc/conf_mode/interfaces-pppoe.py93
-rwxr-xr-xsrc/conf_mode/interfaces-wwan.py1
-rwxr-xr-xsrc/conf_mode/nat.py8
-rwxr-xr-xsrc/conf_mode/nat66.py21
-rwxr-xr-xsrc/conf_mode/policy-local-route.py39
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py59
-rwxr-xr-xsrc/conf_mode/protocols_isis.py10
-rwxr-xr-xsrc/conf_mode/protocols_ospf.py15
-rwxr-xr-xsrc/conf_mode/protocols_ospfv3.py4
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py24
-rwxr-xr-xsrc/conf_mode/vrf.py20
-rwxr-xr-xsrc/conf_mode/vrf_vni.py76
-rwxr-xr-xsrc/etc/ipsec.d/vti-up-down2
-rwxr-xr-xsrc/etc/ppp/ip-up.d/99-vyos-pppoe-callback59
-rw-r--r--src/etc/sysctl.d/32-vyos-podman.conf5
-rw-r--r--src/etc/udev/rules.d/90-vyos-serial.rules8
-rwxr-xr-xsrc/etc/update-motd.d/99-reboot7
-rwxr-xr-xsrc/migration-scripts/conntrack/2-to-337
-rwxr-xr-xsrc/migration-scripts/firewall/5-to-663
-rwxr-xr-xsrc/op_mode/containers_op.py49
-rwxr-xr-xsrc/op_mode/dns_forwarding_statistics.py2
-rwxr-xr-xsrc/op_mode/ikev2_profile_generator.py6
-rwxr-xr-xsrc/op_mode/pki.py15
-rwxr-xr-xsrc/op_mode/restart_frr.py2
-rwxr-xr-xsrc/op_mode/show_interfaces.py4
-rwxr-xr-xsrc/op_mode/show_ipsec_sa.py8
-rwxr-xr-xsrc/op_mode/show_nat_rules.py84
-rwxr-xr-xsrc/op_mode/show_system_integrity.py70
-rwxr-xr-xsrc/op_mode/wireguard_client.py3
-rw-r--r--src/systemd/opennhrp.service4
-rwxr-xr-xsrc/validators/bgp-large-community-list36
-rwxr-xr-xsrc/validators/bgp-route-target51
205 files changed, 2466 insertions, 1761 deletions
diff --git a/Makefile b/Makefile
index c8f6ac7c9..b582ef84c 100644
--- a/Makefile
+++ b/Makefile
@@ -61,12 +61,7 @@ op_mode_definitions: $(op_xml_obj)
# XXX: test if there are empty node.def files - this is not allowed as these
# could mask help strings or mandatory priority statements
- #find $(OP_TMPL_DIR) -name node.def -type f -empty -exec false {} + || sh -c 'echo "There are empty node.def files! Check your interface definitions." && exit 1'
-
-.PHONY: component_versions
-.ONESHELL:
-component_versions: interface_definitions
- $(CURDIR)/scripts/build-component-versions $(BUILD_DIR)/interface-definitions $(DATA_DIR)
+ find $(OP_TMPL_DIR) -name node.def -type f -empty -exec false {} + || sh -c 'echo "There are empty node.def files! Check your interface definitions." && exit 1'
.PHONY: vyshim
vyshim:
@@ -77,7 +72,7 @@ vyxdp:
$(MAKE) -C $(XDP_DIR)
.PHONY: all
-all: clean interface_definitions op_mode_definitions component_versions vyshim
+all: clean interface_definitions op_mode_definitions vyshim
.PHONY: clean
clean:
@@ -89,7 +84,7 @@ clean:
.PHONY: test
test:
- set -e; python3 -m compileall -q -x '/vmware-tools/scripts/' .
+ set -e; python3 -m compileall -q -x '/vmware-tools/scripts/, /ppp/' .
PYTHONPATH=python/ python3 -m "nose" --with-xunit src --with-coverage --cover-erase --cover-xml --cover-package src/conf_mode,src/op_mode,src/completion,src/helpers,src/validators,src/tests --verbose
.PHONY: sonar
diff --git a/data/configd-include.json b/data/configd-include.json
index 3b4e2925b..6893aaa86 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -6,7 +6,6 @@
"dhcpv6_relay.py",
"dns_forwarding.py",
"dynamic_dns.py",
-"firewall_options.py",
"host_name.py",
"https.py",
"igmp_proxy.py",
@@ -69,5 +68,6 @@
"vpn_pptp.py",
"vpn_sstp.py",
"vrf.py",
+"vrf_vni.py",
"vrrp.py"
]
diff --git a/data/templates/accel-ppp/l2tp.config.tmpl b/data/templates/accel-ppp/l2tp.config.tmpl
index 070a966b7..44c96b935 100644
--- a/data/templates/accel-ppp/l2tp.config.tmpl
+++ b/data/templates/accel-ppp/l2tp.config.tmpl
@@ -150,3 +150,4 @@ vendor={{ radius_shaper_vendor }}
[cli]
tcp=127.0.0.1:2004
sessions-columns=ifname,username,calling-sid,ip,{{ ip6_column | join(',') }}{{ ',' if ip6_column }}rate-limit,type,comp,state,rx-bytes,tx-bytes,uptime
+
diff --git a/data/templates/frr/bgpd.frr.tmpl b/data/templates/frr/bgpd.frr.tmpl
index aa297876b..96815836b 100644
--- a/data/templates/frr/bgpd.frr.tmpl
+++ b/data/templates/frr/bgpd.frr.tmpl
@@ -257,6 +257,9 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none
address-family ipv6 flowspec
{% elif afi == 'l2vpn_evpn' %}
address-family l2vpn evpn
+{% if afi_config.rd is defined and afi_config.rd is not none %}
+ rd {{ afi_config.rd }}
+{% endif %}
{% endif %}
{% if afi_config.aggregate_address is defined and afi_config.aggregate_address is not none %}
{% for ip in afi_config.aggregate_address %}
@@ -294,23 +297,39 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none
{% if afi_config.advertise is defined and afi_config.advertise is not none %}
{% for adv_afi, adv_afi_config in afi_config.advertise.items() %}
{% if adv_afi_config.unicast is defined and adv_afi_config.unicast is not none %}
- advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is defined }}
+ advertise {{ adv_afi }} unicast {{ 'route-map ' ~ adv_afi_config.unicast.route_map if adv_afi_config.unicast.route_map is defined }}
{% endif %}
{% endfor %}
{% endif %}
{% if afi_config.distance is defined and afi_config.distance is not none %}
{% if afi_config.distance is defined and afi_config.distance.external is defined and afi_config.distance.internal is defined and afi_config.distance.local is defined %}
- distance bgp {{ afi_config.distance.external }} {{ afi_config.distance.internal }} {{ afi_config.distance.local }}
+ distance bgp {{ afi_config.distance.external }} {{ afi_config.distance.internal }} {{ afi_config.distance.local }}
{% endif %}
{% if afi_config.distance.prefix is defined and afi_config.distance.prefix is not none %}
{% for prefix in afi_config.distance.prefix %}
- distance {{ afi_config.distance.prefix[prefix].distance }} {{ prefix }}
+ distance {{ afi_config.distance.prefix[prefix].distance }} {{ prefix }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% if afi_config.export is defined and afi_config.export.vpn is defined %}
+ export vpn
+{% endif %}
+{% if afi_config.import is defined and afi_config.import is not none %}
+{% if afi_config.import.vpn is defined %}
+ import vpn
+{% endif %}
+{% if afi_config.import.vrf is defined and afi_config.import.vrf is not none %}
+{% for vrf in afi_config.import.vrf %}
+ import vrf {{ vrf }}
{% endfor %}
{% endif %}
{% endif %}
+{% if afi_config.label is defined and afi_config.label.vpn is defined and afi_config.label.vpn.export is defined and afi_config.label.vpn.export is not none %}
+ label vpn export {{ afi_config.label.vpn.export }}
+{% endif %}
{% if afi_config.local_install is defined and afi_config.local_install is not none %}
{% for interface in afi_config.local_install.interface %}
- local-install {{ interface }}
+ local-install {{ interface }}
{% endfor %}
{% endif %}
{% if afi_config.advertise_all_vni is defined %}
@@ -326,26 +345,47 @@ router bgp {{ local_as }} {{ 'vrf ' ~ vrf if vrf is defined and vrf is not none
advertise-svi-ip
{% endif %}
{% if afi_config.rt_auto_derive is defined %}
- autort rfc8365-compatible
+ autort rfc8365-compatible
{% endif %}
{% if afi_config.flooding is defined and afi_config.flooding.disable is defined %}
- flooding disable
+ flooding disable
{% endif %}
{% if afi_config.flooding is defined and afi_config.flooding.head_end_replication is defined %}
- flooding head-end-replication
+ flooding head-end-replication
{% endif %}
-{% if afi_config.rd is defined and afi_config.rd is not none %}
- rd {{ afi_config.rd }}
+{% if afi_config.rd is defined and afi_config.rd.vpn is defined and afi_config.rd.vpn.export is defined %}
+ rd vpn export {{ afi_config.rd.vpn.export }}
{% endif %}
{% if afi_config.route_target is defined and afi_config.route_target is not none %}
+{% if afi_config.route_target.vpn is defined and afi_config.route_target.vpn is not none %}
+{% if afi_config.route_target.vpn.both is defined and afi_config.route_target.vpn.both is not none %}
+ route-target vpn both {{ afi_config.route_target.vpn.both }}
+{% else %}
+{% if afi_config.route_target.vpn.export is defined and afi_config.route_target.vpn.export is not none %}
+ route-target vpn export {{ afi_config.route_target.vpn.export }}
+{% endif %}
+{% if afi_config.route_target.vpn.import is defined and afi_config.route_target.vpn.import is not none %}
+ route-target vpn import {{ afi_config.route_target.vpn.import }}
+{% endif %}
+{% endif %}
+{% endif %}
{% if afi_config.route_target.both is defined and afi_config.route_target.both is not none %}
- route-target both {{ afi_config.route_target.both }}
+ route-target both {{ afi_config.route_target.both }}
+{% else %}
+{% if afi_config.route_target.export is defined and afi_config.route_target.export is not none %}
+ route-target export {{ afi_config.route_target.export }}
+{% endif %}
+{% if afi_config.route_target.import is defined and afi_config.route_target.import is not none %}
+ route-target import {{ afi_config.route_target.import }}
+{% endif %}
{% endif %}
-{% if afi_config.route_target.export is defined and afi_config.route_target.export is not none %}
- route-target export {{ afi_config.route_target.export }}
+{% endif %}
+{% if afi_config.route_map is defined and afi_config.route_map.vpn is defined and afi_config.route_map.vpn is not none %}
+{% if afi_config.route_map.vpn.export is defined and afi_config.route_map.vpn.export is not none %}
+ route-map vpn export {{ afi_config.route_map.vpn.export }}
{% endif %}
-{% if afi_config.route_target.import is defined and afi_config.route_target.import is not none %}
- route-target import {{ afi_config.route_target.import }}
+{% if afi_config.route_map.vpn.import is defined and afi_config.route_map.vpn.import is not none %}
+ route-map vpn import {{ afi_config.route_map.vpn.import }}
{% endif %}
{% endif %}
{% if afi_config.vni is defined and afi_config.vni is not none %}
diff --git a/data/templates/frr/ospfv3.frr.tmpl b/data/templates/frr/ospf6d.frr.tmpl
index 0026c0d2c..0026c0d2c 100644
--- a/data/templates/frr/ospfv3.frr.tmpl
+++ b/data/templates/frr/ospf6d.frr.tmpl
diff --git a/data/templates/frr/ospf.frr.tmpl b/data/templates/frr/ospfd.frr.tmpl
index 36aa699a9..be39519c3 100644
--- a/data/templates/frr/ospf.frr.tmpl
+++ b/data/templates/frr/ospfd.frr.tmpl
@@ -14,6 +14,12 @@ interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
{% endif %}
{% endif %}
{% endif %}
+{% if iface_config.area is defined and iface_config.area is not none %}
+ ip ospf area {{ iface_config.area }}
+{% endif %}
+{% if iface_config.bandwidth is defined and iface_config.bandwidth is not none %}
+ bandwidth {{ iface_config.bandwidth }}
+{% endif %}
{% if iface_config.cost is defined and iface_config.cost is not none %}
ip ospf cost {{ iface_config.cost }}
{% endif %}
@@ -43,9 +49,6 @@ interface {{ iface }} {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
{% if iface_config.network is defined and iface_config.network is not none %}
ip ospf network {{ iface_config.network }}
{% endif %}
-{% if iface_config.bandwidth is defined and iface_config.bandwidth is not none %}
- bandwidth {{ iface_config.bandwidth }}
-{% endif %}
!
{% endfor %}
{% endif %}
@@ -155,15 +158,19 @@ router ospf {{ 'vrf ' + vrf if vrf is defined and vrf is not none }}
ospf router-id {{ parameters.router_id }}
{% endif %}
{% endif %}
-{% for interface in passive_interface if passive_interface is defined %}
+{% if passive_interface is defined and passive_interface is not none %}
+{% for interface in passive_interface %}
passive-interface {{ interface }}
-{% endfor %}
-{% for interface in passive_interface_exclude if passive_interface_exclude is defined %}
-{% if interface.startswith('vlink') %}
+{% endfor %}
+{% endif %}
+{% if passive_interface_exclude is defined and passive_interface_exclude is not none %}
+{% for interface in passive_interface_exclude if passive_interface_exclude is defined %}
+{% if interface.startswith('vlink') %}
{% set interface = interface.upper() %}
-{% endif %}
+{% endif %}
no passive-interface {{ interface }}
-{% endfor %}
+{% endfor %}
+{% endif %}
{% if redistribute is defined and redistribute is not none %}
{% for protocol, options in redistribute.items() %}
redistribute {{ protocol }} {{ 'metric ' + options.metric if options.metric is defined }} {{ 'metric-type ' + options.metric_type if options.metric_type is defined }} {{ 'route-map ' + options.route_map if options.route_map is defined }}
diff --git a/data/templates/frr/policy.frr.tmpl b/data/templates/frr/policy.frr.tmpl
index 89bd558dc..51adc1902 100644
--- a/data/templates/frr/policy.frr.tmpl
+++ b/data/templates/frr/policy.frr.tmpl
@@ -283,6 +283,9 @@ route-map {{ route_map }} {{ rule_config.action }} {{ rule }}
{% if rule_config.set.large_community is defined and rule_config.set.large_community is not none %}
set large-community {{ rule_config.set.large_community }}
{% endif %}
+{% if rule_config.set.large_comm_list_delete is defined and rule_config.set.large_comm_list_delete is not none %}
+ set large-comm-list {{ rule_config.set.large_comm_list_delete }} delete
+{% endif %}
{% if rule_config.set.local_preference is defined and rule_config.set.local_preference is not none %}
set local-preference {{ rule_config.set.local_preference }}
{% endif %}
diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2
index f10b58047..3b432b49b 100644
--- a/data/templates/frr/static_routes_macro.j2
+++ b/data/templates/frr/static_routes_macro.j2
@@ -5,7 +5,7 @@
{% if prefix_config.dhcp_interface is defined and prefix_config.dhcp_interface is not none %}
{% set next_hop = prefix_config.dhcp_interface | get_dhcp_router %}
{% if next_hop is defined and next_hop is not none %}
-{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }}
+{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }}
{% endif %}
{% endif %}
{% if prefix_config.interface is defined and prefix_config.interface is not none %}
diff --git a/data/templates/frr/vrf-vni.frr.tmpl b/data/templates/frr/vrf-vni.frr.tmpl
new file mode 100644
index 000000000..51d4ede1b
--- /dev/null
+++ b/data/templates/frr/vrf-vni.frr.tmpl
@@ -0,0 +1,7 @@
+{% if vrf is defined and vrf is not none %}
+vrf {{ vrf }}
+{% if vni is defined and vni is not none %}
+ vni {{ vni }}
+{% endif %}
+ exit-vrf
+{% endif %}
diff --git a/data/templates/frr/vrf.frr.tmpl b/data/templates/frr/vrf.frr.tmpl
deleted file mode 100644
index 299c9719e..000000000
--- a/data/templates/frr/vrf.frr.tmpl
+++ /dev/null
@@ -1,9 +0,0 @@
-{% if name is defined and name is not none %}
-{% for vrf, vrf_config in name.items() %}
-vrf {{ vrf }}
-{% if vrf_config.vni is defined and vrf_config.vni is not none %}
- vni {{ vrf_config.vni }}
-{% endif %}
- exit-vrf
-{% endfor %}
-{% endif %}
diff --git a/data/templates/https/nginx.default.tmpl b/data/templates/https/nginx.default.tmpl
index b40ddcc74..2f8aa06c2 100644
--- a/data/templates/https/nginx.default.tmpl
+++ b/data/templates/https/nginx.default.tmpl
@@ -17,7 +17,7 @@ server {
listen {{ server.port }} ssl;
listen [::]:{{ server.port }} ssl;
{% else %}
- listen {{ server.address }}:{{ server.port }} ssl;
+ listen {{ server.address | bracketize_ipv6 }}:{{ server.port }} ssl;
{% endif %}
{% for name in server.name %}
diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl
index dd29ea7d4..019f9e0d7 100644
--- a/data/templates/ipsec/swanctl/peer.tmpl
+++ b/data/templates/ipsec/swanctl/peer.tmpl
@@ -17,10 +17,10 @@
{% if ike.key_exchange is defined and ike.key_exchange == "ikev1" and ike.mode is defined and ike.mode == "aggressive" %}
aggressive = yes
{% endif %}
+ rekey_time = {{ ike.lifetime }}s
mobike = {{ "yes" if ike.mobike is not defined or ike.mobike == "enable" else "no" }}
{% if peer[0:1] == '@' %}
keyingtries = 0
- rekey_time = 0
reauth_time = 0
{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %}
keyingtries = 0
@@ -57,6 +57,7 @@
{% set vti_esp = esp_group[ peer_conf.vti.esp_group ] if peer_conf.vti.esp_group is defined else esp_group[ peer_conf.default_esp_group ] %}
peer_{{ name }}_vti {
esp_proposals = {{ vti_esp | get_esp_ike_cipher | join(',') }}
+ life_time = {{ vti_esp.lifetime }}s
local_ts = 0.0.0.0/0,::/0
remote_ts = 0.0.0.0/0,::/0
updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}"
@@ -87,6 +88,7 @@
{% set remote_suffix = '[{0}/{1}]'.format(proto, remote_port) if proto or remote_port else '' %}
peer_{{ name }}_tunnel_{{ tunnel_id }} {
esp_proposals = {{ tunnel_esp | get_esp_ike_cipher | join(',') }}
+ life_time = {{ tunnel_esp.lifetime }}s
{% if tunnel_esp.mode is not defined or tunnel_esp.mode == 'tunnel' %}
{% if tunnel_conf.local is defined and tunnel_conf.local.prefix is defined %}
{% set local_prefix = tunnel_conf.local.prefix if 'any' not in tunnel_conf.local.prefix else ['0.0.0.0/0', '::/0'] %}
diff --git a/data/templates/ipsec/swanctl/profile.tmpl b/data/templates/ipsec/swanctl/profile.tmpl
index 0a7268405..66bcaa776 100644
--- a/data/templates/ipsec/swanctl/profile.tmpl
+++ b/data/templates/ipsec/swanctl/profile.tmpl
@@ -7,7 +7,7 @@
dmvpn-{{ name }}-{{ interface }} {
proposals = {{ ike_group[profile_conf.ike_group] | get_esp_ike_cipher | join(',') }}
version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined else "0" }}
- rekey_time = {{ ike.lifetime }}s
+ life_time = {{ ike.lifetime }}s
keyingtries = 0
{% if profile_conf.authentication is defined and profile_conf.authentication.mode is defined and profile_conf.authentication.mode == 'pre-shared-secret' %}
local {
diff --git a/data/templates/ipsec/swanctl/remote_access.tmpl b/data/templates/ipsec/swanctl/remote_access.tmpl
index 456842488..f906836c6 100644
--- a/data/templates/ipsec/swanctl/remote_access.tmpl
+++ b/data/templates/ipsec/swanctl/remote_access.tmpl
@@ -10,7 +10,9 @@
send_certreq = no
rekey_time = {{ ike.lifetime }}s
keyingtries = 0
+{% if rw_conf.unique is defined and rw_conf.unique is not none %}
unique = {{ rw_conf.unique }}
+{% endif %}
{% if rw_conf.pool is defined and rw_conf.pool is not none %}
pools = {{ rw_conf.pool | join(',') }}
{% endif %}
diff --git a/data/templates/proxy-ndp/ndppd.conf.tmpl b/data/templates/ndppd/ndppd.conf.tmpl
index ccd1d37ad..502dab5b8 100644
--- a/data/templates/proxy-ndp/ndppd.conf.tmpl
+++ b/data/templates/ndppd/ndppd.conf.tmpl
@@ -6,10 +6,10 @@
# interface.
#
# For some services, such as nat66, because it runs
-# stateless, it needs to rely on NDP Proxy to respond
+# stateless, it needs to rely on NDP Proxy to respond
# to NDP requests.
#
-# When using nat66 source rules, NDP Proxy needs
+# When using nat66 source rules, NDP Proxy needs
# to be enabled
#
########################################################
@@ -21,7 +21,7 @@
{% if config.outbound_interface not in global.ndppd_interfaces %}
{% set global.ndppd_interfaces = global.ndppd_interfaces + [config.outbound_interface] %}
{% endif %}
-{% if config.translation.address is defined and config.translation.address | is_ip_network %}
+{% if config.translation is defined and config.translation.address is defined and config.translation.address | is_ip_network %}
{% set global.ndppd_prefixs = global.ndppd_prefixs + [{'interface':config.outbound_interface,'rule':config.translation.address}] %}
{% endif %}
{% endif %}
@@ -41,4 +41,4 @@ proxy {{ interface }} {
{% endif %}
{% endfor %}
}
-{% endfor %}
+{% endfor %}
diff --git a/data/templates/openvpn/server.conf.tmpl b/data/templates/openvpn/server.conf.tmpl
index d9f01310e..9b07a9ba2 100644
--- a/data/templates/openvpn/server.conf.tmpl
+++ b/data/templates/openvpn/server.conf.tmpl
@@ -74,6 +74,16 @@ topology {{ server.topology }}
{% for subnet in server.subnet %}
{% if subnet | is_ipv4 %}
server {{ subnet | address_from_cidr }} {{ subnet | netmask_from_cidr }} nopool
+{# First ip address is used as gateway. It's allows to use metrics #}
+{% if server.push_route is defined and server.push_route is not none %}
+{% for route, route_config in server.push_route.items() %}
+{% if route | is_ipv4 %}
+push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }} {{ subnet | first_host_address }} {{ route_config.metric if route_config.metric is defined else "0" }}"
+{% elif route | is_ipv6 %}
+push "route-ipv6 {{ route }}"
+{% endif %}
+{% endfor %}
+{% endif %}
{# OpenVPN assigns the first IP address to its local interface so the pool used #}
{# in net30 topology - where each client receives a /30 must start from the second subnet #}
{% if server.topology is defined and server.topology == 'net30' %}
@@ -106,15 +116,6 @@ management /run/openvpn/openvpn-mgmt-intf unix
ccd-exclusive
{% endif %}
-{% if server.push_route is defined and server.push_route is not none %}
-{% for route in server.push_route %}
-{% if route | is_ipv4 %}
-push "route {{ route | address_from_cidr }} {{ route | netmask_from_cidr }}"
-{% elif route | is_ipv6 %}
-push "route-ipv6 {{ route }}"
-{% endif %}
-{% endfor %}
-{% endif %}
{% if server.name_server is defined and server.name_server is not none %}
{% for nameserver in server.name_server %}
{% if nameserver | is_ipv4 %}
diff --git a/data/templates/pppoe/ipv6-up.script.tmpl b/data/templates/pppoe/ipv6-up.script.tmpl
index 7e1bc33b4..da73cb4d5 100644
--- a/data/templates/pppoe/ipv6-up.script.tmpl
+++ b/data/templates/pppoe/ipv6-up.script.tmpl
@@ -7,43 +7,6 @@ if [ "$6" != "{{ ifname }}" ]; then
exit
fi
-{% if ipv6 is defined and ipv6.address is defined and ipv6.address.autoconf is defined %}
-# add some info to syslog
-DIALER_PID=$(cat /var/run/{{ ifname }}.pid)
-logger -t pppd[$DIALER_PID] "executing $0"
-logger -t pppd[$DIALER_PID] "configuring interface {{ ifname }} via {{ source_interface }}"
-
-# Configure interface-specific Host/Router behaviour.
-# Note: It is recommended to have the same setting on all interfaces; mixed
-# router/host scenarios are rather uncommon. Possible values are:
-#
-# 0 Forwarding disabled
-# 1 Forwarding enabled
-#
-echo 1 > /proc/sys/net/ipv6/conf/{{ ifname }}/forwarding
-
-# Accept Router Advertisements; autoconfigure using them.
-#
-# It also determines whether or not to transmit Router
-# Solicitations. If and only if the functional setting is to
-# accept Router Advertisements, Router Solicitations will be
-# transmitted. Possible values are:
-#
-# 0 Do not accept Router Advertisements.
-# 1 Accept Router Advertisements if forwarding is disabled.
-# 2 Overrule forwarding behaviour. Accept Router Advertisements
-# even if forwarding is enabled.
-#
-echo 2 > /proc/sys/net/ipv6/conf/{{ ifname }}/accept_ra
-
-# Autoconfigure addresses using Prefix Information in Router Advertisements.
-echo 1 > /proc/sys/net/ipv6/conf/{{ ifname }}/autoconf
-{% endif %}
-
-{% if dhcpv6_options is defined and dhcpv6_options.pd is defined %}
-# Start wide dhcpv6 client
-systemctl restart dhcp6c@{{ ifname }}.service
-{% endif %}
{% if default_route != 'none' %}
# See https://phabricator.vyos.net/T2248 & T2220. Determine if we are enslaved
diff --git a/data/templates/pppoe/peer.tmpl b/data/templates/pppoe/peer.tmpl
index 0f78f9384..928ed1238 100644
--- a/data/templates/pppoe/peer.tmpl
+++ b/data/templates/pppoe/peer.tmpl
@@ -1,8 +1,5 @@
### Autogenerated by interfaces-pppoe.py ###
-
-{% if description %}
-# {{ description }}
-{% endif %}
+{{ '# ' ~ description if description is defined else '' }}
# Require peer to provide the local IP address if it is not
# specified explicitly in the config file.
@@ -30,15 +27,21 @@ connect /bin/true
noauth
# Don't try to proxy ARP for the remote endpoint. User can set proxy
-# arp entries up manually if they wish. More importantly, having
+# arp entries up manually if they wish. More importantly, having
# the "proxyarp" parameter set disables the "defaultroute" option.
noproxyarp
# Unlimited connection attempts
maxfail 0
-plugin rp-pppoe.so
-{{ source_interface }}
+plugin rp-pppoe.so {{ source_interface }}
+{% if access_concentrator is defined and access_concentrator is not none %}
+rp_pppoe_ac '{{ access_concentrator }}'
+{% endif %}
+{% if service_name is defined and service_name is not none %}
+rp_pppoe_service '{{ service_name }}'
+{% endif %}
+
persist
ifname {{ ifname }}
ipparam {{ ifname }}
@@ -54,14 +57,9 @@ mru {{ mtu }}
{{ "usepeerdns" if no_peer_dns is not defined }}
{% if ipv6 is defined %}
-+ipv6
-{% if ipv6.address is defined and ipv6.address.autoconf is defined %}
-ipv6cp-use-ipaddr
-{% endif %}
-{% endif %}
-
-{% if service_name is defined %}
-rp_pppoe_service "{{ service_name }}"
++ipv6 {{ 'ipv6cp-use-ipaddr' if ipv6.address is defined and ipv6.address.autoconf is defined }}
+{% else %}
+noipv6
{% endif %}
{% if connect_on_demand is defined %}
@@ -71,8 +69,14 @@ demand
# passed to the ip-up.d/ip-down.s scripts which is required for VRF support.
{% if 'auto' in default_route %}
defaultroute
+{{ 'defaultroute6' if ipv6 is defined }}
{% elif 'force' in default_route %}
defaultroute
replacedefaultroute
+{{ 'defaultroute6' if ipv6 is defined }}
{% endif %}
+{% else %}
+nodefaultroute
+noreplacedefaultroute
+{{ 'nodefaultroute6' if ipv6 is defined }}
{% endif %}
diff --git a/debian/control b/debian/control
index c5cbeb7d4..f3a26e73e 100644
--- a/debian/control
+++ b/debian/control
@@ -156,6 +156,7 @@ Depends:
traceroute,
tuned,
udp-broadcast-relay,
+ uidmap,
usb-modeswitch,
usbutils,
vyatta-bash,
diff --git a/debian/rules b/debian/rules
index 70d39c481..c7a7138e1 100755
--- a/debian/rules
+++ b/debian/rules
@@ -18,6 +18,10 @@ DEB_TARGET_ARCH := $(shell dpkg-architecture -qDEB_TARGET_ARCH)
%:
dh $@ --with python3, --with quilt
+# Skip dh_strip_nondeterminism - this is very time consuming
+# and we have no non deterministic output (yet)
+override_dh_strip_nondeterminism:
+
override_dh_gencontrol:
dh_gencontrol -- -v$(shell (git describe --tags --long --match 'vyos/*' --dirty 2>/dev/null || echo 0.0-no.git.tag) | sed -E 's%vyos/%%' | sed -E 's%-dirty%+dirty%')
diff --git a/debian/vyos-1x.install b/debian/vyos-1x.install
index 2ed25755f..d332e0d36 100644
--- a/debian/vyos-1x.install
+++ b/debian/vyos-1x.install
@@ -3,6 +3,7 @@ etc/dhcp
etc/ipsec.d
etc/netplug
etc/opennhrp
+etc/ppp
etc/rsyslog.d
etc/securetty
etc/security
@@ -10,6 +11,7 @@ etc/sudoers.d
etc/systemd
etc/sysctl.d
etc/udev
+etc/update-motd.d
etc/vyos
lib/
opt/
diff --git a/interface-definitions/bcast-relay.xml.in b/interface-definitions/bcast-relay.xml.in
index 1b354d885..c7948ded1 100644
--- a/interface-definitions/bcast-relay.xml.in
+++ b/interface-definitions/bcast-relay.xml.in
@@ -49,18 +49,7 @@
<multi/>
</properties>
</leafNode>
- <leafNode name="port">
- <properties>
- <help>Destination or source port to listen and retransmit on [REQUIRED]</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>UDP port to listen on</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/port-number.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/containers.xml.in b/interface-definitions/containers.xml.in
index 124b1f65e..d990e41a3 100644
--- a/interface-definitions/containers.xml.in
+++ b/interface-definitions/containers.xml.in
@@ -9,6 +9,10 @@
<tagNode name="name">
<properties>
<help>Container name</help>
+ <constraint>
+ <regex>^[-a-zA-Z0-9]+$</regex>
+ </constraint>
+ <constraintErrorMessage>Container name must be alphanumeric and can contain hyphens</constraintErrorMessage>
</properties>
<children>
<leafNode name="allow-host-networks">
@@ -17,14 +21,15 @@
<valueless/>
</properties>
</leafNode>
- <leafNode name="description">
- <properties>
- <help>Container description</help>
- </properties>
- </leafNode>
+ #include <include/generic-description.xml.i>
+ #include <include/generic-disable-node.xml.i>
<tagNode name="environment">
<properties>
<help>Add custom environment variables</help>
+ <constraint>
+ <regex>^[-_a-zA-Z0-9]+$</regex>
+ </constraint>
+ <constraintErrorMessage>Environment variable name must be alphanumeric and can contain hyphen and underscores</constraintErrorMessage>
</properties>
<children>
<leafNode name="value">
@@ -43,6 +48,24 @@
<help>Image name in the hub-registry</help>
</properties>
</leafNode>
+ <leafNode name="memory">
+ <properties>
+ <help>Constrain the memory available to a container (default: 512MB)</help>
+ <valueHelp>
+ <format>u32:0</format>
+ <description>Unlimited</description>
+ </valueHelp>
+ <valueHelp>
+ <format>u32:1-16384</format>
+ <description>Container memory in megabytes (MB)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16384"/>
+ </constraint>
+ <constraintErrorMessage>Container memory must be in range 0 to 16384 MB</constraintErrorMessage>
+ </properties>
+ <defaultValue>512</defaultValue>
+ </leafNode>
<tagNode name="network">
<properties>
<help>Attach user defined network to container</help>
@@ -56,7 +79,7 @@
<help>Set IPv4 static address to container (optional)</help>
<valueHelp>
<format>ipv4</format>
- <description>IPv4 address (x.x.x.1 reserved)</description>
+ <description>IPv4 address</description>
</valueHelp>
<constraint>
<validator name="ipv4-address"/>
@@ -115,6 +138,30 @@
</leafNode>
</children>
</tagNode>
+ <leafNode name="restart">
+ <properties>
+ <help>Mount a volume into the container</help>
+ <completionHelp>
+ <list>no on-failure always</list>
+ </completionHelp>
+ <valueHelp>
+ <format>no</format>
+ <description>Do not restart containers on exit</description>
+ </valueHelp>
+ <valueHelp>
+ <format>on-failure</format>
+ <description>Restart containers when they exit with a non-zero exit code, retrying indefinitely (default)</description>
+ </valueHelp>
+ <valueHelp>
+ <format>always</format>
+ <description>Restart containers when they exit, regardless of status, retrying indefinitely</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(no|on-failure|always)$</regex>
+ </constraint>
+ </properties>
+ <defaultValue>on-failure</defaultValue>
+ </leafNode>
<tagNode name="volume">
<properties>
<help>Mount a volume into the container</help>
diff --git a/interface-definitions/firewall-options.xml.in b/interface-definitions/firewall-options.xml.in
deleted file mode 100644
index 8d9225a9a..000000000
--- a/interface-definitions/firewall-options.xml.in
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0"?>
-<interfaceDefinition>
- <node name="firewall">
- <children>
- <node name="options">
- <properties>
- <help>Firewall options/Packet manipulation</help>
- <priority>990</priority>
- </properties>
- <children>
- <tagNode name="interface" owner="${vyos_conf_scripts_dir}/firewall_options.py">
- <properties>
- <help>Interface clamping options</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py</script>
- </completionHelp>
- </properties>
- <children>
- #include <include/generic-disable-node.xml.i>
- <leafNode name="adjust-mss">
- <properties>
- <help>Adjust MSS for IPv4 transit packets</help>
- <valueHelp>
- <format>500-1460</format>
- <description>TCP Maximum segment size in bytes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 500-1460"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="adjust-mss6">
- <properties>
- <help>Adjust MSS for IPv6 transit packets</help>
- <valueHelp>
- <format>1280-1492</format>
- <description>TCP Maximum segment size in bytes</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1280-1492"/>
- </constraint>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- </children>
- </node>
- </children>
- </node>
-</interfaceDefinition>
diff --git a/interface-definitions/https.xml.in b/interface-definitions/https.xml.in
index b65a89b56..b0532e249 100644
--- a/interface-definitions/https.xml.in
+++ b/interface-definitions/https.xml.in
@@ -1,7 +1,6 @@
<?xml version="1.0"?>
<!-- HTTPS configuration -->
<interfaceDefinition>
- <syntaxVersion component='https' version='3'></syntaxVersion>
<node name="service">
<children>
<node name="https" owner="${vyos_conf_scripts_dir}/https.py">
diff --git a/interface-definitions/include/bgp/afi-export-import.xml.i b/interface-definitions/include/bgp/afi-export-import.xml.i
new file mode 100644
index 000000000..86817cdb3
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-export-import.xml.i
@@ -0,0 +1,41 @@
+<!-- include start from bgp/afi-export-import.xml.i -->
+<node name="export">
+ <properties>
+ <help>Export routes from this address-family</help>
+ </properties>
+ <children>
+ <leafNode name="vpn">
+ <properties>
+ <help>to/from default instance VPN RIB</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<node name="import">
+ <properties>
+ <help>Import routes to this address-family</help>
+ </properties>
+ <children>
+ <leafNode name="vpn">
+ <properties>
+ <help>to/from default instance VPN RIB</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="vrf">
+ <properties>
+ <help>VRF to import from</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>VRF instance name</description>
+ </valueHelp>
+ <completionHelp>
+ <path>vrf name</path>
+ </completionHelp>
+ <multi/>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-l2vpn-common.xml.i b/interface-definitions/include/bgp/afi-l2vpn-common.xml.i
index aaa69e6c8..8deb189ab 100644
--- a/interface-definitions/include/bgp/afi-l2vpn-common.xml.i
+++ b/interface-definitions/include/bgp/afi-l2vpn-common.xml.i
@@ -12,5 +12,47 @@
</properties>
</leafNode>
#include <include/bgp/route-distinguisher.xml.i>
-#include <include/bgp/route-target.xml.i>
+<node name="route-target">
+ <properties>
+ <help>Route Target</help>
+ </properties>
+ <children>
+ <leafNode name="both">
+ <properties>
+ <help>Route Target both import and export</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-route-target" argument="--single"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="import">
+ <properties>
+ <help>Route Target import</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-route-target" argument="--single"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="export">
+ <properties>
+ <help>Route Target export</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-route-target" argument="--single"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-label.xml.i b/interface-definitions/include/bgp/afi-label.xml.i
new file mode 100644
index 000000000..f7a1f609f
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-label.xml.i
@@ -0,0 +1,36 @@
+<!-- include start from bgp/afi-label.xml.i -->
+<node name="label">
+ <properties>
+ <help>Label value for VRF</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Between current address-family and VPN</help>
+ </properties>
+ <children>
+ <leafNode name="export">
+ <properties>
+ <help>For routes leaked from current address-family to VPN</help>
+ <completionHelp>
+ <list>auto</list>
+ </completionHelp>
+ <valueHelp>
+ <format>auto</format>
+ <description>Automatically assign a label</description>
+ </valueHelp>
+ <valueHelp>
+ <format>u32:0-1048575</format>
+ <description>Label Value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-1048575"/>
+ <regex>^(auto)$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-path-limit.xml.i b/interface-definitions/include/bgp/afi-path-limit.xml.i
new file mode 100644
index 000000000..e3d630a57
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-path-limit.xml.i
@@ -0,0 +1,14 @@
+<!-- include start from bgp/afi-path-limit.xml.i -->
+<leafNode name="path-limit">
+ <properties>
+ <help>AS-path hopcount limit</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>AS path hop count limit</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-rd.xml.i b/interface-definitions/include/bgp/afi-rd.xml.i
new file mode 100644
index 000000000..c4d29268c
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-rd.xml.i
@@ -0,0 +1,28 @@
+<!-- include start from bgp/afi-rd.xml.i -->
+<node name="rd">
+ <properties>
+ <help>Specify route distinguisher</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Between current address-family and VPN</help>
+ </properties>
+ <children>
+ <leafNode name="export">
+ <properties>
+ <help>For routes leaked from current address-family to VPN</help>
+ <valueHelp>
+ <format>ASN:NN_OR_IP-ADDRESS:NN</format>
+ <description>Route Distinguisher, (x.x.x.x:yyy|xxxx:yyyy)</description>
+ </valueHelp>
+ <constraint>
+ <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-route-map-export-import.xml.i b/interface-definitions/include/bgp/afi-route-map-export-import.xml.i
new file mode 100644
index 000000000..eae10d312
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-route-map-export-import.xml.i
@@ -0,0 +1,34 @@
+<!-- include start from bgp/afi-route-map.xml.i -->
+<leafNode name="export">
+ <properties>
+ <help>Route-map to filter outgoing route updates</help>
+ <completionHelp>
+ <path>policy route-map</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Route map name</description>
+ </valueHelp>
+ <constraint>
+ <regex>^[-_a-zA-Z0-9.]+$</regex>
+ </constraint>
+ <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
+ </properties>
+</leafNode>
+<leafNode name="import">
+ <properties>
+ <help>Route-map to filter incoming route updates</help>
+ <completionHelp>
+ <path>policy route-map</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Route map name</description>
+ </valueHelp>
+ <constraint>
+ <regex>^[-_a-zA-Z0-9.]+$</regex>
+ </constraint>
+ <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-route-map-vpn.xml.i b/interface-definitions/include/bgp/afi-route-map-vpn.xml.i
new file mode 100644
index 000000000..e6be113c5
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-route-map-vpn.xml.i
@@ -0,0 +1,17 @@
+<!-- include start from bgp/afi-route-map-vpn.xml.i -->
+<node name="route-map">
+ <properties>
+ <help>Route-map to filter route updates to/from this peer</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Between current address-family and VPN</help>
+ </properties>
+ <children>
+ #include <include/bgp/afi-route-map-export-import.xml.i>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-route-map.xml.i b/interface-definitions/include/bgp/afi-route-map.xml.i
index 24a5ddd12..0b6178176 100644
--- a/interface-definitions/include/bgp/afi-route-map.xml.i
+++ b/interface-definitions/include/bgp/afi-route-map.xml.i
@@ -4,38 +4,7 @@
<help>Route-map to filter route updates to/from this peer</help>
</properties>
<children>
- <leafNode name="export">
- <properties>
- <help>Route-map to filter outgoing route updates</help>
- <completionHelp>
- <path>policy route-map</path>
- </completionHelp>
- <valueHelp>
- <format>txt</format>
- <description>Route map name</description>
- </valueHelp>
- <constraint>
- <regex>^[-_a-zA-Z0-9.]+$</regex>
- </constraint>
- <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="import">
- <properties>
- <help>Route-map to filter incoming route updates</help>
- <completionHelp>
- <path>policy route-map</path>
- </completionHelp>
- <valueHelp>
- <format>txt</format>
- <description>Route map name</description>
- </valueHelp>
- <constraint>
- <regex>^[-_a-zA-Z0-9.]+$</regex>
- </constraint>
- <constraintErrorMessage>Name of route-map can only contain alpha-numeric letters, hyphen and underscores</constraintErrorMessage>
- </properties>
- </leafNode>
+ #include <include/bgp/afi-route-map-export-import.xml.i>
</children>
</node>
<!-- include end -->
diff --git a/interface-definitions/include/bgp/afi-route-target-vpn.xml.i b/interface-definitions/include/bgp/afi-route-target-vpn.xml.i
new file mode 100644
index 000000000..1dc184a02
--- /dev/null
+++ b/interface-definitions/include/bgp/afi-route-target-vpn.xml.i
@@ -0,0 +1,52 @@
+<!-- include start from bgp/route-target-both.xml.i -->
+<node name="route-target">
+ <properties>
+ <help>Specify route distinguisher</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Between current address-family and VPN</help>
+ </properties>
+ <children>
+ <leafNode name="both">
+ <properties>
+ <help>Route Target both import and export</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-route-target" argument="--multi"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="import">
+ <properties>
+ <help>Route Target import</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-route-target" argument="--multi"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="export">
+ <properties>
+ <help>Route Target export</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-route-target" argument="--multi"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index 552e85aa4..2b22bac7d 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -93,6 +93,9 @@
</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>
@@ -114,7 +117,9 @@
#include <include/route-map.xml.i>
</children>
</tagNode>
- #include <include/bgp/afi-maximum-paths.xml.i>
+ #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>
@@ -478,6 +483,9 @@
</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>
@@ -490,22 +498,13 @@
</constraint>
</properties>
<children>
- <leafNode name="path-limit">
- <properties>
- <help>AS-path hopcount limit</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>AS path hop count limit</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/bgp/afi-path-limit.xml.i>
#include <include/route-map.xml.i>
</children>
</tagNode>
- #include <include/bgp/afi-maximum-paths.xml.i>
+ #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>
@@ -661,18 +660,7 @@
</constraint>
</properties>
<children>
- <leafNode name="path-limit">
- <properties>
- <help>AS-path hopcount limit</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>AS path hop count limit</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/bgp/afi-path-limit.xml.i>
#include <include/route-map.xml.i>
</children>
</tagNode>
diff --git a/interface-definitions/include/bgp/route-distinguisher.xml.i b/interface-definitions/include/bgp/route-distinguisher.xml.i
index fdfbe7076..6d0aa3ef1 100644
--- a/interface-definitions/include/bgp/route-distinguisher.xml.i
+++ b/interface-definitions/include/bgp/route-distinguisher.xml.i
@@ -3,7 +3,7 @@
<properties>
<help>Route Distinguisher</help>
<valueHelp>
- <format>txt</format>
+ <format>ASN:NN_OR_IP-ADDRESS:NN</format>
<description>Route Distinguisher, (x.x.x.x:yyy|xxxx:yyyy)</description>
</valueHelp>
<constraint>
diff --git a/interface-definitions/include/bgp/route-target.xml.i b/interface-definitions/include/bgp/route-target.xml.i
deleted file mode 100644
index 674b6db15..000000000
--- a/interface-definitions/include/bgp/route-target.xml.i
+++ /dev/null
@@ -1,45 +0,0 @@
-<!-- include start from bgp/route-target.xml.i -->
-<node name="route-target">
- <properties>
- <help>Route Target</help>
- </properties>
- <children>
- <leafNode name="both">
- <properties>
- <help>Route Target both import and export</help>
- <valueHelp>
- <format>txt</format>
- <description>Route target (x.x.x.x:yyy|xxxx:yyyy)</description>
- </valueHelp>
- <constraint>
- <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="export">
- <properties>
- <help>Route Target export</help>
- <valueHelp>
- <format>txt</format>
- <description>Route target (x.x.x.x:yyy|xxxx:yyyy)</description>
- </valueHelp>
- <constraint>
- <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="import">
- <properties>
- <help>Route Target import</help>
- <valueHelp>
- <format>txt</format>
- <description>Route target (x.x.x.x:yyy|xxxx:yyyy)</description>
- </valueHelp>
- <constraint>
- <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex>
- </constraint>
- </properties>
- </leafNode>
- </children>
-</node>
-<!-- include end -->
diff --git a/interface-definitions/include/conntrack-module-disable.xml.i b/interface-definitions/include/conntrack-module-disable.xml.i
deleted file mode 100644
index f891225e0..000000000
--- a/interface-definitions/include/conntrack-module-disable.xml.i
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- include start from conntrack-module-disable.xml.i -->
-<leafNode name="disable">
- <properties>
- <help>Disable connection tracking helper</help>
- <valueless/>
- </properties>
-</leafNode>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/adjust-mss.xml.i b/interface-definitions/include/interface/adjust-mss.xml.i
new file mode 100644
index 000000000..57019f02c
--- /dev/null
+++ b/interface-definitions/include/interface/adjust-mss.xml.i
@@ -0,0 +1,23 @@
+<!-- include start from interface/adjust-mss.xml.i -->
+<!-- https://datatracker.ietf.org/doc/html/rfc6691 -->
+<leafNode name="adjust-mss">
+ <properties>
+ <help>Adjust TCP MSS value</help>
+ <completionHelp>
+ <list>clamp-mss-to-pmtu</list>
+ </completionHelp>
+ <valueHelp>
+ <format>clamp-mss-to-pmtu</format>
+ <description>Automatically sets the MSS to the proper value</description>
+ </valueHelp>
+ <valueHelp>
+ <format>u32:500-65535</format>
+ <description>TCP Maximum segment size in bytes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 500-65535"/>
+ <regex>^(clamp-mss-to-pmtu)$</regex>
+ </constraint>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-arp-cache-timeout.xml.i b/interface-definitions/include/interface/arp-cache-timeout.xml.i
index b269fecd8..3fb64f1ff 100644
--- a/interface-definitions/include/interface/interface-arp-cache-timeout.xml.i
+++ b/interface-definitions/include/interface/arp-cache-timeout.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-arp-cache-timeout.xml.i -->
+<!-- include start from interface/arp-cache-timeout.xml.i -->
<leafNode name="arp-cache-timeout">
<properties>
<help>ARP cache entry timeout in seconds</help>
diff --git a/interface-definitions/include/interface/interface-description.xml.i b/interface-definitions/include/interface/description.xml.i
index d618b50d2..8579cf7d1 100644
--- a/interface-definitions/include/interface/interface-description.xml.i
+++ b/interface-definitions/include/interface/description.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-description.xml.i -->
+<!-- include start from interface/description.xml.i -->
<leafNode name="description">
<properties>
<help>Interface specific description</help>
diff --git a/interface-definitions/include/interface/interface-dial-on-demand.xml.i b/interface-definitions/include/interface/dial-on-demand.xml.i
index 66edd9678..30e8c7e97 100644
--- a/interface-definitions/include/interface/interface-dial-on-demand.xml.i
+++ b/interface-definitions/include/interface/dial-on-demand.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-dial-on-demand.xml.i -->
+<!-- include start from interface/dial-on-demand.xml.i -->
<leafNode name="connect-on-demand">
<properties>
<help>Establishment connection automatically when traffic is sent</help>
diff --git a/interface-definitions/include/interface/interface-disable-arp-filter.xml.i b/interface-definitions/include/interface/disable-arp-filter.xml.i
index 49cddaf76..a69455d58 100644
--- a/interface-definitions/include/interface/interface-disable-arp-filter.xml.i
+++ b/interface-definitions/include/interface/disable-arp-filter.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-disable-arp-filter.xml.i -->
+<!-- include start from interface/disable-arp-filter.xml.i -->
<leafNode name="disable-arp-filter">
<properties>
<help>Disable ARP filter on this interface</help>
diff --git a/interface-definitions/include/interface/disable-forwarding.xml.i b/interface-definitions/include/interface/disable-forwarding.xml.i
new file mode 100644
index 000000000..45382ec95
--- /dev/null
+++ b/interface-definitions/include/interface/disable-forwarding.xml.i
@@ -0,0 +1,8 @@
+<!-- include start from interface/disable-forwarding.xml.i -->
+<leafNode name="disable-forwarding">
+ <properties>
+ <help>Disable IP forwarding on this interface</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-disable-link-detect.xml.i b/interface-definitions/include/interface/disable-link-detect.xml.i
index c528885b2..b101ec292 100644
--- a/interface-definitions/include/interface/interface-disable-link-detect.xml.i
+++ b/interface-definitions/include/interface/disable-link-detect.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-disable-link-detect.xml.i -->
+<!-- include start from interface/disable-link-detect.xml.i -->
<leafNode name="disable-link-detect">
<properties>
<help>Ignore link state changes</help>
diff --git a/interface-definitions/include/interface/interface-disable.xml.i b/interface-definitions/include/interface/disable.xml.i
index d90e6395b..b76bd3f53 100644
--- a/interface-definitions/include/interface/interface-disable.xml.i
+++ b/interface-definitions/include/interface/disable.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-disable.xml.i -->
+<!-- include start from interface/disable.xml.i -->
<leafNode name="disable">
<properties>
<help>Administratively disable interface</help>
diff --git a/interface-definitions/include/interface/interface-eapol.xml.i b/interface-definitions/include/interface/eapol.xml.i
index 270ec5b13..c4cdeae0c 100644
--- a/interface-definitions/include/interface/interface-eapol.xml.i
+++ b/interface-definitions/include/interface/eapol.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-eapol.xml.i -->
+<!-- include start from interface/eapol.xml.i -->
<node name="eapol">
<properties>
<help>Extensible Authentication Protocol over Local Area Network</help>
diff --git a/interface-definitions/include/interface/interface-enable-arp-accept.xml.i b/interface-definitions/include/interface/enable-arp-accept.xml.i
index 7c5d51857..90f6bc3db 100644
--- a/interface-definitions/include/interface/interface-enable-arp-accept.xml.i
+++ b/interface-definitions/include/interface/enable-arp-accept.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-enable-arp-accept.xml.i -->
+<!-- include start from interface/enable-arp-accept.xml.i -->
<leafNode name="enable-arp-accept">
<properties>
<help>Enable ARP accept on this interface</help>
diff --git a/interface-definitions/include/interface/interface-enable-arp-announce.xml.i b/interface-definitions/include/interface/enable-arp-announce.xml.i
index f44599c54..cf02fce0b 100644
--- a/interface-definitions/include/interface/interface-enable-arp-announce.xml.i
+++ b/interface-definitions/include/interface/enable-arp-announce.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-enable-arp-announce.xml.i -->
+<!-- include start from interface/enable-arp-announce.xml.i -->
<leafNode name="enable-arp-announce">
<properties>
<help>Enable ARP announce on this interface</help>
diff --git a/interface-definitions/include/interface/interface-enable-arp-ignore.xml.i b/interface-definitions/include/interface/enable-arp-ignore.xml.i
index 3ea39613c..5bb444f35 100644
--- a/interface-definitions/include/interface/interface-enable-arp-ignore.xml.i
+++ b/interface-definitions/include/interface/enable-arp-ignore.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-enable-arp-ignore.xml.i -->
+<!-- include start from interface/enable-arp-ignore.xml.i -->
<leafNode name="enable-arp-ignore">
<properties>
<help>Enable ARP ignore on this interface</help>
diff --git a/interface-definitions/include/interface/interface-enable-proxy-arp.xml.i b/interface-definitions/include/interface/enable-proxy-arp.xml.i
index dbdeeb7a7..27e497f84 100644
--- a/interface-definitions/include/interface/interface-enable-proxy-arp.xml.i
+++ b/interface-definitions/include/interface/enable-proxy-arp.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-enable-proxy-arp.xml.i -->
+<!-- include start from interface/enable-proxy-arp.xml.i -->
<leafNode name="enable-proxy-arp">
<properties>
<help>Enable proxy-arp on this interface</help>
diff --git a/interface-definitions/include/interface/interface-hw-id.xml.i b/interface-definitions/include/interface/hw-id.xml.i
index 989cd9cb7..a3a1eec7c 100644
--- a/interface-definitions/include/interface/interface-hw-id.xml.i
+++ b/interface-definitions/include/interface/hw-id.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-hw-id.xml.i -->
+<!-- include start from interface/hw-id.xml.i -->
<leafNode name="hw-id">
<properties>
<help>Associate Ethernet Interface with given Media Access Control (MAC) address</help>
diff --git a/interface-definitions/include/interface/interface-disable-forwarding.xml.i b/interface-definitions/include/interface/interface-disable-forwarding.xml.i
deleted file mode 100644
index cb6ef0475..000000000
--- a/interface-definitions/include/interface/interface-disable-forwarding.xml.i
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- include start from interface/interface-disable-forwarding.xml.i -->
-<leafNode name="disable-forwarding">
- <properties>
- <help>Disable IPv4 forwarding on this interface</help>
- <valueless/>
- </properties>
-</leafNode>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-ipv4-options.xml.i b/interface-definitions/include/interface/interface-ipv4-options.xml.i
deleted file mode 100644
index c2d0677b7..000000000
--- a/interface-definitions/include/interface/interface-ipv4-options.xml.i
+++ /dev/null
@@ -1,18 +0,0 @@
-<!-- include start from interface/interface-ipv4-options.xml.i -->
-<node name="ip">
- <properties>
- <help>IPv4 routing parameters</help>
- </properties>
- <children>
- #include <include/interface/interface-arp-cache-timeout.xml.i>
- #include <include/interface/interface-disable-arp-filter.xml.i>
- #include <include/interface/interface-disable-forwarding.xml.i>
- #include <include/interface/interface-enable-arp-accept.xml.i>
- #include <include/interface/interface-enable-arp-announce.xml.i>
- #include <include/interface/interface-enable-arp-ignore.xml.i>
- #include <include/interface/interface-enable-proxy-arp.xml.i>
- #include <include/interface/interface-proxy-arp-pvlan.xml.i>
- #include <include/interface/interface-source-validation.xml.i>
- </children>
-</node>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/ipv4-options.xml.i b/interface-definitions/include/interface/ipv4-options.xml.i
new file mode 100644
index 000000000..bca1229c6
--- /dev/null
+++ b/interface-definitions/include/interface/ipv4-options.xml.i
@@ -0,0 +1,19 @@
+<!-- include start from interface/ipv4-options.xml.i -->
+<node name="ip">
+ <properties>
+ <help>IPv4 routing parameters</help>
+ </properties>
+ <children>
+ #include <include/interface/adjust-mss.xml.i>
+ #include <include/interface/arp-cache-timeout.xml.i>
+ #include <include/interface/disable-arp-filter.xml.i>
+ #include <include/interface/disable-forwarding.xml.i>
+ #include <include/interface/enable-arp-accept.xml.i>
+ #include <include/interface/enable-arp-announce.xml.i>
+ #include <include/interface/enable-arp-ignore.xml.i>
+ #include <include/interface/enable-proxy-arp.xml.i>
+ #include <include/interface/proxy-arp-pvlan.xml.i>
+ #include <include/interface/source-validation.xml.i>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/interface/ipv6-disable-forwarding.xml.i b/interface-definitions/include/interface/ipv6-disable-forwarding.xml.i
deleted file mode 100644
index 4adb77d1b..000000000
--- a/interface-definitions/include/interface/ipv6-disable-forwarding.xml.i
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- include start from interface/ipv6-disable-forwarding.xml.i -->
-<leafNode name="disable-forwarding">
- <properties>
- <help>Disable IPv6 forwarding on this interface</help>
- <valueless/>
- </properties>
-</leafNode>
-<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-ipv6-options.xml.i b/interface-definitions/include/interface/ipv6-options.xml.i
index dcd5a8710..f740ce0c2 100644
--- a/interface-definitions/include/interface/interface-ipv6-options.xml.i
+++ b/interface-definitions/include/interface/ipv6-options.xml.i
@@ -1,11 +1,12 @@
-<!-- include start from interface/interface-ipv6-options.xml.i -->
+<!-- include start from interface/ipv6-options.xml.i -->
<node name="ipv6">
<properties>
<help>IPv6 routing parameters</help>
</properties>
<children>
+ #include <include/interface/adjust-mss.xml.i>
+ #include <include/interface/disable-forwarding.xml.i>
#include <include/interface/ipv6-address.xml.i>
- #include <include/interface/ipv6-disable-forwarding.xml.i>
#include <include/interface/ipv6-dup-addr-detect-transmits.xml.i>
</children>
</node>
diff --git a/interface-definitions/include/interface/interface-mac.xml.i b/interface-definitions/include/interface/mac.xml.i
index d7107ad23..705330dce 100644
--- a/interface-definitions/include/interface/interface-mac.xml.i
+++ b/interface-definitions/include/interface/mac.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mac.xml.i -->
+<!-- include start from interface/mac.xml.i -->
<leafNode name="mac">
<properties>
<help>Media Access Control (MAC) address</help>
diff --git a/interface-definitions/include/interface/interface-mirror.xml.i b/interface-definitions/include/interface/mirror.xml.i
index b3b45fb43..2959551f0 100644
--- a/interface-definitions/include/interface/interface-mirror.xml.i
+++ b/interface-definitions/include/interface/mirror.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mirror.xml.i -->
+<!-- include start from interface/mirror.xml.i -->
<node name="mirror">
<properties>
<help>Incoming/outgoing packet mirroring destination</help>
diff --git a/interface-definitions/include/interface/interface-mtu-1200-16000.xml.i b/interface-definitions/include/interface/mtu-1200-16000.xml.i
index 3241ba912..ccd986d55 100644
--- a/interface-definitions/include/interface/interface-mtu-1200-16000.xml.i
+++ b/interface-definitions/include/interface/mtu-1200-16000.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mtu-1200-16000.xml.i -->
+<!-- include start from interface/mtu-1200-16000.xml.i -->
<leafNode name="mtu">
<properties>
<help>Maximum Transmission Unit (MTU)</help>
diff --git a/interface-definitions/include/interface/interface-mtu-1450-16000.xml.i b/interface-definitions/include/interface/mtu-1450-16000.xml.i
index 0a35bbbaa..2dc3a2029 100644
--- a/interface-definitions/include/interface/interface-mtu-1450-16000.xml.i
+++ b/interface-definitions/include/interface/mtu-1450-16000.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mtu-1450-16000.xml.i -->
+<!-- include start from interface/mtu-1450-16000.xml.i -->
<leafNode name="mtu">
<properties>
<help>Maximum Transmission Unit (MTU)</help>
diff --git a/interface-definitions/include/interface/interface-mtu-64-8024.xml.i b/interface-definitions/include/interface/mtu-64-8024.xml.i
index f75de02ba..9b8bc4697 100644
--- a/interface-definitions/include/interface/interface-mtu-64-8024.xml.i
+++ b/interface-definitions/include/interface/mtu-64-8024.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mtu-68-8024.xml.i -->
+<!-- include start from interface/mtu-68-8024.xml.i -->
<leafNode name="mtu">
<properties>
<help>Maximum Transmission Unit (MTU)</help>
diff --git a/interface-definitions/include/interface/interface-mtu-68-1500.xml.i b/interface-definitions/include/interface/mtu-68-1500.xml.i
index 9e6fe8760..e3b70302f 100644
--- a/interface-definitions/include/interface/interface-mtu-68-1500.xml.i
+++ b/interface-definitions/include/interface/mtu-68-1500.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mtu-68-1500.xml.i -->
+<!-- include start from interface/mtu-68-1500.xml.i -->
<leafNode name="mtu">
<properties>
<help>Maximum Transmission Unit (MTU)</help>
diff --git a/interface-definitions/include/interface/interface-mtu-68-16000.xml.i b/interface-definitions/include/interface/mtu-68-16000.xml.i
index 83af7bbd4..b610ab3e2 100644
--- a/interface-definitions/include/interface/interface-mtu-68-16000.xml.i
+++ b/interface-definitions/include/interface/mtu-68-16000.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-mtu-68-16000.xml.i -->
+<!-- include start from interface/mtu-68-16000.xml.i -->
<leafNode name="mtu">
<properties>
<help>Maximum Transmission Unit (MTU)</help>
diff --git a/interface-definitions/include/interface/interface-parameters-dont-fragment.xml.i b/interface-definitions/include/interface/parameters-dont-fragment.xml.i
index 166c31115..d34f0a97b 100644
--- a/interface-definitions/include/interface/interface-parameters-dont-fragment.xml.i
+++ b/interface-definitions/include/interface/parameters-dont-fragment.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-parameters-df.xml.i -->
+<!-- include start from interface/parameters-df.xml.i -->
<leafNode name="dont-fragment">
<properties>
<help>Specifies the usage of the dont fragment (DF) bit</help>
diff --git a/interface-definitions/include/interface/interface-parameters-flowlabel.xml.i b/interface-definitions/include/interface/parameters-flowlabel.xml.i
index ed075e40d..7fa571634 100644
--- a/interface-definitions/include/interface/interface-parameters-flowlabel.xml.i
+++ b/interface-definitions/include/interface/parameters-flowlabel.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-parameters-flowlabel.xml.i -->
+<!-- include start from interface/parameters-flowlabel.xml.i -->
<leafNode name="flowlabel">
<properties>
<help>Specifies the flow label to use in outgoing packets</help>
diff --git a/interface-definitions/include/interface/interface-parameters-key.xml.i b/interface-definitions/include/interface/parameters-key.xml.i
index 6c59f7879..25a6c0303 100644
--- a/interface-definitions/include/interface/interface-parameters-key.xml.i
+++ b/interface-definitions/include/interface/parameters-key.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-parameters-key.xml.i -->
+<!-- include start from interface/parameters-key.xml.i -->
<leafNode name="key">
<properties>
<help>Tunnel key (only GRE tunnels)</help>
diff --git a/interface-definitions/include/interface/interface-parameters-tos.xml.i b/interface-definitions/include/interface/parameters-tos.xml.i
index 83b4e0671..83b4e0671 100644
--- a/interface-definitions/include/interface/interface-parameters-tos.xml.i
+++ b/interface-definitions/include/interface/parameters-tos.xml.i
diff --git a/interface-definitions/include/interface/interface-parameters-ttl.xml.i b/interface-definitions/include/interface/parameters-ttl.xml.i
index df193cf24..da5ce69c2 100644
--- a/interface-definitions/include/interface/interface-parameters-ttl.xml.i
+++ b/interface-definitions/include/interface/parameters-ttl.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-parameters-ttl.xml.i -->
+<!-- include start from interface/parameters-ttl.xml.i -->
<leafNode name="ttl">
<properties>
<help>Specifies TTL value to use in outgoing packets</help>
diff --git a/interface-definitions/include/interface/interface-proxy-arp-pvlan.xml.i b/interface-definitions/include/interface/proxy-arp-pvlan.xml.i
index 153dfc072..c00b2fe85 100644
--- a/interface-definitions/include/interface/interface-proxy-arp-pvlan.xml.i
+++ b/interface-definitions/include/interface/proxy-arp-pvlan.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-proxy-arp-pvlan.xml.i -->
+<!-- include start from interface/proxy-arp-pvlan.xml.i -->
<leafNode name="proxy-arp-pvlan">
<properties>
<help>Enable private VLAN proxy ARP on this interface</help>
diff --git a/interface-definitions/include/interface/interface-source-validation.xml.i b/interface-definitions/include/interface/source-validation.xml.i
index 70914f2e9..f38065f4d 100644
--- a/interface-definitions/include/interface/interface-source-validation.xml.i
+++ b/interface-definitions/include/interface/source-validation.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-source-validation.xml.i -->
+<!-- include start from interface/source-validation.xml.i -->
<leafNode name="source-validation">
<properties>
<help>Source validation by reversed path (RFC3704)</help>
diff --git a/interface-definitions/include/interface/vif-s.xml.i b/interface-definitions/include/interface/vif-s.xml.i
index 17d1746be..3fd69d9d1 100644
--- a/interface-definitions/include/interface/vif-s.xml.i
+++ b/interface-definitions/include/interface/vif-s.xml.i
@@ -9,11 +9,11 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
<leafNode name="protocol">
<properties>
<help>Protocol used for service VLAN (default: 802.1ad)</help>
@@ -35,10 +35,10 @@
</properties>
<defaultValue>802.1ad</defaultValue>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
<tagNode name="vif-c">
<properties>
<help>QinQ TAG-C Virtual Local Area Network (VLAN) ID</help>
@@ -49,19 +49,19 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
<!-- include end -->
diff --git a/interface-definitions/include/interface/vif.xml.i b/interface-definitions/include/interface/vif.xml.i
index 9e89cbbf6..8daafeaf4 100644
--- a/interface-definitions/include/interface/vif.xml.i
+++ b/interface-definitions/include/interface/vif.xml.i
@@ -13,12 +13,12 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
<leafNode name="egress-qos">
<properties>
<help>VLAN egress QoS</help>
@@ -45,10 +45,10 @@
<constraintErrorMessage>QoS mapping should be in the format of '0:7 2:3' with numbers 0-9</constraintErrorMessage>
</properties>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
</children>
</tagNode>
<!-- include end -->
diff --git a/interface-definitions/include/interface/interface-vrf.xml.i b/interface-definitions/include/interface/vrf.xml.i
index ef6ca1241..5ad978a27 100644
--- a/interface-definitions/include/interface/interface-vrf.xml.i
+++ b/interface-definitions/include/interface/vrf.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-vrf.xml.i -->
+<!-- include start from interface/vrf.xml.i -->
<leafNode name="vrf">
<properties>
<help>VRF instance name</help>
diff --git a/interface-definitions/include/interface/interface-xdp.xml.i b/interface-definitions/include/interface/xdp.xml.i
index 0253f6dad..10223e766 100644
--- a/interface-definitions/include/interface/interface-xdp.xml.i
+++ b/interface-definitions/include/interface/xdp.xml.i
@@ -1,4 +1,4 @@
-<!-- include start from interface/interface-xdp.xml.i -->
+<!-- include start from interface/xdp.xml.i -->
<leafNode name="xdp">
<properties>
<help>Enable eXpress Data Path</help>
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index af5a21f49..84e2f7bb2 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -447,7 +447,7 @@
<help>Border Gateway Protocol (BGP)</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv4.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="connected">
@@ -455,7 +455,7 @@
<help>Redistribute connected routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv4.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="kernel">
@@ -463,7 +463,7 @@
<help>Redistribute kernel routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv4.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="ospf">
@@ -471,7 +471,7 @@
<help>Redistribute OSPF routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv4.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="rip">
@@ -479,7 +479,7 @@
<help>Redistribute RIP routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv4.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="static">
@@ -487,7 +487,7 @@
<help>Redistribute static routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv4.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
</children>
@@ -502,7 +502,7 @@
<help>Redistribute BGP routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv6.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="connected">
@@ -510,7 +510,7 @@
<help>Redistribute connected routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv6.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="kernel">
@@ -518,7 +518,7 @@
<help>Redistribute kernel routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv6.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="ospf6">
@@ -526,7 +526,7 @@
<help>Redistribute OSPFv3 routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv6.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="ripng">
@@ -534,7 +534,7 @@
<help>Redistribute RIPng routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv6.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
<node name="static">
@@ -542,7 +542,7 @@
<help>Redistribute static routes into IS-IS</help>
</properties>
<children>
- #include <include/isis/redistribute-ipv6.xml.i>
+ #include <include/isis/redistribute-level-1-2.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/include/isis/redistribute-ipv4.xml.i b/interface-definitions/include/isis/redistribute-ipv4.xml.i
deleted file mode 100644
index fbb6210c7..000000000
--- a/interface-definitions/include/isis/redistribute-ipv4.xml.i
+++ /dev/null
@@ -1,42 +0,0 @@
-<!-- include start from isis/redistribute-ipv4.xml.i -->
-<node name="level-1">
- <properties>
- <help>Redistribute into level-1</help>
- </properties>
- <children>
- <leafNode name="metric">
- <properties>
- <help>Metric for redistributed routes</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>ISIS default metric</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/route-map.xml.i>
- </children>
-</node>
-<node name="level-2">
- <properties>
- <help>Redistribute into level-2</help>
- </properties>
- <children>
- <leafNode name="metric">
- <properties>
- <help>Metric for redistributed routes</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>ISIS default metric</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/route-map.xml.i>
- </children>
-</node>
-<!-- include end -->
diff --git a/interface-definitions/include/isis/redistribute-ipv6.xml.i b/interface-definitions/include/isis/redistribute-ipv6.xml.i
deleted file mode 100644
index 7e679e38a..000000000
--- a/interface-definitions/include/isis/redistribute-ipv6.xml.i
+++ /dev/null
@@ -1,42 +0,0 @@
-<!-- include start from isis/redistribute-ipv6.xml.i -->
-<node name="level-1">
- <properties>
- <help>Redistribute into level-1</help>
- </properties>
- <children>
- <leafNode name="metric">
- <properties>
- <help>Metric for redistributed routes</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>ISIS default metric</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/route-map.xml.i>
- </children>
-</node>
-<node name="level-2">
- <properties>
- <help>Redistribute into level-2</help>
- </properties>
- <children>
- <leafNode name="metric">
- <properties>
- <help>Metric for redistributed routes</help>
- <valueHelp>
- <format>u32:0-16777215</format>
- <description>ISIS default metric</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-16777215"/>
- </constraint>
- </properties>
- </leafNode>
- #include <include/route-map.xml.i>
- </children>
-</node>
-<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/include/isis/redistribute-level-1-2.xml.i b/interface-definitions/include/isis/redistribute-level-1-2.xml.i
new file mode 100644
index 000000000..abb85274f
--- /dev/null
+++ b/interface-definitions/include/isis/redistribute-level-1-2.xml.i
@@ -0,0 +1,20 @@
+<!-- include start from isis/redistribute-level-1-2.xml.i -->
+<node name="level-1">
+ <properties>
+ <help>Redistribute into level-1</help>
+ </properties>
+ <children>
+ #include <include/isis/metric.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+</node>
+<node name="level-2">
+ <properties>
+ <help>Redistribute into level-2</help>
+ </properties>
+ <children>
+ #include <include/isis/metric.xml.i>
+ #include <include/route-map.xml.i>
+ </children>
+</node>
+<!-- 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 db39b1a86..c4ca613a4 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -361,6 +361,23 @@
</constraint>
</properties>
<children>
+ <leafNode name="area">
+ <properties>
+ <help>Enable OSPF on this interface</help>
+ <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>
diff --git a/interface-definitions/include/port-number.xml.i b/interface-definitions/include/port-number.xml.i
index b62aef32b..6820df0c4 100644
--- a/interface-definitions/include/port-number.xml.i
+++ b/interface-definitions/include/port-number.xml.i
@@ -9,6 +9,7 @@
<constraint>
<validator name="numeric" argument="--range 1-65535"/>
</constraint>
+ <constraintErrorMessage>Port number must be in range 1 to 65535</constraintErrorMessage>
</properties>
</leafNode>
<!-- include end -->
diff --git a/interface-definitions/include/pppoe-access-concentrator.xml.i b/interface-definitions/include/pppoe-access-concentrator.xml.i
new file mode 100644
index 000000000..ccfcc1c49
--- /dev/null
+++ b/interface-definitions/include/pppoe-access-concentrator.xml.i
@@ -0,0 +1,11 @@
+<!-- include start from pppoe-access-concentrator.xml.i -->
+<leafNode name="access-concentrator">
+ <properties>
+ <help>Access concentrator name</help>
+ <constraint>
+ <regex>[a-zA-Z0-9]{1,100}</regex>
+ </constraint>
+ <constraintErrorMessage>Access-concentrator name must be alphanumerical only (max. 100 characters)</constraintErrorMessage>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in
index 4bfc6e730..05e0d8461 100644
--- a/interface-definitions/interfaces-bonding.xml.in
+++ b/interface-definitions/interfaces-bonding.xml.in
@@ -49,13 +49,13 @@
</leafNode>
</children>
</node>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
- #include <include/interface/interface-mirror.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
+ #include <include/interface/mirror.xml.i>
<leafNode name="hash-policy">
<properties>
<help>Bonding transmit hash policy</help>
@@ -89,9 +89,9 @@
</properties>
<defaultValue>layer2</defaultValue>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
<leafNode name="min-links">
<properties>
<help>Minimum number of member interfaces required up before enabling bond</help>
@@ -182,7 +182,7 @@
</leafNode>
</children>
</node>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
<leafNode name="primary">
<properties>
<help>Primary device interface</help>
@@ -193,7 +193,7 @@
</leafNode>
#include <include/interface/vif-s.xml.i>
#include <include/interface/vif.xml.i>
- #include <include/interface/interface-xdp.xml.i>
+ #include <include/interface/xdp.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in
index 1af002142..ddfc5ade4 100644
--- a/interface-definitions/interfaces-bridge.xml.in
+++ b/interface-definitions/interfaces-bridge.xml.in
@@ -34,13 +34,13 @@
</properties>
<defaultValue>300</defaultValue>
</leafNode>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
<leafNode name="forwarding-delay">
<properties>
<help>Forwarding delay</help>
@@ -82,10 +82,10 @@
</leafNode>
</children>
</node>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mirror.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mirror.xml.i>
<leafNode name="enable-vlan">
<properties>
<help>Enable VLAN aware bridge</help>
diff --git a/interface-definitions/interfaces-dummy.xml.in b/interface-definitions/interfaces-dummy.xml.in
index 84c6903c7..2bc88c1a7 100644
--- a/interface-definitions/interfaces-dummy.xml.in
+++ b/interface-definitions/interfaces-dummy.xml.in
@@ -17,17 +17,17 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
<node name="ip">
<properties>
<help>IPv4 routing parameters</help>
</properties>
<children>
- #include <include/interface/interface-source-validation.xml.i>
+ #include <include/interface/source-validation.xml.i>
</children>
</node>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in
index cb451f5be..ca076e3fa 100644
--- a/interface-definitions/interfaces-ethernet.xml.in
+++ b/interface-definitions/interfaces-ethernet.xml.in
@@ -20,7 +20,7 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
<leafNode name="disable-flow-control">
@@ -29,8 +29,8 @@
<valueless/>
</properties>
</leafNode>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
<leafNode name="duplex">
<properties>
<help>Duplex mode</help>
@@ -56,13 +56,13 @@
</properties>
<defaultValue>auto</defaultValue>
</leafNode>
- #include <include/interface/interface-eapol.xml.i>
- #include <include/interface/interface-hw-id.xml.i>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
- #include <include/interface/interface-mirror.xml.i>
+ #include <include/interface/eapol.xml.i>
+ #include <include/interface/hw-id.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
+ #include <include/interface/mirror.xml.i>
<node name="offload">
<properties>
<help>Configurable offload options</help>
@@ -202,8 +202,8 @@
</node>
#include <include/interface/vif-s.xml.i>
#include <include/interface/vif.xml.i>
- #include <include/interface/interface-vrf.xml.i>
- #include <include/interface/interface-xdp.xml.i>
+ #include <include/interface/vrf.xml.i>
+ #include <include/interface/xdp.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-geneve.xml.in b/interface-definitions/interfaces-geneve.xml.in
index bdcbc3f5e..2ca7dd9f6 100644
--- a/interface-definitions/interfaces-geneve.xml.in
+++ b/interface-definitions/interfaces-geneve.xml.in
@@ -17,12 +17,12 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mtu-1450-16000.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mtu-1450-16000.xml.i>
<node name="parameters">
<properties>
<help>GENEVE tunnel parameters</help>
@@ -33,9 +33,9 @@
<help>IPv4 specific tunnel parameters</help>
</properties>
<children>
- #include <include/interface/interface-parameters-dont-fragment.xml.i>
- #include <include/interface/interface-parameters-tos.xml.i>
- #include <include/interface/interface-parameters-ttl.xml.i>
+ #include <include/interface/parameters-dont-fragment.xml.i>
+ #include <include/interface/parameters-tos.xml.i>
+ #include <include/interface/parameters-ttl.xml.i>
</children>
</node>
<node name="ipv6">
@@ -43,7 +43,7 @@
<help>IPv6 specific tunnel parameters</help>
</properties>
<children>
- #include <include/interface/interface-parameters-flowlabel.xml.i>
+ #include <include/interface/parameters-flowlabel.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in
index 8835a6b1d..9edc98ef6 100644
--- a/interface-definitions/interfaces-l2tpv3.xml.in
+++ b/interface-definitions/interfaces-l2tpv3.xml.in
@@ -17,7 +17,7 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
<leafNode name="destination-port">
<properties>
<help>UDP destination port for L2TPv3 tunnel (default: 5000)</help>
@@ -31,7 +31,7 @@
</properties>
<defaultValue>5000</defaultValue>
</leafNode>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/disable.xml.i>
<leafNode name="encapsulation">
<properties>
<help>Encapsulation type (default: UDP)</help>
@@ -53,10 +53,10 @@
</properties>
<defaultValue>udp</defaultValue>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
#include <include/source-address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1488</defaultValue>
</leafNode>
@@ -84,7 +84,7 @@
</constraint>
</properties>
</leafNode>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
#include <include/interface/tunnel-remote.xml.i>
<leafNode name="session-id">
<properties>
@@ -123,7 +123,7 @@
</constraint>
</properties>
</leafNode>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-loopback.xml.in b/interface-definitions/interfaces-loopback.xml.in
index 5d0ca5b0a..7be15ab89 100644
--- a/interface-definitions/interfaces-loopback.xml.in
+++ b/interface-definitions/interfaces-loopback.xml.in
@@ -17,13 +17,13 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
<node name="ip">
<properties>
<help>IPv4 routing parameters</help>
</properties>
<children>
- #include <include/interface/interface-source-validation.xml.i>
+ #include <include/interface/source-validation.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in
index fce88b21c..e88cb4794 100644
--- a/interface-definitions/interfaces-macsec.xml.in
+++ b/interface-definitions/interfaces-macsec.xml.in
@@ -17,8 +17,8 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
<node name="security">
<properties>
<help>Security/Encryption Settings</help>
@@ -111,14 +111,14 @@
</leafNode>
</children>
</node>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1460</defaultValue>
</leafNode>
#include <include/source-interface-ethernet.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in
index 7ff08ac86..01e6bf2fb 100644
--- a/interface-definitions/interfaces-openvpn.xml.in
+++ b/interface-definitions/interfaces-openvpn.xml.in
@@ -33,7 +33,7 @@
</leafNode>
</children>
</node>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
<leafNode name="device-type">
<properties>
<help>OpenVPN interface device-type (default: tun)</help>
@@ -54,7 +54,7 @@
</properties>
<defaultValue>tun</defaultValue>
</leafNode>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/disable.xml.i>
<node name="encryption">
<properties>
<help>Data Encryption settings</help>
@@ -165,7 +165,7 @@
</leafNode>
</children>
</node>
- #include <include/interface/interface-ipv6-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
<leafNode name="hash">
<properties>
<help>Hashing Algorithm</help>
@@ -571,7 +571,7 @@
<multi/>
</properties>
</leafNode>
- <leafNode name="push-route">
+ <tagNode name="push-route">
<properties>
<help>Route to be pushed to all clients</help>
<valueHelp>
@@ -585,9 +585,23 @@
<constraint>
<validator name="ip-prefix"/>
</constraint>
- <multi/>
</properties>
- </leafNode>
+ <children>
+ <leafNode name="metric">
+ <properties>
+ <help>Set metric for this route</help>
+ <valueHelp>
+ <format>0-4294967295</format>
+ <description>Metric for this route</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ <defaultValue>0</defaultValue>
+ </leafNode>
+ </children>
+ </tagNode>
<leafNode name="reject-unconfigured-clients">
<properties>
<help>Reject connections from clients that are not explicitly configured</help>
@@ -726,7 +740,7 @@
<valueless/>
</properties>
</leafNode>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-pppoe.xml.in b/interface-definitions/interfaces-pppoe.xml.in
index 96479e057..57bb01258 100644
--- a/interface-definitions/interfaces-pppoe.xml.in
+++ b/interface-definitions/interfaces-pppoe.xml.in
@@ -5,7 +5,7 @@
<tagNode name="pppoe" owner="${vyos_conf_scripts_dir}/interfaces-pppoe.py">
<properties>
<help>Point-to-Point Protocol over Ethernet (PPPoE)</help>
- <priority>321</priority>
+ <priority>322</priority>
<constraint>
<regex>^pppoe[0-9]+$</regex>
</constraint>
@@ -16,17 +16,9 @@
</valueHelp>
</properties>
<children>
- <leafNode name="access-concentrator">
- <properties>
- <help>Access concentrator name (only connect to this concentrator)</help>
- <constraint>
- <regex>[a-zA-Z0-9]+$</regex>
- </constraint>
- <constraintErrorMessage>Access concentrator name must be composed of uppper and lower case letters or numbers only</constraintErrorMessage>
- </properties>
- </leafNode>
+ #include <include/pppoe-access-concentrator.xml.i>
#include <include/interface/authentication.xml.i>
- #include <include/interface/interface-dial-on-demand.xml.i>
+ #include <include/interface/dial-on-demand.xml.i>
<leafNode name="default-route">
<properties>
<help>Default route insertion behaviour (default: auto)</help>
@@ -53,16 +45,20 @@
<defaultValue>auto</defaultValue>
</leafNode>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
<leafNode name="idle-timeout">
<properties>
<help>Delay before disconnecting idle session (in seconds)</help>
<valueHelp>
- <format>n</format>
+ <format>u32:0-86400</format>
<description>Idle timeout in seconds</description>
</valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-86400"/>
+ </constraint>
+ <constraintErrorMessage>Timeout must be in range 0 to 86400</constraintErrorMessage>
</properties>
</leafNode>
<node name="ip">
@@ -70,7 +66,9 @@
<help>IPv4 routing parameters</help>
</properties>
<children>
- #include <include/interface/interface-source-validation.xml.i>
+ #include <include/interface/adjust-mss.xml.i>
+ #include <include/interface/disable-forwarding.xml.i>
+ #include <include/interface/source-validation.xml.i>
</children>
</node>
<node name="ipv6">
@@ -86,16 +84,11 @@
#include <include/interface/ipv6-address-autoconf.xml.i>
</children>
</node>
+ #include <include/interface/adjust-mss.xml.i>
+ #include <include/interface/disable-forwarding.xml.i>
</children>
</node>
- <leafNode name="source-interface">
- <properties>
- <help>Physical Interface used for this PPPoE session</help>
- <completionHelp>
- <script>${vyos_completion_dir}/list_interfaces.py --broadcast</script>
- </completionHelp>
- </properties>
- </leafNode>
+ #include <include/source-interface.xml.i>
<leafNode name="local-address">
<properties>
<help>IPv4 address of local end of the PPPoE link</help>
@@ -108,7 +101,7 @@
</constraint>
</properties>
</leafNode>
- #include <include/interface/interface-mtu-68-1500.xml.i>
+ #include <include/interface/mtu-68-1500.xml.i>
<leafNode name="mtu">
<defaultValue>1492</defaultValue>
</leafNode>
@@ -136,7 +129,7 @@
<constraint>
<regex>[a-zA-Z0-9]+$</regex>
</constraint>
- <constraintErrorMessage>Service name must be composed of uppper and lower case letters or numbers only</constraintErrorMessage>
+ <constraintErrorMessage>Service name must be alphanumeric only</constraintErrorMessage>
</properties>
</leafNode>
</children>
diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in
index 136841290..366892032 100644
--- a/interface-definitions/interfaces-pseudo-ethernet.xml.in
+++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in
@@ -17,16 +17,16 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6-dhcp.xml.i>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
#include <include/source-interface-ethernet.xml.i>
- #include <include/interface/interface-mac.xml.i>
+ #include <include/interface/mac.xml.i>
<leafNode name="mode">
<properties>
<help>Receive mode (default: private)</help>
@@ -56,7 +56,7 @@
</properties>
<defaultValue>private</defaultValue>
</leafNode>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
#include <include/interface/vif-s.xml.i>
#include <include/interface/vif.xml.i>
</children>
diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in
index b994bdafc..c059ef624 100644
--- a/interface-definitions/interfaces-tunnel.xml.in
+++ b/interface-definitions/interfaces-tunnel.xml.in
@@ -16,17 +16,17 @@
</valueHelp>
</properties>
<children>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-vrf.xml.i>
- #include <include/interface/interface-mtu-64-8024.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/vrf.xml.i>
+ #include <include/interface/mtu-64-8024.xml.i>
<leafNode name="mtu">
<defaultValue>1476</defaultValue>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
#include <include/source-address-ipv4-ipv6.xml.i>
#include <include/interface/tunnel-remote.xml.i>
#include <include/source-interface.xml.i>
@@ -216,9 +216,9 @@
<valueless/>
</properties>
</leafNode>
- #include <include/interface/interface-parameters-key.xml.i>
- #include <include/interface/interface-parameters-tos.xml.i>
- #include <include/interface/interface-parameters-ttl.xml.i>
+ #include <include/interface/parameters-key.xml.i>
+ #include <include/interface/parameters-tos.xml.i>
+ #include <include/interface/parameters-ttl.xml.i>
<leafNode name="ttl">
<defaultValue>64</defaultValue>
</leafNode>
@@ -251,7 +251,7 @@
</properties>
<defaultValue>4</defaultValue>
</leafNode>
- #include <include/interface/interface-parameters-flowlabel.xml.i>
+ #include <include/interface/parameters-flowlabel.xml.i>
<leafNode name="hoplimit">
<properties>
<help>Hoplimit</help>
diff --git a/interface-definitions/interfaces-vti.xml.in b/interface-definitions/interfaces-vti.xml.in
index 10e1feb6b..b12434ae7 100644
--- a/interface-definitions/interfaces-vti.xml.in
+++ b/interface-definitions/interfaces-vti.xml.in
@@ -29,10 +29,12 @@
<multi/>
</properties>
</leafNode>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in
index 56d01dfb6..43b73a2e9 100644
--- a/interface-definitions/interfaces-vxlan.xml.in
+++ b/interface-definitions/interfaces-vxlan.xml.in
@@ -17,8 +17,8 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
<leafNode name="group">
<properties>
<help>Multicast group address for VXLAN interface</help>
@@ -35,10 +35,10 @@
</constraint>
</properties>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-mac.xml.i>
- #include <include/interface/interface-mtu-1200-16000.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/mac.xml.i>
+ #include <include/interface/mtu-1200-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1450</defaultValue>
</leafNode>
@@ -52,9 +52,9 @@
<help>IPv4 specific tunnel parameters</help>
</properties>
<children>
- #include <include/interface/interface-parameters-dont-fragment.xml.i>
- #include <include/interface/interface-parameters-tos.xml.i>
- #include <include/interface/interface-parameters-ttl.xml.i>
+ #include <include/interface/parameters-dont-fragment.xml.i>
+ #include <include/interface/parameters-tos.xml.i>
+ #include <include/interface/parameters-ttl.xml.i>
<leafNode name="ttl">
<defaultValue>16</defaultValue>
</leafNode>
@@ -65,7 +65,7 @@
<help>IPv6 specific tunnel parameters</help>
</properties>
<children>
- #include <include/interface/interface-parameters-flowlabel.xml.i>
+ #include <include/interface/parameters-flowlabel.xml.i>
</children>
</node>
<leafNode name="nolearning">
@@ -76,23 +76,14 @@
</leafNode>
</children>
</node>
+ #include <include/port-number.xml.i>
<leafNode name="port">
- <properties>
- <help>Destination port of VXLAN tunnel (default: 8472)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Numeric IP port</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
<defaultValue>8472</defaultValue>
</leafNode>
#include <include/source-address-ipv4-ipv6.xml.i>
#include <include/source-interface.xml.i>
#include <include/interface/tunnel-remote.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
#include <include/vni.xml.i>
</children>
</tagNode>
diff --git a/interface-definitions/interfaces-wireguard.xml.in b/interface-definitions/interfaces-wireguard.xml.in
index 773bde09c..ecb4cf331 100644
--- a/interface-definitions/interfaces-wireguard.xml.in
+++ b/interface-definitions/interfaces-wireguard.xml.in
@@ -17,16 +17,16 @@
</properties>
<children>
#include <include/interface/address-ipv4-ipv6.xml.i>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
#include <include/port-number.xml.i>
- #include <include/interface/interface-mtu-68-16000.xml.i>
+ #include <include/interface/mtu-68-16000.xml.i>
<leafNode name="mtu">
<defaultValue>1420</defaultValue>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
<leafNode name="fwmark">
<properties>
<help>A 32-bit fwmark value set on all outgoing packets</help>
@@ -102,18 +102,7 @@
</constraint>
</properties>
</leafNode>
- <leafNode name="port">
- <properties>
- <help>Port number used for tunnel endpoint</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Numeric IP port</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/port-number.xml.i>
<leafNode name="persistent-keepalive">
<properties>
<help>Interval to send keepalive messages</help>
diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in
index aaeb285f1..c96d9b78d 100644
--- a/interface-definitions/interfaces-wireless.xml.in
+++ b/interface-definitions/interfaces-wireless.xml.in
@@ -464,7 +464,7 @@
<constraintErrorMessage>Invalid ISO/IEC 3166-1 Country Code</constraintErrorMessage>
</properties>
</leafNode>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
<leafNode name="disable-broadcast-ssid">
@@ -473,25 +473,25 @@
<valueless/>
</properties>
</leafNode>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
<leafNode name="expunge-failing-stations">
<properties>
<help>Disassociate stations based on excessive transmission failures</help>
<valueless/>
</properties>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-hw-id.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/hw-id.xml.i>
<leafNode name="isolate-stations">
<properties>
<help>Isolate stations on the AP so they cannot see each other</help>
<valueless/>
</properties>
</leafNode>
- #include <include/interface/interface-mac.xml.i>
+ #include <include/interface/mac.xml.i>
<leafNode name="max-stations">
<properties>
<help>Maximum number of wireless radio stations. Excess stations will be rejected upon authentication request.</help>
diff --git a/interface-definitions/interfaces-wwan.xml.in b/interface-definitions/interfaces-wwan.xml.in
index ea3184a11..6b6fa1a66 100644
--- a/interface-definitions/interfaces-wwan.xml.in
+++ b/interface-definitions/interfaces-wwan.xml.in
@@ -28,17 +28,17 @@
#include <include/interface/dhcp-options.xml.i>
#include <include/interface/dhcpv6-options.xml.i>
#include <include/interface/authentication.xml.i>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
- #include <include/interface/interface-vrf.xml.i>
- #include <include/interface/interface-disable-link-detect.xml.i>
- #include <include/interface/interface-mtu-68-1500.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
+ #include <include/interface/vrf.xml.i>
+ #include <include/interface/disable-link-detect.xml.i>
+ #include <include/interface/mtu-68-1500.xml.i>
<leafNode name="mtu">
<defaultValue>1430</defaultValue>
</leafNode>
- #include <include/interface/interface-ipv4-options.xml.i>
- #include <include/interface/interface-ipv6-options.xml.i>
- #include <include/interface/interface-dial-on-demand.xml.i>
+ #include <include/interface/ipv4-options.xml.i>
+ #include <include/interface/ipv6-options.xml.i>
+ #include <include/interface/dial-on-demand.xml.i>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/ntp.xml.in b/interface-definitions/ntp.xml.in
index 2bfac900b..a518a9def 100644
--- a/interface-definitions/ntp.xml.in
+++ b/interface-definitions/ntp.xml.in
@@ -82,7 +82,7 @@
</children>
</node>
#include <include/listen-address.xml.i>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/policy-local-route.xml.in b/interface-definitions/policy-local-route.xml.in
index 3769c3748..86445b65d 100644
--- a/interface-definitions/policy-local-route.xml.in
+++ b/interface-definitions/policy-local-route.xml.in
@@ -40,6 +40,18 @@
</leafNode>
</children>
</node>
+ <leafNode name="fwmark">
+ <properties>
+ <help>Match fwmark value</help>
+ <valueHelp>
+ <format>u32:1-2147483647</format>
+ <description>Address to match against</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-2147483647"/>
+ </constraint>
+ </properties>
+ </leafNode>
<leafNode name="source">
<properties>
<help>Source address or prefix</help>
diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in
index fb62d2f89..cf65daf00 100644
--- a/interface-definitions/policy.xml.in
+++ b/interface-definitions/policy.xml.in
@@ -139,7 +139,7 @@
</tagNode>
<tagNode name="as-path-list">
<properties>
- <help>Border Gateway Protocol (BGP) autonomous system path filter</help>
+ <help>Add a BGP autonomous system path filter</help>
<valueHelp>
<format>txt</format>
<description>AS path list name</description>
@@ -176,10 +176,10 @@
</tagNode>
<tagNode name="community-list">
<properties>
- <help>Border Gateway Protocol (BGP) autonomous system path filter</help>
+ <help>Add a BGP community list entry</help>
<valueHelp>
<format>txt</format>
- <description>Border Gateway Protocol (BGP) community-list filter</description>
+ <description>BGP community-list name</description>
</valueHelp>
</properties>
<children>
@@ -236,11 +236,15 @@
</tagNode>
<tagNode name="extcommunity-list">
<properties>
- <help>Border Gateway Protocol (BGP) extended community-list filter</help>
+ <help>Add a BGP extended community list entry</help>
<valueHelp>
<format>txt</format>
- <description>Border Gateway Protocol (BGP) extended community-list filter</description>
+ <description>BGP extended community-list name</description>
</valueHelp>
+ <constraint>
+ <regex>^[-_a-zA-Z0-9]+$</regex>
+ </constraint>
+ <constraintErrorMessage>Should be an alphanumeric name</constraintErrorMessage>
</properties>
<children>
#include <include/generic-description.xml.i>
@@ -281,11 +285,15 @@
</tagNode>
<tagNode name="large-community-list">
<properties>
- <help>Border Gateway Protocol (BGP) large-community-list filter</help>
+ <help>Add a BGP large community list entry</help>
<valueHelp>
<format>txt</format>
- <description>Border Gateway Protocol (BGP) large-community-list filter</description>
+ <description>BGP large-community-list name</description>
</valueHelp>
+ <constraint>
+ <regex>^[-_a-zA-Z0-9]+$</regex>
+ </constraint>
+ <constraintErrorMessage>Should be an alphanumeric name</constraintErrorMessage>
</properties>
<children>
#include <include/generic-description.xml.i>
@@ -307,9 +315,17 @@
<properties>
<help>Regular expression to match against a large community list</help>
<valueHelp>
- <format>&lt;aa:nn:nn&gt;</format>
- <description>Large Community value</description>
+ <format>ASN:NN:NN</format>
+ <description>BGP large-community-list filter</description>
</valueHelp>
+ <valueHelp>
+ <format>IP:NN:NN</format>
+ <description>BGP large-community-list filter (IPv4 address format)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="bgp-large-community-list"/>
+ </constraint>
+ <constraintErrorMessage>Malformed large-community-list</constraintErrorMessage>
</properties>
</leafNode>
</children>
@@ -808,7 +824,7 @@
</leafNode>
<leafNode name="origin">
<properties>
- <help>Border Gateway Protocol (BGP) origin code to match</help>
+ <help>BGP origin code to match</help>
<completionHelp>
<list>egp igp incomplete</list>
</completionHelp>
@@ -910,7 +926,7 @@
<children>
<node name="aggregator">
<properties>
- <help>Border Gateway Protocol (BGP) aggregator attribute</help>
+ <help>BGP aggregator attribute</help>
</properties>
<children>
<leafNode name="as">
@@ -959,13 +975,13 @@
</leafNode>
<leafNode name="atomic-aggregate">
<properties>
- <help>Border Gateway Protocol (BGP) atomic aggregate attribute</help>
+ <help>BGP atomic aggregate attribute</help>
<valueless/>
</properties>
</leafNode>
<node name="comm-list">
<properties>
- <help>Border Gateway Protocol (BGP) communities matching a community-list</help>
+ <help>BGP communities matching a community-list</help>
</properties>
<children>
<leafNode name="comm-list">
@@ -1162,9 +1178,21 @@
</completionHelp>
</properties>
</leafNode>
+ <leafNode name="large-comm-list-delete">
+ <properties>
+ <help>Delete BGP communities matching the large community-list</help>
+ <completionHelp>
+ <path>policy large-community-list</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>BGP large community-list</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
<leafNode name="local-preference">
<properties>
- <help>Border Gateway Protocol (BGP) local preference attribute</help>
+ <help>BGP local preference attribute</help>
<valueHelp>
<format>u32:0-4294967295</format>
<description>Local preference value</description>
@@ -1234,7 +1262,7 @@
</leafNode>
<leafNode name="originator-id">
<properties>
- <help>Border Gateway Protocol (BGP) originator ID attribute</help>
+ <help>BGP originator ID attribute</help>
<valueHelp>
<format>ipv4</format>
<description>Orignator IP address</description>
@@ -1287,7 +1315,7 @@
</leafNode>
<leafNode name="weight">
<properties>
- <help>Border Gateway Protocol (BGP) weight attribute</help>
+ <help>BGP weight attribute</help>
<valueHelp>
<format>u32:0-4294967295</format>
<description>BGP weight</description>
diff --git a/interface-definitions/service_console-server.xml.in b/interface-definitions/service_console-server.xml.in
index 78eb2d0ba..28aa7ea71 100644
--- a/interface-definitions/service_console-server.xml.in
+++ b/interface-definitions/service_console-server.xml.in
@@ -27,7 +27,7 @@
</constraint>
</properties>
<children>
- #include <include/interface/interface-description.xml.i>
+ #include <include/interface/description.xml.i>
<leafNode name="speed">
<properties>
<help>Serial port baud rate</help>
diff --git a/interface-definitions/service_pppoe-server.xml.in b/interface-definitions/service_pppoe-server.xml.in
index 7b96b5692..79042e0f3 100644
--- a/interface-definitions/service_pppoe-server.xml.in
+++ b/interface-definitions/service_pppoe-server.xml.in
@@ -8,14 +8,8 @@
<priority>900</priority>
</properties>
<children>
+ #include <include/pppoe-access-concentrator.xml.i>
<leafNode name="access-concentrator">
- <properties>
- <help>Access concentrator name</help>
- <constraint>
- <regex>[a-zA-Z0-9]{1,100}</regex>
- </constraint>
- <constraintErrorMessage>access-concentrator name limited to alphanumerical characters only (max. 100)</constraintErrorMessage>
- </properties>
<defaultValue>vyos-ac</defaultValue>
</leafNode>
<node name="authentication">
@@ -129,7 +123,7 @@
<constraint>
<regex>[a-zA-Z0-9\-]{1,100}</regex>
</constraint>
- <constraintErrorMessage>servicename can contain aplhanumerical characters and dashes only (max. 100)</constraintErrorMessage>
+ <constraintErrorMessage>Service-name can contain aplhanumerical characters and dashes only (max. 100)</constraintErrorMessage>
<multi/>
</properties>
</leafNode>
diff --git a/interface-definitions/service_webproxy.xml.in b/interface-definitions/service_webproxy.xml.in
index 7cb0f7ece..64747420b 100644
--- a/interface-definitions/service_webproxy.xml.in
+++ b/interface-definitions/service_webproxy.xml.in
@@ -83,17 +83,8 @@
<valueless/>
</properties>
</leafNode>
+ #include <include/port-number.xml.i>
<leafNode name="port">
- <properties>
- <help>LDAP server port to use (default: 389)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Port number to use</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
<defaultValue>389</defaultValue>
</leafNode>
<leafNode name="server">
@@ -214,7 +205,7 @@
<properties>
<help>Cache peer options (default: "no-query default")</help>
<valueHelp>
- <format>text</format>
+ <format>txt</format>
<description>Cache peer options</description>
</valueHelp>
</properties>
diff --git a/interface-definitions/snmp.xml.in b/interface-definitions/snmp.xml.in
index 2654449a1..b0b7768d2 100644
--- a/interface-definitions/snmp.xml.in
+++ b/interface-definitions/snmp.xml.in
@@ -646,7 +646,7 @@
</tagNode>
</children>
</node>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/ssh.xml.in b/interface-definitions/ssh.xml.in
index 54742f1d0..c447f144d 100644
--- a/interface-definitions/ssh.xml.in
+++ b/interface-definitions/ssh.xml.in
@@ -146,7 +146,7 @@
</constraint>
</properties>
</leafNode>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/system-conntrack.xml.in b/interface-definitions/system-conntrack.xml.in
index fa73df3db..daa4177c9 100644
--- a/interface-definitions/system-conntrack.xml.in
+++ b/interface-definitions/system-conntrack.xml.in
@@ -37,65 +37,51 @@
</leafNode>
<node name="modules">
<properties>
- <help>Connection tracking modules settings</help>
+ <help>Connection tracking modules</help>
</properties>
<children>
- <node name="ftp">
+ <leafNode name="ftp">
<properties>
- <help>FTP connection tracking settings</help>
+ <help>FTP connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
- <node name="h323">
+ </leafNode>
+ <leafNode name="h323">
<properties>
- <help>H.323 connection tracking settings</help>
+ <help>H.323 connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
- <node name="nfs">
+ </leafNode>
+ <leafNode name="nfs">
<properties>
- <help>NFS connection tracking settings</help>
+ <help>NFS connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
- <node name="pptp">
+ </leafNode>
+ <leafNode name="pptp">
<properties>
- <help>PPTP connection tracking settings</help>
+ <help>PPTP connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
- <node name="sip">
+ </leafNode>
+ <leafNode name="sip">
<properties>
- <help>SIP connection tracking settings</help>
+ <help>SIP connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
- <node name="sqlnet">
+ </leafNode>
+ <leafNode name="sqlnet">
<properties>
- <help>SQLnet connection tracking settings</help>
+ <help>SQLnet connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
- <node name="tftp">
+ </leafNode>
+ <leafNode name="tftp">
<properties>
- <help>TFTP connection tracking settings</help>
+ <help>TFTP connection tracking</help>
+ <valueless/>
</properties>
- <children>
- #include <include/conntrack-module-disable.xml.i>
- </children>
- </node>
+ </leafNode>
</children>
</node>
<leafNode name="table-size">
diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in
index 86db3f368..fb34b7199 100644
--- a/interface-definitions/system-login.xml.in
+++ b/interface-definitions/system-login.xml.in
@@ -145,7 +145,7 @@
</leafNode>
</children>
</tagNode>
- #include <include/interface/interface-vrf.xml.i>
+ #include <include/interface/vrf.xml.i>
</children>
</node>
</children>
diff --git a/interface-definitions/system-proxy.xml.in b/interface-definitions/system-proxy.xml.in
index 791f41f2f..ade168522 100644
--- a/interface-definitions/system-proxy.xml.in
+++ b/interface-definitions/system-proxy.xml.in
@@ -15,18 +15,7 @@
</constraint>
</properties>
</leafNode>
- <leafNode name="port">
- <properties>
- <help>Proxy port</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Numeric IP port</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- </leafNode>
+ #include <include/port-number.xml.i>
<leafNode name="username">
<properties>
<help>Proxy username</help>
diff --git a/interface-definitions/system-syslog.xml.in b/interface-definitions/system-syslog.xml.in
index f3dcae2f3..9280a43c8 100644
--- a/interface-definitions/system-syslog.xml.in
+++ b/interface-definitions/system-syslog.xml.in
@@ -195,19 +195,7 @@
</valueHelp>
</properties>
<children>
- <leafNode name="port">
- <properties>
- <help>Destination port</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Destination port</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- <constraintErrorMessage>Invalid destination port value</constraintErrorMessage>
- </properties>
- </leafNode>
+ #include <include/port-number.xml.i>
<tagNode name="facility">
<properties>
<help>Facility for logging</help>
diff --git a/interface-definitions/tftp-server.xml.in b/interface-definitions/tftp-server.xml.in
index e903e8f4e..037c097ca 100644
--- a/interface-definitions/tftp-server.xml.in
+++ b/interface-definitions/tftp-server.xml.in
@@ -20,17 +20,8 @@
<valueless/>
</properties>
</leafNode>
+ #include <include/port-number.xml.i>
<leafNode name="port">
- <properties>
- <help>Port number used to listen for connections</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Numeric IP port</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
<defaultValue>69</defaultValue>
</leafNode>
#include <include/listen-address.xml.i>
diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in
index b28c86ae6..b0dba4bce 100644
--- a/interface-definitions/vpn_ipsec.xml.in
+++ b/interface-definitions/vpn_ipsec.xml.in
@@ -771,11 +771,19 @@
<help>Pool name used for IP address assignments</help>
<completionHelp>
<path>vpn ipsec remote-access pool</path>
- <list>dhcp</list>
+ <list>dhcp radius</list>
</completionHelp>
<valueHelp>
<format>txt</format>
- <description>Pool name</description>
+ <description>Name of predefined IP pool</description>
+ </valueHelp>
+ <valueHelp>
+ <format>dhcp</format>
+ <description>Forward requests for virtual IP addresses to a DHCP server</description>
+ </valueHelp>
+ <valueHelp>
+ <format>radius</format>
+ <description>Forward requests for virtual IP addresses to a RADIUS server</description>
</valueHelp>
<multi/>
</properties>
diff --git a/interface-definitions/vpn_l2tp.xml.in b/interface-definitions/vpn_l2tp.xml.in
index cf31af70f..907bcaadb 100644
--- a/interface-definitions/vpn_l2tp.xml.in
+++ b/interface-definitions/vpn_l2tp.xml.in
@@ -5,6 +5,7 @@
<node name="l2tp" owner="${vyos_conf_scripts_dir}/vpn_l2tp.py">
<properties>
<help>L2TP Virtual Private Network (VPN)</help>
+ <priority>902</priority>
</properties>
<children>
<node name="remote-access">
diff --git a/interface-definitions/vpn_sstp.xml.in b/interface-definitions/vpn_sstp.xml.in
index 3576bac90..5cd331d7f 100644
--- a/interface-definitions/vpn_sstp.xml.in
+++ b/interface-definitions/vpn_sstp.xml.in
@@ -25,7 +25,7 @@
</node>
</children>
</node>
- #include <include/interface/interface-mtu-68-1500.xml.i>
+ #include <include/interface/mtu-68-1500.xml.i>
#include <include/accel-ppp/gateway-address.xml.i>
#include <include/accel-ppp/name-server.xml.i>
<node name="client-ip-pool">
diff --git a/interface-definitions/vrf.xml.in b/interface-definitions/vrf.xml.in
index 9d513945c..2ed50ec5c 100644
--- a/interface-definitions/vrf.xml.in
+++ b/interface-definitions/vrf.xml.in
@@ -26,8 +26,8 @@
</valueHelp>
</properties>
<children>
- #include <include/interface/interface-description.xml.i>
- #include <include/interface/interface-disable.xml.i>
+ #include <include/interface/description.xml.i>
+ #include <include/interface/disable.xml.i>
<node name="protocols">
<properties>
<help>Routing protocol parameters</help>
@@ -85,7 +85,20 @@
<constraintErrorMessage>VRF routing table must be in range from 100 to 65535</constraintErrorMessage>
</properties>
</leafNode>
- #include <include/vni.xml.i>
+ <leafNode name="vni" owner="${vyos_conf_scripts_dir}/vrf_vni.py $VAR(../@)">
+ <properties>
+ <help>Virtual Network Identifier</help>
+ <!-- priority must be after BGP -->
+ <priority>822</priority>
+ <valueHelp>
+ <format>0-16777214</format>
+ <description>VXLAN virtual network identifier</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-16777214"/>
+ </constraint>
+ </properties>
+ </leafNode>
</children>
</tagNode>
</children>
diff --git a/interface-definitions/vrrp.xml.in b/interface-definitions/vrrp.xml.in
index bb551296f..7bbe25347 100644
--- a/interface-definitions/vrrp.xml.in
+++ b/interface-definitions/vrrp.xml.in
@@ -45,7 +45,7 @@
<properties>
<help>VRRP password</help>
<valueHelp>
- <format>text</format>
+ <format>txt</format>
<description>Password string (up to 8 characters)</description>
</valueHelp>
<constraint>
@@ -285,7 +285,7 @@
<multi/>
<help>Sync group member</help>
<valueHelp>
- <format>text</format>
+ <format>txt</format>
<description>VRRP group name</description>
</valueHelp>
<completionHelp>
diff --git a/op-mode-definitions/containers.xml.in b/op-mode-definitions/containers.xml.in
index a22549dd9..b2b318786 100644
--- a/op-mode-definitions/containers.xml.in
+++ b/op-mode-definitions/containers.xml.in
@@ -17,6 +17,19 @@
</node>
</children>
</node>
+ <node name="connect">
+ <children>
+ <tagNode name="container">
+ <properties>
+ <help>Attach to a running container</help>
+ <completionHelp>
+ <path>container name</path>
+ </completionHelp>
+ </properties>
+ <command>sudo podman exec --interactive --tty "$3" /bin/sh</command>
+ </tagNode>
+ </children>
+ </node>
<node name="delete">
<children>
<node name="container">
@@ -27,6 +40,9 @@
<tagNode name="image">
<properties>
<help>Delete container image</help>
+ <completionHelp>
+ <script>sudo podman image ls -q</script>
+ </completionHelp>
</properties>
<command>sudo ${vyos_op_scripts_dir}/containers_op.py --remove "${4}"</command>
</tagNode>
@@ -48,6 +64,15 @@
</properties>
<command>sudo ${vyos_op_scripts_dir}/containers_op.py --image</command>
</leafNode>
+ <tagNode name="log">
+ <properties>
+ <help>Show logs from a given container</help>
+ <completionHelp>
+ <path>container name</path>
+ </completionHelp>
+ </properties>
+ <command>sudo podman logs --names "$4"</command>
+ </tagNode>
<leafNode name="network">
<properties>
<help>Show available container networks</help>
@@ -56,6 +81,52 @@
</leafNode>
</children>
</node>
+ <node name="log">
+ <children>
+ <tagNode name="container">
+ <properties>
+ <help>Show logs from a given container</help>
+ <completionHelp>
+ <path>container name</path>
+ </completionHelp>
+ </properties>
+ <command>sudo podman logs --names "$4"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ <node name="restart">
+ <children>
+ <tagNode name="container">
+ <properties>
+ <help>Restart a given container</help>
+ <completionHelp>
+ <path>container name</path>
+ </completionHelp>
+ </properties>
+ <command>sudo podman restart "$3"</command>
+ </tagNode>
+ </children>
+ </node>
+ <node name="update">
+ <children>
+ <node name="container">
+ <properties>
+ <help>Update a container image</help>
+ </properties>
+ <children>
+ <tagNode name="image">
+ <properties>
+ <help>Delete container image</help>
+ <completionHelp>
+ <path>container name</path>
+ </completionHelp>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/containers_op.py --update "${4}"</command>
+ </tagNode>
+ </children>
+ </node>
</children>
</node>
</interfaceDefinition>
diff --git a/op-mode-definitions/dns-forwarding.xml.in b/op-mode-definitions/dns-forwarding.xml.in
index 36fe6b5ef..6574f2319 100644
--- a/op-mode-definitions/dns-forwarding.xml.in
+++ b/op-mode-definitions/dns-forwarding.xml.in
@@ -59,9 +59,6 @@
</children>
</node>
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="dns">
<properties>
diff --git a/op-mode-definitions/generate-ipsec-profile.xml.in b/op-mode-definitions/generate-ipsec-profile.xml.in
index be9227971..8d1051b94 100644
--- a/op-mode-definitions/generate-ipsec-profile.xml.in
+++ b/op-mode-definitions/generate-ipsec-profile.xml.in
@@ -100,37 +100,6 @@
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/ikev2_profile_generator.py --os windows --connection "$5" --remote "$7" --name "$9"</command>
- <children>
- <tagNode name="profile">
- <properties>
- <help>Profile name as seen under system profiles</help>
- <completionHelp>
- <list>&lt;name&gt;</list>
- </completionHelp>
- </properties>
- <command>${vyos_op_scripts_dir}/ikev2_profile_generator.py --os windows --connection "$5" --remote "$7" --name "$9" --profile "${11}"</command>
- </tagNode>
- </children>
- </tagNode>
- <tagNode name="profile">
- <properties>
- <help>Profile name as seen under system profiles</help>
- <completionHelp>
- <list>&lt;name&gt;</list>
- </completionHelp>
- </properties>
- <command>${vyos_op_scripts_dir}/ikev2_profile_generator.py --os windows --connection "$5" --remote "$7" --profile "$9"</command>
- <children>
- <tagNode name="name">
- <properties>
- <help>Connection name as seen in the VPN application</help>
- <completionHelp>
- <list>&lt;name&gt;</list>
- </completionHelp>
- </properties>
- <command>${vyos_op_scripts_dir}/ikev2_profile_generator.py --os windows --connection "$5" --remote "$7" --profile "$9" --name "${11}"</command>
- </tagNode>
- </children>
</tagNode>
</children>
</tagNode>
diff --git a/op-mode-definitions/include/bgp/afi-common.xml.i b/op-mode-definitions/include/bgp/afi-common.xml.i
index 7fc59f3b0..4d5f56656 100644
--- a/op-mode-definitions/include/bgp/afi-common.xml.i
+++ b/op-mode-definitions/include/bgp/afi-common.xml.i
@@ -7,23 +7,33 @@
</completionHelp>
</properties>
<children>
- <leafNode name="exact-match">
- <properties>
- <help>Exact match of the communities</help>
- </properties>
- <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
- </leafNode>
+ #include <include/bgp/exact-match.xml.i>
</children>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
</tagNode>
<tagNode name="large-community">
<properties>
- <help>List of large-community numbers</help>
+ <help>Display routes matching the large-communities</help>
<completionHelp>
<list>AA:BB:CC</list>
</completionHelp>
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/bgp/exact-match.xml.i>
+ </children>
+</tagNode>
+<tagNode name="large-community-list">
+ <properties>
+ <help>Display routes matching the large-community-list</help>
+ <completionHelp>
+ <path>policy large-community-list</path>
+ </completionHelp>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+ <children>
+ #include <include/bgp/exact-match.xml.i>
+ </children>
</tagNode>
<leafNode name="statistics">
<properties>
diff --git a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i
index f1b699347..a51595b7f 100644
--- a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i
+++ b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-common.xml.i
@@ -22,12 +22,7 @@
</properties>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
</leafNode>
- <leafNode name="exact-match">
- <properties>
- <help>Exact match of the communities</help>
- </properties>
- <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
- </leafNode>
+ #include <include/bgp/exact-match.xml.i>
<leafNode name="graceful-shutdown">
<properties>
<help>Graceful shutdown (well-known community)</help>
@@ -105,12 +100,7 @@
</completionHelp>
</properties>
<children>
- <leafNode name="exact-match">
- <properties>
- <help>Show BGP routes exactly matching specified community list</help>
- </properties>
- <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
- </leafNode>
+ #include <include/bgp/exact-match.xml.i>
</children>
<command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
</tagNode>
diff --git a/op-mode-definitions/include/bgp/afi-ipv4-ipv6-vpn.xml.i b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-vpn.xml.i
new file mode 100644
index 000000000..ba6edb256
--- /dev/null
+++ b/op-mode-definitions/include/bgp/afi-ipv4-ipv6-vpn.xml.i
@@ -0,0 +1,23 @@
+<!-- included start from bgp/afi-ipv4-ipv6-vpn.xml.i -->
+<tagNode name="vpn">
+ <properties>
+ <help>Network in the BGP routing table to display</help>
+ <completionHelp>
+ <list>&lt;x.x.x.x&gt; &lt;x.x.x.x/x&gt; &lt;h:h:h:h:h:h:h:h&gt; &lt;h:h:h:h:h:h:h:h/x&gt;</list>
+ </completionHelp>
+ </properties>
+ <children>
+ #include <include/bgp/prefix-bestpath-multipath.xml.i>
+ </children>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</tagNode>
+<node name="vpn">
+ <properties>
+ <help>VPN Address Family modifier</help>
+ </properties>
+ <children>
+ #include <include/bgp/afi-common.xml.i>
+ #include <include/bgp/afi-ipv4-ipv6-common.xml.i>
+ </children>
+</node>
+<!-- included end -->
diff --git a/op-mode-definitions/include/bgp/exact-match.xml.i b/op-mode-definitions/include/bgp/exact-match.xml.i
new file mode 100644
index 000000000..49026db9b
--- /dev/null
+++ b/op-mode-definitions/include/bgp/exact-match.xml.i
@@ -0,0 +1,8 @@
+<!-- included start from bgp/exact-match.xml.i -->
+<leafNode name="exact-match">
+ <properties>
+ <help>Exact match of the communities</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/vtysh_wrapper.sh $@</command>
+</leafNode>
+<!-- included end -->
diff --git a/op-mode-definitions/include/bgp/show-bgp-common.xml.i b/op-mode-definitions/include/bgp/show-bgp-common.xml.i
index b86b09056..0664b11fc 100644
--- a/op-mode-definitions/include/bgp/show-bgp-common.xml.i
+++ b/op-mode-definitions/include/bgp/show-bgp-common.xml.i
@@ -20,6 +20,7 @@
<children>
#include <include/bgp/afi-common.xml.i>
#include <include/bgp/afi-ipv4-ipv6-common.xml.i>
+ #include <include/bgp/afi-ipv4-ipv6-vpn.xml.i>
</children>
</node>
<tagNode name="ipv6">
@@ -41,6 +42,7 @@
<children>
#include <include/bgp/afi-common.xml.i>
#include <include/bgp/afi-ipv4-ipv6-common.xml.i>
+ #include <include/bgp/afi-ipv4-ipv6-vpn.xml.i>
</children>
</node>
<node name="l2vpn">
diff --git a/op-mode-definitions/ipv4-route.xml.in b/op-mode-definitions/ipv4-route.xml.in
index aab3df0f1..8f001d5bb 100644
--- a/op-mode-definitions/ipv4-route.xml.in
+++ b/op-mode-definitions/ipv4-route.xml.in
@@ -20,11 +20,7 @@
</node>
</children>
</node>
-
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="ip">
<properties>
@@ -56,7 +52,6 @@
</tagNode>
</children>
</node>
-
<node name="route">
<properties>
<help>Reset IP route</help>
@@ -68,7 +63,6 @@
</properties>
<command>sudo ip route flush cache</command>
</leafNode>
-
<tagNode name="cache">
<properties>
<help>Flush the kernel route cache for a given route</help>
diff --git a/op-mode-definitions/ipv6-route.xml.in b/op-mode-definitions/ipv6-route.xml.in
index 7f188fdb2..5f20444d4 100644
--- a/op-mode-definitions/ipv6-route.xml.in
+++ b/op-mode-definitions/ipv6-route.xml.in
@@ -28,11 +28,7 @@
</node>
</children>
</node>
-
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="ipv6">
<properties>
@@ -64,7 +60,6 @@
</tagNode>
</children>
</node>
-
<node name="route">
<properties>
<help>Reset IPv6 route</help>
@@ -76,7 +71,6 @@
</properties>
<command>sudo ip -f inet6 route flush cache</command>
</leafNode>
-
<tagNode name="cache">
<properties>
<help>Flush the kernel IPv6 route cache for a given route</help>
diff --git a/op-mode-definitions/monitor-protocol.xml.in b/op-mode-definitions/monitor-protocol.xml.in
index 6a6bd50f3..f3af3575c 100644
--- a/op-mode-definitions/monitor-protocol.xml.in
+++ b/op-mode-definitions/monitor-protocol.xml.in
@@ -263,13 +263,14 @@
</node>
<node name="ospf">
<properties>
- <help>Monitor the Open Shortest Path First (OSPF) protocol</help>
+ <help>Monitor Open Shortest Path First (OSPF) protocol</help>
</properties>
<children>
#include <include/monitor-background.xml.i>
-
-
<node name="disable">
+ <properties>
+ <help>Disable Open Shortest Path First (OSPF) debugging</help>
+ </properties>
<children>
<node name="event">
<properties>
@@ -458,6 +459,9 @@
</children>
</node>
<node name="enable">
+ <properties>
+ <help>Enable Open Shortest Path First (OSPF) debugging</help>
+ </properties>
<children>
<node name="event">
<properties>
diff --git a/op-mode-definitions/nhrp.xml.in b/op-mode-definitions/nhrp.xml.in
index 9e746cc35..89508e2be 100644
--- a/op-mode-definitions/nhrp.xml.in
+++ b/op-mode-definitions/nhrp.xml.in
@@ -50,13 +50,13 @@
<properties>
<help>Show NHRP interface connection information</help>
</properties>
- <command>if [ -f /var/run/opennhrp.pid ]; then sudo opennhrpctl interface show; else echo OpenNHRP is not running.; fi</command>
+ <command>if pgrep opennhrp >/dev/null; then sudo opennhrpctl interface show; else echo OpenNHRP is not running; fi</command>
</leafNode>
<leafNode name="tunnel">
<properties>
<help>Show NHRP tunnel connection information</help>
</properties>
- <command>if [ -f /var/run/opennhrp.pid ]; then sudo opennhrpctl show ; else echo OpenNHRP is not running.; fi</command>
+ <command>if pgrep opennhrp >/dev/null; then sudo opennhrpctl show ; else echo OpenNHRP is not running; fi</command>
</leafNode>
</children>
</node>
diff --git a/op-mode-definitions/openvpn.xml.in b/op-mode-definitions/openvpn.xml.in
index 781fbdc9d..73cbbe501 100644
--- a/op-mode-definitions/openvpn.xml.in
+++ b/op-mode-definitions/openvpn.xml.in
@@ -1,11 +1,11 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="openvpn">
+ <properties>
+ <help>Reset OpenVPN client/server connections</help>
+ </properties>
<children>
<tagNode name="client">
<properties>
diff --git a/op-mode-definitions/pppoe-server.xml.in b/op-mode-definitions/pppoe-server.xml.in
index 6efdc5a48..835e03aab 100644
--- a/op-mode-definitions/pppoe-server.xml.in
+++ b/op-mode-definitions/pppoe-server.xml.in
@@ -40,9 +40,6 @@
</children>
</node>
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="pppoe-server">
<properties>
diff --git a/op-mode-definitions/reset-conntrack.xml.in b/op-mode-definitions/reset-conntrack.xml.in
index 827ba4af4..9c8265f77 100644
--- a/op-mode-definitions/reset-conntrack.xml.in
+++ b/op-mode-definitions/reset-conntrack.xml.in
@@ -1,9 +1,6 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="conntrack">
<properties>
diff --git a/op-mode-definitions/reset-vpn.xml.in b/op-mode-definitions/reset-vpn.xml.in
index 71dbb4ed9..94ee1c7df 100644
--- a/op-mode-definitions/reset-vpn.xml.in
+++ b/op-mode-definitions/reset-vpn.xml.in
@@ -1,9 +1,6 @@
<?xml version="1.0"?>
<interfaceDefinition>
<node name="reset">
- <properties>
- <help>Reset a service</help>
- </properties>
<children>
<node name="vpn">
<properties>
diff --git a/op-mode-definitions/restart-frr.xml.in b/op-mode-definitions/restart-frr.xml.in
index 96ad1a650..475bd1ee8 100644
--- a/op-mode-definitions/restart-frr.xml.in
+++ b/op-mode-definitions/restart-frr.xml.in
@@ -2,62 +2,66 @@
<interfaceDefinition>
<node name="restart">
<children>
- <node name="frr">
+ <leafNode name="all">
<properties>
- <help>Restart FRRouting daemons</help>
+ <help>Restart all routing daemons</help>
</properties>
<command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart</command>
- <children>
- <leafNode name="bfdd">
- <properties>
- <help>Restart Bidirectional Forwarding Detection daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bfdd</command>
- </leafNode>
- <leafNode name="bgpd">
- <properties>
- <help>Restart Border Gateway Protocol daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bgpd</command>
- </leafNode>
- <leafNode name="ospfd">
- <properties>
- <help>Restart OSPFv2 daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospfd</command>
- </leafNode>
- <leafNode name="ospf6d">
- <properties>
- <help>Restart OSPFv3 daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospf6d</command>
- </leafNode>
- <leafNode name="ripd">
- <properties>
- <help>Restart Routing Information Protocol daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripd</command>
- </leafNode>
- <leafNode name="ripngd">
- <properties>
- <help>Restart RIPng daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripngd</command>
- </leafNode>
- <leafNode name="staticd">
- <properties>
- <help>Restart Static Route daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon staticd</command>
- </leafNode>
- <leafNode name="zebra">
- <properties>
- <help>Restart IP routing manager daemon</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon zebra</command>
- </leafNode>
- </children>
- </node>
+ </leafNode>
+ <leafNode name="bfd">
+ <properties>
+ <help>Restart Bidirectional Forwarding Detection (BFD) daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bfdd</command>
+ </leafNode>
+ <leafNode name="bgp">
+ <properties>
+ <help>Restart Border Gateway Protocol (BGP) routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon bgpd</command>
+ </leafNode>
+ <leafNode name="isis">
+ <properties>
+ <help>Restart Intermediate System to Intermediate System (IS-IS) routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon isisd</command>
+ </leafNode>
+ <leafNode name="ospf">
+ <properties>
+ <help>Restart Open Shortest Path First (OSPF) routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospfd</command>
+ </leafNode>
+ <leafNode name="ospfv3">
+ <properties>
+ <help>Restart IPv6 Open Shortest Path First (OSPFv3) routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ospf6d</command>
+ </leafNode>
+ <leafNode name="rip">
+ <properties>
+ <help>Restart Routing Information Protocol (RIP) routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripd</command>
+ </leafNode>
+ <leafNode name="ripng">
+ <properties>
+ <help>Restart Routing Information Protocol NG (RIPng) routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon ripngd</command>
+ </leafNode>
+ <leafNode name="static">
+ <properties>
+ <help>Restart static routing daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon staticd</command>
+ </leafNode>
+ <leafNode name="zebra">
+ <properties>
+ <help>Restart Routing Information Base (RIB) manager daemon</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/restart_frr.py --action restart --daemon zebra</command>
+ </leafNode>
</children>
</node>
</interfaceDefinition>
diff --git a/op-mode-definitions/show-system.xml.in b/op-mode-definitions/show-system.xml.in
index 5e9bf719e..18a28868d 100644
--- a/op-mode-definitions/show-system.xml.in
+++ b/op-mode-definitions/show-system.xml.in
@@ -55,12 +55,6 @@
</properties>
<command>${vyos_op_scripts_dir}/show_cpu.py</command>
</leafNode>
- <leafNode name= "integrity">
- <properties>
- <help>Checks overall system integrity</help>
- </properties>
- <command>sudo ${vyos_op_scripts_dir}/show_system_integrity.py</command>
- </leafNode>
<leafNode name="kernel-messages">
<properties>
<help>Show messages in kernel ring buffer</help>
diff --git a/op-mode-definitions/show-vpn.xml.in b/op-mode-definitions/show-vpn.xml.in
deleted file mode 100644
index 3fbc74ad1..000000000
--- a/op-mode-definitions/show-vpn.xml.in
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<interfaceDefinition>
- <node name="show">
- <children>
- <node name="vpn">
- <properties>
- <help>Show active remote access Virtual Private Network (VPN) sessions</help>
- </properties>
- <children>
- <leafNode name="remote-access">
- <properties>
- <help>Show active VPN server sessions</help>
- </properties>
- <command>${vyos_op_scripts_dir}/show_vpn_ra.py</command>
- </leafNode>
- </children>
- </node>
- </children>
- </node>
-</interfaceDefinition>
diff --git a/op-mode-definitions/terminal.xml.in b/op-mode-definitions/terminal.xml.in
index 9c4e629cb..2a76de146 100644
--- a/op-mode-definitions/terminal.xml.in
+++ b/op-mode-definitions/terminal.xml.in
@@ -40,7 +40,6 @@
</properties>
<command>builtin $3</command>
</tagNode>
-
<node name="console">
<properties>
<help>Control console behaviors</help>
@@ -54,13 +53,11 @@
</leafNode>
</children>
</node>
-
<node name="terminal">
<properties>
<help>Control terminal behaviors</help>
</properties>
<children>
-
<node name="key">
<properties>
<help>Set key behaviors</help>
@@ -77,7 +74,6 @@
</tagNode>
</children>
</node>
-
<node name="pager">
<properties>
<help>Set terminal pager to default (less)</help>
@@ -93,7 +89,6 @@
</properties>
<command>VYATTA_PAGER=$4</command>
</tagNode>
-
<tagNode name="length">
<properties>
<help>Set terminal to given number of rows (0 disables paging)</help>
@@ -103,7 +98,6 @@
</properties>
<command>if [ "$4" -eq 0 ]; then VYATTA_PAGER=cat; else VYATTA_PAGER=${_vyatta_default_pager}; stty rows $4; fi</command>
</tagNode>
-
<tagNode name="width">
<properties>
<help>Set terminal to given number of columns</help>
@@ -117,6 +111,4 @@
</node>
</children>
</node>
-
-
</interfaceDefinition>
diff --git a/op-mode-definitions/vpn-ipsec.xml.in b/op-mode-definitions/vpn-ipsec.xml.in
index 20f275e9b..3d997c143 100644
--- a/op-mode-definitions/vpn-ipsec.xml.in
+++ b/op-mode-definitions/vpn-ipsec.xml.in
@@ -140,6 +140,12 @@
</properties>
<command>sudo ip xfrm policy list</command>
</node>
+ <leafNode name="remote-access">
+ <properties>
+ <help>Show active VPN server sessions</help>
+ </properties>
+ <command>${vyos_op_scripts_dir}/show_vpn_ra.py</command>
+ </leafNode>
<node name="sa">
<properties>
<help>Show all active IPSec Security Associations (SA)</help>
@@ -178,7 +184,7 @@
<command>if pgrep charon >/dev/null ; then sudo /usr/sbin/ipsec statusall ; else echo "IPSec process not running" ; fi</command>
</node>
</children>
- <command>if pgrep charon >/dev/null ; then sudo /usr/libexec/vyos/op_mode/show_ipsec_sa.py ; else echo "IPSec process not running" ; fi</command>
+ <command>if pgrep charon >/dev/null ; then sudo ${vyos_op_scripts_dir}/show_ipsec_sa.py ; else echo "IPSec process not running" ; fi</command>
</node>
<node name="state">
<properties>
diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py
index 0969a5353..e15579b95 100644
--- a/python/vyos/configdict.py
+++ b/python/vyos/configdict.py
@@ -108,16 +108,20 @@ def leaf_node_changed(conf, path):
"""
Check if a leaf node was altered. If it has been altered - values has been
changed, or it was added/removed, we will return a list containing the old
- value(s). If nothing has been changed, None is returned
+ value(s). If nothing has been changed, None is returned.
+
+ NOTE: path must use the real CLI node name (e.g. with a hyphen!)
"""
from vyos.configdiff import get_config_diff
D = get_config_diff(conf, key_mangling=('-', '_'))
D.set_level(conf.get_level())
(new, old) = D.get_value_diff(path)
if new != old:
+ if old is None:
+ return ['']
if isinstance(old, str):
return [old]
- elif isinstance(old, list):
+ if isinstance(old, list):
if isinstance(new, str):
new = [new]
elif isinstance(new, type(None)):
diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py
index 4279e6982..7f49aa9af 100644
--- a/python/vyos/configverify.py
+++ b/python/vyos/configverify.py
@@ -237,8 +237,8 @@ def verify_interface_exists(ifname):
Common helper function used by interface implementations to perform
recurring validation if an interface actually exists.
"""
- from netifaces import interfaces
- if ifname not in interfaces():
+ import os
+ if not os.path.exists(f'/sys/class/net/{ifname}'):
raise ConfigError(f'Interface "{ifname}" does not exist!')
def verify_source_interface(config):
diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index 03006c383..dacdbdef2 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -13,6 +13,7 @@
# 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/>.
+import os
directories = {
"data": "/usr/share/vyos/",
@@ -34,7 +35,7 @@ cfg_vintage = 'vyos'
commit_lock = '/opt/vyatta/config/.lock'
-version_file = '/usr/share/vyos/component-versions.json'
+component_version_json = os.path.join(directories['data'], 'component-versions.json')
https_data = {
'listen_addresses' : { '*': ['_'] }
diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py
index 14f64a8de..27073b266 100644
--- a/python/vyos/ifconfig/bridge.py
+++ b/python/vyos/ifconfig/bridge.py
@@ -366,5 +366,4 @@ class BridgeIf(Interface):
cmd = f'bridge vlan add dev {interface} vid {native_vlan_id} pvid untagged master'
self._cmd(cmd)
- # call base class first
super().update(config)
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index a1928ba51..45a220e22 100755
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -52,6 +52,10 @@ from vyos.ifconfig.vrrp import VRRP
from vyos.ifconfig.operational import Operational
from vyos.ifconfig import Section
+from netaddr import EUI
+from netaddr import mac_unix_expanded
+from random import getrandbits
+
class Interface(Control):
# This is the class which will be used to create
# self.operational, it allows subclasses, such as
@@ -389,6 +393,31 @@ class Interface(Control):
"""
return self.get_interface('mac')
+ def get_mac_synthetic(self):
+ """
+ Get a synthetic MAC address. This is a common method which can be called
+ from derived classes to overwrite the get_mac() call in a generic way.
+
+ NOTE: Tunnel interfaces have no "MAC" address by default. The content
+ of the 'address' file in /sys/class/net/device contains the
+ local-ip thus we generate a random MAC address instead
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').get_mac()
+ '00:50:ab:cd:ef:00'
+ """
+ # we choose 40 random bytes for the MAC address, this gives
+ # us e.g. EUI('00-EA-EE-D6-A3-C8') or EUI('00-41-B9-0D-F2-2A')
+ tmp = EUI(getrandbits(48)).value
+ # set locally administered bit in MAC address
+ tmp |= 0xf20000000000
+ # convert integer to "real" MAC address representation
+ mac = EUI(hex(tmp).split('x')[-1])
+ # change dialect to use : as delimiter instead of -
+ mac.dialect = mac_unix_expanded
+ return str(mac)
+
def set_mac(self, mac):
"""
Set interface MAC (Media Access Contrl) address to given value.
@@ -436,6 +465,62 @@ class Interface(Control):
"""
return self.set_interface('arp_cache_tmo', tmo)
+ def set_tcp_ipv4_mss(self, mss):
+ """
+ Set IPv4 TCP MSS value advertised when TCP SYN packets leave this
+ interface. Value is in bytes.
+
+ A value of 0 will disable the MSS adjustment
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').set_tcp_ipv4_mss(1340)
+ """
+ iptables_bin = 'iptables'
+ base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = self._cmd(f'{iptables_bin}-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ # remove OLD MSS mangling configuration
+ line = line.replace('-A FORWARD', '-D FORWARD')
+ self._cmd(f'{iptables_bin} -t mangle {line}')
+
+ cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS'
+ if mss == 'clamp-mss-to-pmtu':
+ self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu')
+ elif int(mss) > 0:
+ # probably add option to clamp only if bigger:
+ low_mss = str(int(mss) + 1)
+ self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}')
+
+ def set_tcp_ipv6_mss(self, mss):
+ """
+ Set IPv6 TCP MSS value advertised when TCP SYN packets leave this
+ interface. Value is in bytes.
+
+ A value of 0 will disable the MSS adjustment
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').set_tcp_mss(1320)
+ """
+ iptables_bin = 'ip6tables'
+ base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = self._cmd(f'{iptables_bin}-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ # remove OLD MSS mangling configuration
+ line = line.replace('-A FORWARD', '-D FORWARD')
+ self._cmd(f'{iptables_bin} -t mangle {line}')
+
+ cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS'
+ if mss == 'clamp-mss-to-pmtu':
+ self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu')
+ elif int(mss) > 0:
+ # probably add option to clamp only if bigger:
+ low_mss = str(int(mss) + 1)
+ self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}')
+
def set_arp_filter(self, arp_filter):
"""
Filter ARP requests
@@ -1202,6 +1287,16 @@ class Interface(Control):
# checked before
self.set_vrf(config.get('vrf', ''))
+ # Configure MSS value for IPv4 TCP connections
+ tmp = dict_search('ip.adjust_mss', config)
+ value = tmp if (tmp != None) else '0'
+ self.set_tcp_ipv4_mss(value)
+
+ # Configure MSS value for IPv6 TCP connections
+ tmp = dict_search('ipv6.adjust_mss', config)
+ value = tmp if (tmp != None) else '0'
+ self.set_tcp_ipv6_mss(value)
+
# Configure ARP cache timeout in milliseconds - has default value
tmp = dict_search('ip.arp_cache_timeout', config)
value = tmp if (tmp != None) else '30'
diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py
index 65575cf99..9153863de 100644
--- a/python/vyos/ifconfig/pppoe.py
+++ b/python/vyos/ifconfig/pppoe.py
@@ -1,4 +1,4 @@
-# Copyright 2020 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2020-2021 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
@@ -14,12 +14,11 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
from vyos.ifconfig.interface import Interface
+from vyos.util import get_interface_config
@Interface.register
class PPPoEIf(Interface):
- default = {
- 'type': 'pppoe',
- }
+ iftype = 'pppoe'
definition = {
**Interface.definition,
**{
@@ -28,7 +27,31 @@ class PPPoEIf(Interface):
},
}
- # stub this interface is created in the configure script
+ def _remove_routes(self, vrf=''):
+ # Always delete default routes when interface is removed
+ if vrf:
+ vrf = f'-c "vrf {vrf}"'
+ self._cmd(f'vtysh -c "conf t" {vrf} -c "no ip route 0.0.0.0/0 {self.ifname} tag 210"')
+ self._cmd(f'vtysh -c "conf t" {vrf} -c "no ipv6 route ::/0 {self.ifname} tag 210"')
+
+ def remove(self):
+ """
+ Remove interface from operating system. Removing the interface
+ deconfigures all assigned IP addresses and clear possible DHCP(v6)
+ client processes.
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> i = Interface('pppoe0')
+ >>> i.remove()
+ """
+
+ tmp = get_interface_config(self.ifname)
+ vrf = ''
+ if 'master' in tmp:
+ self._remove_routes(tmp['master'])
+
+ # remove bond master which places members in disabled state
+ super().remove()
def _create(self):
# we can not create this interface as it is managed outside
@@ -37,3 +60,84 @@ class PPPoEIf(Interface):
def _delete(self):
# we can not create this interface as it is managed outside
pass
+
+ def del_addr(self, addr):
+ # we can not create this interface as it is managed outside
+ pass
+
+ def get_mac(self):
+ """ Get a synthetic MAC address. """
+ return self.get_mac_synthetic()
+
+ def update(self, config):
+ """ General helper function which works on a dictionary retrived by
+ get_config_dict(). It's main intention is to consolidate the scattered
+ interface setup code and provide a single point of entry when workin
+ on any interface. """
+
+ # remove old routes from an e.g. old VRF assignment
+ vrf = ''
+ if 'vrf_old' in config:
+ vrf = config['vrf_old']
+ self._remove_routes(vrf)
+
+ # DHCPv6 PD handling is a bit different on PPPoE interfaces, as we do
+ # not require an 'address dhcpv6' CLI option as with other interfaces
+ if 'dhcpv6_options' in config and 'pd' in config['dhcpv6_options']:
+ self.set_dhcpv6(True)
+ else:
+ self.set_dhcpv6(False)
+
+ super().update(config)
+
+ if 'default_route' not in config or config['default_route'] == 'none':
+ return
+
+ #
+ # Set default routes pointing to pppoe interface
+ #
+ vrf = ''
+ sed_opt = '^ip route'
+
+ install_v4 = True
+ install_v6 = True
+
+ # generate proper configuration string when VRFs are in use
+ if 'vrf' in config:
+ tmp = config['vrf']
+ vrf = f'-c "vrf {tmp}"'
+ sed_opt = f'vrf {tmp}'
+
+ if config['default_route'] == 'auto':
+ # only add route if there is no default route present
+ tmp = self._cmd(f'vtysh -c "show running-config staticd no-header" | sed -n "/{sed_opt}/,/!/p"')
+ for line in tmp.splitlines():
+ line = line.lstrip()
+ if line.startswith('ip route 0.0.0.0/0'):
+ install_v4 = False
+ continue
+
+ if 'ipv6' in config and line.startswith('ipv6 route ::/0'):
+ install_v6 = False
+ continue
+
+ elif config['default_route'] == 'force':
+ # Force means that all static routes are replaced with the ones from this interface
+ tmp = self._cmd(f'vtysh -c "show running-config staticd no-header" | sed -n "/{sed_opt}/,/!/p"')
+ for line in tmp.splitlines():
+ if self.ifname in line:
+ # It makes no sense to remove a route with our interface and the later re-add it.
+ # This will only make traffic disappear - which is a no-no!
+ continue
+
+ line = line.lstrip()
+ if line.startswith('ip route 0.0.0.0/0'):
+ self._cmd(f'vtysh -c "conf t" {vrf} -c "no {line}"')
+
+ if 'ipv6' in config and line.startswith('ipv6 route ::/0'):
+ self._cmd(f'vtysh -c "conf t" {vrf} -c "no {line}"')
+
+ if install_v4:
+ self._cmd(f'vtysh -c "conf t" {vrf} -c "ip route 0.0.0.0/0 {self.ifname} tag 210"')
+ if install_v6 and 'ipv6' in config:
+ self._cmd(f'vtysh -c "conf t" {vrf} -c "ipv6 route ::/0 {self.ifname} tag 210"')
diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py
index 173a90bb4..0e4447b9e 100644
--- a/python/vyos/ifconfig/section.py
+++ b/python/vyos/ifconfig/section.py
@@ -46,7 +46,7 @@ class Section:
return klass
@classmethod
- def _basename (cls, name, vlan):
+ def _basename(cls, name, vlan, vrrp):
"""
remove the number at the end of interface name
name: name of the interface
@@ -56,16 +56,18 @@ class Section:
name = name.rstrip('.')
if vlan:
name = name.rstrip('0123456789.')
+ if vrrp:
+ name = name.rstrip('0123456789v')
return name
@classmethod
- def section(cls, name, vlan=True):
+ def section(cls, name, vlan=True, vrrp=True):
"""
return the name of a section an interface should be under
name: name of the interface (eth0, dum1, ...)
vlan: should we try try to remove the VLAN from the number
"""
- name = cls._basename(name, vlan)
+ name = cls._basename(name, vlan, vrrp)
if name in cls._prefixes:
return cls._prefixes[name].definition['section']
@@ -79,8 +81,8 @@ class Section:
return list(set([cls._prefixes[_].definition['section'] for _ in cls._prefixes]))
@classmethod
- def klass(cls, name, vlan=True):
- name = cls._basename(name, vlan)
+ def klass(cls, name, vlan=True, vrrp=True):
+ name = cls._basename(name, vlan, vrrp)
if name in cls._prefixes:
return cls._prefixes[name]
raise ValueError(f'No type found for interface name: {name}')
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 64c735824..5258a2cb1 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -16,10 +16,6 @@
# https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/
# https://community.hetzner.com/tutorials/linux-setup-gre-tunnel
-from netaddr import EUI
-from netaddr import mac_unix_expanded
-from random import getrandbits
-
from vyos.ifconfig.interface import Interface
from vyos.util import dict_search
from vyos.validate import assert_list
@@ -163,28 +159,8 @@ class TunnelIf(Interface):
self._cmd(cmd.format(**self.config))
def get_mac(self):
- """
- Get current interface MAC (Media Access Contrl) address used.
-
- NOTE: Tunnel interfaces have no "MAC" address by default. The content
- of the 'address' file in /sys/class/net/device contains the
- local-ip thus we generate a random MAC address instead
-
- Example:
- >>> from vyos.ifconfig import Interface
- >>> Interface('eth0').get_mac()
- '00:50:ab:cd:ef:00'
- """
- # we choose 40 random bytes for the MAC address, this gives
- # us e.g. EUI('00-EA-EE-D6-A3-C8') or EUI('00-41-B9-0D-F2-2A')
- tmp = EUI(getrandbits(48)).value
- # set locally administered bit in MAC address
- tmp |= 0xf20000000000
- # convert integer to "real" MAC address representation
- mac = EUI(hex(tmp).split('x')[-1])
- # change dialect to use : as delimiter instead of -
- mac.dialect = mac_unix_expanded
- return str(mac)
+ """ Get a synthetic MAC address. """
+ return self.get_mac_synthetic()
def update(self, config):
""" General helper function which works on a dictionary retrived by
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index c4cf2fbbf..28b5e2991 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -17,9 +17,6 @@ import os
import time
from datetime import timedelta
-from netaddr import EUI
-from netaddr import mac_unix_expanded
-from random import getrandbits
from hurry.filesize import size
from hurry.filesize import alternative
@@ -159,28 +156,8 @@ class WireGuardIf(Interface):
}
def get_mac(self):
- """
- Get current interface MAC (Media Access Contrl) address used.
-
- NOTE: Tunnel interfaces have no "MAC" address by default. The content
- of the 'address' file in /sys/class/net/device contains the
- local-ip thus we generate a random MAC address instead
-
- Example:
- >>> from vyos.ifconfig import Interface
- >>> Interface('eth0').get_mac()
- '00:50:ab:cd:ef:00'
- """
- # we choose 40 random bytes for the MAC address, this gives
- # us e.g. EUI('00-EA-EE-D6-A3-C8') or EUI('00-41-B9-0D-F2-2A')
- tmp = EUI(getrandbits(48)).value
- # set locally administered bit in MAC address
- tmp |= 0xf20000000000
- # convert integer to "real" MAC address representation
- mac = EUI(hex(tmp).split('x')[-1])
- # change dialect to use : as delimiter instead of -
- mac.dialect = mac_unix_expanded
- return str(mac)
+ """ Get a synthetic MAC address. """
+ return self.get_mac_synthetic()
def update(self, config):
""" General helper function which works on a dictionary retrived by
diff --git a/python/vyos/migrator.py b/python/vyos/migrator.py
index 9a5fdef2f..4574bb6d1 100644
--- a/python/vyos/migrator.py
+++ b/python/vyos/migrator.py
@@ -15,6 +15,7 @@
import sys
import os
+import json
import subprocess
import vyos.version
import vyos.defaults
@@ -165,6 +166,20 @@ class Migrator(object):
versions_string,
os_version_string)
+ def save_json_record(self, component_versions: dict):
+ """
+ Write component versions to a json file
+ """
+ mask = os.umask(0o113)
+ version_file = vyos.defaults.component_version_json
+ try:
+ with open(version_file, 'w') as f:
+ f.write(json.dumps(component_versions, indent=2, sort_keys=True))
+ except OSError:
+ pass
+ finally:
+ os.umask(mask)
+
def run(self):
"""
Gather component versions from config file and system.
@@ -182,6 +197,9 @@ class Migrator(object):
sys_versions = systemversions.get_system_versions()
+ # save system component versions in json file for easy reference
+ self.save_json_record(sys_versions)
+
rev_versions = self.run_migration_scripts(cfg_versions, sys_versions)
if rev_versions != cfg_versions:
diff --git a/python/vyos/systemversions.py b/python/vyos/systemversions.py
index 5c4deca29..9b3f4f413 100644
--- a/python/vyos/systemversions.py
+++ b/python/vyos/systemversions.py
@@ -16,15 +16,12 @@
import os
import re
import sys
-import json
-
import vyos.defaults
def get_system_versions():
"""
- Get component versions from running system: read vyatta directory
- structure for versions, then read vyos JSON file. It is a critical
- error if either migration directory or JSON file is unreadable.
+ Get component versions from running system; critical failure if
+ unable to read migration directory.
"""
system_versions = {}
@@ -39,25 +36,4 @@ def get_system_versions():
pair = info.split('@')
system_versions[pair[0]] = int(pair[1])
- version_dict = {}
- path = vyos.defaults.version_file
-
- if os.path.isfile(path):
- with open(path, 'r') as f:
- try:
- version_dict = json.load(f)
- except ValueError as err:
- print(f"\nValue error in {path}: {err}")
- sys.exit(1)
-
- for k, v in version_dict.items():
- if not isinstance(v, int):
- print(f"\nType error in {path}; expecting Dict[str, int]")
- sys.exit(1)
- existing = system_versions.get(k)
- if existing is None:
- system_versions[k] = v
- elif v > existing:
- system_versions[k] = v
-
return system_versions
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 08a5712af..ee6e52e1d 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -406,7 +406,7 @@ def get_esp_ike_cipher(group_config):
'dh-group18' : 'modp8192',
'dh-group19' : 'ecp256',
'dh-group20' : 'ecp384',
- 'dh-group21' : 'ecp512',
+ 'dh-group21' : 'ecp521',
'dh-group22' : 'modp1024s160',
'dh-group23' : 'modp2048s224',
'dh-group24' : 'modp2048s256',
diff --git a/python/vyos/util.py b/python/vyos/util.py
index 59f9f1c44..8af46a6ee 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -562,12 +562,13 @@ def commit_in_progress():
# Since this will be used in scripts that modify the config outside of the CLI
# framework, those knowingly have root permissions.
# For everything else, we add a safeguard.
- from psutil import process_iter, NoSuchProcess
+ from psutil import process_iter
+ from psutil import NoSuchProcess
+ from getpass import getuser
from vyos.defaults import commit_lock
- idu = cmd('/usr/bin/id -u')
- if idu != '0':
- raise OSError("This functions needs root permissions to return correct results")
+ if getuser() != 'root':
+ raise OSError('This functions needs to be run as root to return correct results!')
for proc in process_iter():
try:
@@ -805,8 +806,16 @@ def make_incremental_progressbar(increment: float):
while True:
yield
+def is_systemd_service_active(service):
+ """ Test is a specified systemd service is activated.
+ Returns True if service is active, false otherwise.
+ Copied from: https://unix.stackexchange.com/a/435317 """
+ tmp = cmd(f'systemctl show --value -p ActiveState {service}')
+ return bool((tmp == 'active'))
+
def is_systemd_service_running(service):
""" Test is a specified systemd service is actually running.
- Returns True if service is running, false otherwise. """
- tmp = run(f'systemctl is-active --quiet {service}')
- return bool((tmp == 0))
+ Returns True if service is running, false otherwise.
+ Copied from: https://unix.stackexchange.com/a/435317 """
+ tmp = cmd(f'systemctl show --value -p SubState {service}')
+ return bool((tmp == 'running'))
diff --git a/python/vyos/xml/__init__.py b/python/vyos/xml/__init__.py
index 0ef0c85ce..e0eacb2d1 100644
--- a/python/vyos/xml/__init__.py
+++ b/python/vyos/xml/__init__.py
@@ -46,6 +46,8 @@ def is_tag(lpath):
def is_leaf(lpath, flat=True):
return load_configuration().is_leaf(lpath, flat)
+def component_versions():
+ return load_configuration().component_versions()
def defaults(lpath, flat=False):
return load_configuration().defaults(lpath, flat)
diff --git a/python/vyos/xml/definition.py b/python/vyos/xml/definition.py
index f556c5ced..5e0d5282c 100644
--- a/python/vyos/xml/definition.py
+++ b/python/vyos/xml/definition.py
@@ -30,6 +30,7 @@ class XML(dict):
self[kw.owners] = {}
self[kw.default] = {}
self[kw.tags] = []
+ self[kw.component_version] = {}
dict.__init__(self)
@@ -248,6 +249,11 @@ class XML(dict):
# @lru_cache(maxsize=100)
# XXX: need to use cachetool instead - for later
+ def component_versions(self) -> dict:
+ sort_component = sorted(self[kw.component_version].items(),
+ key = lambda kv: kv[0])
+ return dict(sort_component)
+
def defaults(self, lpath, flat):
d = self[kw.default]
for k in lpath:
diff --git a/python/vyos/xml/kw.py b/python/vyos/xml/kw.py
index 58d47e751..48226ce96 100644
--- a/python/vyos/xml/kw.py
+++ b/python/vyos/xml/kw.py
@@ -32,6 +32,7 @@ priorities = '[priorities]'
owners = '[owners]'
tags = '[tags]'
default = '[default]'
+component_version = '[component_version]'
# nodes
diff --git a/python/vyos/xml/load.py b/python/vyos/xml/load.py
index 37479c6e1..c3022f3d6 100644
--- a/python/vyos/xml/load.py
+++ b/python/vyos/xml/load.py
@@ -115,7 +115,12 @@ def _format_nodes(inside, conf, xml):
nodetype = 'tagNode'
nodename = kw.tagNode
elif 'syntaxVersion' in conf.keys():
- conf.pop('syntaxVersion')
+ sv = conf.pop('syntaxVersion')
+ if isinstance(sv, list):
+ for v in sv:
+ xml[kw.component_version][v['@component']] = v['@version']
+ else:
+ xml[kw.component_version][sv['@component']] = sv['@version']
continue
else:
_fatal(conf.keys())
@@ -125,14 +130,20 @@ def _format_nodes(inside, conf, xml):
for node in nodes:
name = node.pop('@name')
into = inside + [name]
- r[name] = _format_node(into, node, xml)
+ if name in r:
+ r[name].update(_format_node(into, node, xml))
+ else:
+ r[name] = _format_node(into, node, xml)
r[name][kw.node] = nodename
xml[kw.tags].append(' '.join(into))
else:
node = nodes
name = node.pop('@name')
into = inside + [name]
- r[name] = _format_node(inside + [name], node, xml)
+ if name in r:
+ r[name].update(_format_node(inside + [name], node, xml))
+ else:
+ r[name] = _format_node(inside + [name], node, xml)
r[name][kw.node] = nodename
xml[kw.tags].append(' '.join(into))
return r
diff --git a/scripts/build-command-op-templates b/scripts/build-command-op-templates
index c285ee594..a4d6d1d08 100755
--- a/scripts/build-command-op-templates
+++ b/scripts/build-command-op-templates
@@ -54,7 +54,7 @@ debug = args.debug
try:
xml = ET.parse(input_file)
except Exception as e:
- print("Failed to load interface definition file {0}".format(input_file))
+ print(f"Failed to load interface definition file {input_file}")
print(e)
sys.exit(1)
@@ -64,15 +64,15 @@ try:
if not validator.validate(xml):
print(validator.error_log)
- print("Interface definition file {0} does not match the schema!".format(input_file))
+ print(f"Interface definition file {input_file} does not match the schema!")
sys.exit(1)
except Exception as e:
- print("Failed to load the XML schema {0}".format(schema_file))
+ print(f"Failed to load the XML schema {schema_file}")
print(e)
sys.exit(1)
if not os.access(output_dir, os.W_OK):
- print("The output directory {0} is not writeable".format(output_dir))
+ print(f"The output directory {output_dir} is not writeable")
sys.exit(1)
## If we got this far, everything must be ok and we can convert the file
@@ -160,16 +160,16 @@ def process_node(n, tmpl_dir):
my_tmpl_dir.append(name)
if debug:
- print("Name of the node: {};\n Created directory: ".format(name), end="")
+ print(f"Name of the node: {name};\n Created directory: ", end="")
os.makedirs(make_path(my_tmpl_dir), exist_ok=True)
props = get_properties(props_elem)
+ nodedef_path = os.path.join(make_path(my_tmpl_dir), "node.def")
if node_type == "node":
if debug:
- print("Processing node {}".format(name))
+ print(f"Processing node {name}")
- nodedef_path = os.path.join(make_path(my_tmpl_dir), "node.def")
# Only create the "node.def" file if it exists but is empty, or if it
# does not exist at all.
if not os.path.exists(nodedef_path) or os.path.getsize(nodedef_path) == 0:
@@ -180,19 +180,18 @@ def process_node(n, tmpl_dir):
inner_nodes = children.iterfind("*")
for inner_n in inner_nodes:
process_node(inner_n, my_tmpl_dir)
+
if node_type == "tagNode":
if debug:
- print("Processing tag node {}".format(name))
+ print(f"Processing tagNode {name}")
os.makedirs(make_path(my_tmpl_dir), exist_ok=True)
- nodedef_path = os.path.join(make_path(my_tmpl_dir), "node.def")
- if not os.path.exists(nodedef_path):
+ # Only create the "node.def" file if it exists but is empty, or if it
+ # does not exist at all.
+ if not os.path.exists(nodedef_path) or os.path.getsize(nodedef_path) == 0:
with open(nodedef_path, "w") as f:
f.write('help: {0}\n'.format(props['help']))
- else:
- # Something has already generated this file
- pass
# Create the inner node.tag part
my_tmpl_dir.append("node.tag")
@@ -201,8 +200,12 @@ def process_node(n, tmpl_dir):
print("Created path for the tagNode: {}".format(make_path(my_tmpl_dir)), end="")
# Not sure if we want partially defined tag nodes, write the file unconditionally
- with open(os.path.join(make_path(my_tmpl_dir), "node.def"), "w") as f:
- f.write(make_node_def(props, command))
+ nodedef_path = os.path.join(make_path(my_tmpl_dir), "node.def")
+ # Only create the "node.def" file if it exists but is empty, or if it
+ # does not exist at all.
+ if not os.path.exists(nodedef_path) or os.path.getsize(nodedef_path) == 0:
+ with open(nodedef_path, "w") as f:
+ f.write(make_node_def(props, command))
if children is not None:
inner_nodes = children.iterfind("*")
@@ -211,11 +214,11 @@ def process_node(n, tmpl_dir):
else:
# This is a leaf node
if debug:
- print("Processing leaf node {}".format(name))
-
- with open(os.path.join(make_path(my_tmpl_dir), "node.def"), "w") as f:
- f.write(make_node_def(props, command))
+ print(f"Processing leaf node {name}")
+ if not os.path.exists(nodedef_path) or os.path.getsize(nodedef_path) == 0:
+ with open(nodedef_path, "w") as f:
+ f.write(make_node_def(props, command))
root = xml.getroot()
diff --git a/scripts/build-component-versions b/scripts/build-component-versions
deleted file mode 100755
index 5362dbdd4..000000000
--- a/scripts/build-component-versions
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-import os
-import argparse
-import json
-
-from lxml import etree as ET
-
-parser = argparse.ArgumentParser()
-parser.add_argument('INPUT_DIR', type=str,
- help="Directory containing XML interface definition files")
-parser.add_argument('OUTPUT_DIR', type=str,
- help="Output directory for JSON file")
-
-args = parser.parse_args()
-
-input_dir = args.INPUT_DIR
-output_dir = args.OUTPUT_DIR
-
-version_dict = {}
-
-for filename in os.listdir(input_dir):
- filepath = os.path.join(input_dir, filename)
- print(filepath)
- try:
- xml = ET.parse(filepath)
- except Exception as e:
- print("Failed to load interface definition file {0}".format(filename))
- print(e)
- sys.exit(1)
-
- root = xml.getroot()
- version_data = root.iterfind("syntaxVersion")
- for ver in version_data:
- component = ver.get("component")
- version = int(ver.get("version"))
-
- v = version_dict.get(component)
- if v is None:
- version_dict[component] = version
- elif version > v:
- version_dict[component] = version
-
-out_file = os.path.join(output_dir, 'component-versions.json')
-with open(out_file, 'w') as f:
- json.dump(version_dict, f, indent=4, sort_keys=True)
diff --git a/scripts/override-default b/scripts/override-default
index c8a0ff1da..0c49087c8 100755
--- a/scripts/override-default
+++ b/scripts/override-default
@@ -27,6 +27,7 @@
import sys
import glob
import logging
+from copy import deepcopy
from lxml import etree
debug = False
@@ -60,30 +61,55 @@ def override_element(l: list):
for el in parents:
el.getparent().remove(el)
+def merge_remaining(l: list, elementtree):
+ """
+ Merge (now) single leaf node containing 'defaultValue' with leaf nodes
+ of same path and no 'defaultValue'.
+ """
+ for p in l:
+ p = p.split()
+ path_str = f'/interfaceDefinition/*'
+ path_list = []
+ for i in range(len(p)):
+ path_list.append(f'[@name="{p[i]}"]')
+ path_str += '/children/*'.join(path_list)
+ rp = elementtree.xpath(path_str)
+ if len(rp) > 1:
+ for el in rp[1:]:
+ # in practice there will only be one child of the path,
+ # either defaultValue or Properties, since
+ # override_element() has already run
+ for child in el:
+ rp[0].append(deepcopy(child))
+ el.getparent().remove(el)
+
def collect_and_override(dir_name):
"""
- Collect elements with defaultValue tag into dictionary indexed by tuple
- of (name: str, ancestor path: str).
+ Collect elements with defaultValue tag into dictionary indexed by name
+ attributes of ancestor path.
"""
for fname in glob.glob(f'{dir_name}/*.xml'):
tree = etree.parse(fname)
root = tree.getroot()
defv = {}
- xpath_str = f'//defaultValue'
+ xpath_str = '//defaultValue'
xp = tree.xpath(xpath_str)
for element in xp:
ap = element.xpath('ancestor::*[@name]')
ap_name = [el.get("name") for el in ap]
- ap_path_str = ' '.join(ap_name[:-1])
- defv.setdefault((ap_name[-1], ap_path_str), []).append(element)
+ ap_path_str = ' '.join(ap_name)
+ defv.setdefault(ap_path_str, []).append(element)
for k, v in defv.items():
if len(v) > 1:
- logger.info(f"overridding default in {k[0]}, path '{k[1]}'")
+ logger.info(f"overridding default in path '{k}'")
override_element(v)
+ to_merge = list(defv)
+ merge_remaining(to_merge, tree)
+
revised_str = etree.tostring(root, encoding='unicode', pretty_print=True)
with open(f'{fname}', 'w') as f:
diff --git a/smoketest/configs/isis-small b/smoketest/configs/isis-small
index 2c42ac9c4..247ae32b5 100644
--- a/smoketest/configs/isis-small
+++ b/smoketest/configs/isis-small
@@ -102,4 +102,3 @@ system {
// Warning: Do not remove the following line.
// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@1:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@18:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@7:rpki@1:salt@1:snmp@2:ssh@2:sstp@3:system@20:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1"
// Release version: 1.3.0-rc1
-
diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py
index 7f69b8444..edb604dbf 100644
--- a/smoketest/scripts/cli/base_interfaces_test.py
+++ b/smoketest/scripts/cli/base_interfaces_test.py
@@ -556,13 +556,16 @@ class BasicInterfaceTest:
if not self._test_ip:
self.skipTest('not supported')
+ arp_tmo = '300'
+ mss = '1420'
+
for interface in self._interfaces:
- arp_tmo = '300'
path = self._base_path + [interface]
for option in self._options.get(interface, []):
self.cli_set(path + option.split())
# Options
+ self.cli_set(path + ['ip', 'adjust-mss', mss])
self.cli_set(path + ['ip', 'arp-cache-timeout', arp_tmo])
self.cli_set(path + ['ip', 'disable-arp-filter'])
self.cli_set(path + ['ip', 'disable-forwarding'])
@@ -576,54 +579,73 @@ class BasicInterfaceTest:
self.cli_commit()
for interface in self._interfaces:
+ base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = cmd('sudo iptables-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ self.assertIn(f'--set-mss {mss}', line)
+
tmp = read_file(f'/proc/sys/net/ipv4/neigh/{interface}/base_reachable_time_ms')
self.assertEqual(tmp, str((int(arp_tmo) * 1000))) # tmo value is in milli seconds
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_filter')
+ proc_base = f'/proc/sys/net/ipv4/conf/{interface}'
+
+ tmp = read_file(f'{proc_base}/arp_filter')
self.assertEqual('0', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_accept')
+ tmp = read_file(f'{proc_base}/arp_accept')
self.assertEqual('1', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_announce')
+ tmp = read_file(f'{proc_base}/arp_announce')
self.assertEqual('1', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/arp_ignore')
+ tmp = read_file(f'{proc_base}/arp_ignore')
self.assertEqual('1', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/forwarding')
+ tmp = read_file(f'{proc_base}/forwarding')
self.assertEqual('0', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp')
+ tmp = read_file(f'{proc_base}/proxy_arp')
self.assertEqual('1', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/proxy_arp_pvlan')
+ tmp = read_file(f'{proc_base}/proxy_arp_pvlan')
self.assertEqual('1', tmp)
- tmp = read_file(f'/proc/sys/net/ipv4/conf/{interface}/rp_filter')
+ tmp = read_file(f'{proc_base}/rp_filter')
self.assertEqual('2', tmp)
def test_interface_ipv6_options(self):
if not self._test_ipv6:
self.skipTest('not supported')
+ mss = '1400'
+ dad_transmits = '10'
+
for interface in self._interfaces:
- dad_transmits = '10'
path = self._base_path + [interface]
for option in self._options.get(interface, []):
self.cli_set(path + option.split())
# Options
+ self.cli_set(path + ['ipv6', 'adjust-mss', mss])
self.cli_set(path + ['ipv6', 'disable-forwarding'])
self.cli_set(path + ['ipv6', 'dup-addr-detect-transmits', dad_transmits])
self.cli_commit()
for interface in self._interfaces:
- tmp = read_file(f'/proc/sys/net/ipv6/conf/{interface}/forwarding')
+ base_options = f'-A FORWARD -o {interface} -p tcp -m tcp --tcp-flags SYN,RST SYN'
+ out = cmd('sudo ip6tables-save -t mangle')
+ for line in out.splitlines():
+ if line.startswith(base_options):
+ self.assertIn(f'--set-mss {mss}', line)
+
+ proc_base = f'/proc/sys/net/ipv6/conf/{interface}'
+
+ tmp = read_file(f'{proc_base}/forwarding')
self.assertEqual('0', tmp)
- tmp = read_file(f'/proc/sys/net/ipv6/conf/{interface}/dad_transmits')
+ tmp = read_file(f'{proc_base}/dad_transmits')
self.assertEqual(dad_transmits, tmp)
def test_dhcpv6_client_options(self):
diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py
index 18e49f47f..50f80e7d1 100644
--- a/smoketest/scripts/cli/base_vyostest_shim.py
+++ b/smoketest/scripts/cli/base_vyostest_shim.py
@@ -20,7 +20,9 @@ from time import sleep
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
from vyos import ConfigError
+from vyos.defaults import commit_lock
from vyos.util import cmd
+from vyos.util import run
save_config = '/tmp/vyos-smoketest-save'
@@ -70,21 +72,16 @@ class VyOSUnitTestSHIM:
def cli_commit(self):
self._session.commit()
+ # during a commit there is a process opening commit_lock, and run() returns 0
+ while run(f'sudo lsof | grep -q {commit_lock}') == 0:
+ sleep(0.250)
- def getFRRconfig(self, string, end='$', endsection='^!'):
+ def getFRRconfig(self, string, end='$', endsection='^!', daemon=''):
""" Retrieve current "running configuration" from FRR """
- command = f'vtysh -c "show run" | sed -n "/^{string}{end}/,/{endsection}/p"'
-
- count = 0
- tmp = ''
- while count < 10 and tmp == '':
- # Let FRR settle after a config change first before harassing it again
- sleep(1)
- tmp = cmd(command)
- count += 1
-
- if self.debug or tmp == '':
+ command = f'vtysh -c "show run {daemon} no-header" | sed -n "/^{string}{end}/,/{endsection}/p"'
+ out = cmd(command)
+ if self.debug:
import pprint
print(f'\n\ncommand "{command}" returned:\n')
- pprint.pprint(tmp)
- return tmp
+ pprint.pprint(out)
+ return out
diff --git a/smoketest/scripts/cli/test_interfaces_pppoe.py b/smoketest/scripts/cli/test_interfaces_pppoe.py
index 3412ebae0..67edce2a0 100755
--- a/smoketest/scripts/cli/test_interfaces_pppoe.py
+++ b/smoketest/scripts/cli/test_interfaces_pppoe.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2020 VyOS maintainers and contributors
+# Copyright (C) 2019-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
@@ -22,10 +22,8 @@ from base_vyostest_shim import VyOSUnitTestSHIM
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
-from vyos.util import read_file
config_file = '/etc/ppp/peers/{}'
-dhcp6c_config_file = '/run/dhcp6c/dhcp6c.{}.conf'
base_path = ['interfaces', 'pppoe']
def get_config_value(interface, key):
@@ -35,25 +33,26 @@ def get_config_value(interface, key):
return list(line.split())
return []
-def get_dhcp6c_config_value(interface, key):
- tmp = read_file(dhcp6c_config_file.format(interface))
- tmp = re.findall(r'\n?{}\s+(.*)'.format(key), tmp)
-
- out = []
- for item in tmp:
- out.append(item.replace(';',''))
- return out
-
+# add a classmethod to setup a temporaray PPPoE server for "proper" validation
class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase):
def setUp(self):
self._interfaces = ['pppoe10', 'pppoe20', 'pppoe30']
self._source_interface = 'eth0'
def tearDown(self):
+ # Validate PPPoE client process
+ for interface in self._interfaces:
+ running = False
+ for proc in process_iter():
+ if interface in proc.cmdline():
+ running = True
+ break
+ self.assertTrue(running)
+
self.cli_delete(base_path)
self.cli_commit()
- def test_pppoe_client(self):
+ def test_01_pppoe_client(self):
# Check if PPPoE dialer can be configured and runs
for interface in self._interfaces:
user = 'VyOS-user-' + interface
@@ -71,8 +70,8 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
self.cli_set(base_path + [interface, 'source-interface', self._source_interface])
- # commit changes
- self.cli_commit()
+ # commit changes
+ self.cli_commit()
# verify configuration file(s)
for interface in self._interfaces:
@@ -88,17 +87,7 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase):
tmp = get_config_value(interface, 'ifname')[1]
self.assertEqual(tmp, interface)
- # Check if ppp process is running in the interface in question
- running = False
- for p in process_iter():
- if "pppd" in p.name():
- if interface in p.cmdline():
- running = True
-
- self.assertTrue(running)
-
-
- def test_pppoe_clent_disabled_interface(self):
+ def test_02_pppoe_client_disabled_interface(self):
# Check if PPPoE Client can be disabled
for interface in self._interfaces:
self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos'])
@@ -106,23 +95,45 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + [interface, 'source-interface', self._source_interface])
self.cli_set(base_path + [interface, 'disable'])
- self.cli_commit()
+ self.cli_commit()
- # Validate PPPoE client process
- running = False
+ # Validate PPPoE client process - must not run as interfaces are disabled
for interface in self._interfaces:
+ running = False
for proc in process_iter():
if interface in proc.cmdline():
running = True
+ break
+ self.assertFalse(running)
+
+ # enable PPPoE interfaces
+ for interface in self._interfaces:
+ self.cli_delete(base_path + [interface, 'disable'])
+
+ self.cli_commit()
+
- self.assertFalse(running)
+ def test_03_pppoe_authentication(self):
+ # When username or password is set - so must be the other
+ for interface in self._interfaces:
+ self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos'])
+ self.cli_set(base_path + [interface, 'source-interface', self._source_interface])
+ self.cli_set(base_path + [interface, 'ipv6', 'address', 'autoconf'])
+ # check validate() - if user is set, so must be the password
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos'])
+
+ self.cli_commit()
- def test_pppoe_dhcpv6pd(self):
+ def test_04_pppoe_dhcpv6pd(self):
# Check if PPPoE dialer can be configured with DHCPv6-PD
address = '1'
sla_id = '0'
sla_len = '8'
+
for interface in self._interfaces:
self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos'])
self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos'])
@@ -147,51 +158,8 @@ class PPPoEInterfaceTest(VyOSUnitTestSHIM.TestCase):
self.assertEqual(tmp, 'vyos')
tmp = get_config_value(interface, 'password')[1].replace('"', '')
self.assertEqual(tmp, 'vyos')
-
- for param in ['+ipv6', 'ipv6cp-use-ipaddr']:
- tmp = get_config_value(interface, param)[0]
- self.assertEqual(tmp, param)
-
- # verify DHCPv6 prefix delegation
- # will return: ['delegation', '::/56 infinity;']
- tmp = get_dhcp6c_config_value(interface, 'prefix')[1].split()[0] # mind the whitespace
- self.assertEqual(tmp, '::/56')
- tmp = get_dhcp6c_config_value(interface, 'prefix-interface')[0].split()[0]
- self.assertEqual(tmp, self._source_interface)
- tmp = get_dhcp6c_config_value(interface, 'ifid')[0]
- self.assertEqual(tmp, address)
- tmp = get_dhcp6c_config_value(interface, 'sla-id')[0]
- self.assertEqual(tmp, sla_id)
- tmp = get_dhcp6c_config_value(interface, 'sla-len')[0]
- self.assertEqual(tmp, sla_len)
-
- # Check if ppp process is running in the interface in question
- running = False
- for p in process_iter():
- if "pppd" in p.name():
- running = True
- self.assertTrue(running)
-
- # We can not check if wide-dhcpv6 process is running as it is started
- # after the PPP interface gets a link to the ISP - but we can see if
- # it would be started by the scripts
- tmp = read_file(f'/etc/ppp/ipv6-up.d/1000-vyos-pppoe-{interface}')
- tmp = re.findall(f'systemctl restart dhcp6c@{interface}.service', tmp)
- self.assertTrue(tmp)
-
- def test_pppoe_authentication(self):
- # When username or password is set - so must be the other
- interface = 'pppoe0'
- self.cli_set(base_path + [interface, 'authentication', 'user', 'vyos'])
- self.cli_set(base_path + [interface, 'source-interface', self._source_interface])
- self.cli_set(base_path + [interface, 'ipv6', 'address', 'autoconf'])
-
- # check validate() - if user is set, so must be the password
- with self.assertRaises(ConfigSessionError):
- self.cli_commit()
-
- self.cli_set(base_path + [interface, 'authentication', 'password', 'vyos'])
- self.cli_commit()
+ tmp = get_config_value(interface, '+ipv6 ipv6cp-use-ipaddr')
+ self.assertListEqual(tmp, ['+ipv6', 'ipv6cp-use-ipaddr'])
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py
index dca92c97d..7721105e0 100755
--- a/smoketest/scripts/cli/test_nat66.py
+++ b/smoketest/scripts/cli/test_nat66.py
@@ -31,10 +31,13 @@ src_path = base_path + ['source']
dst_path = base_path + ['destination']
class TestNAT66(VyOSUnitTestSHIM.TestCase):
- def setUp(self):
+ @classmethod
+ def setUpClass(cls):
+ super(cls, cls).setUpClass()
+
# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
- self.cli_delete(base_path)
+ cls.cli_delete(cls, base_path)
def tearDown(self):
self.cli_delete(base_path)
@@ -183,4 +186,4 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2, failfast=True)
diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py
index 66d3f3812..c2288a86a 100755
--- a/smoketest/scripts/cli/test_policy.py
+++ b/smoketest/scripts/cli/test_policy.py
@@ -1149,5 +1149,58 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):
self.assertEqual(tmp, original)
+ # Test set table for fwmark
+ def test_fwmark_table_id(self):
+ path = base_path + ['local-route']
+
+ fwmk = '24'
+ rule = '101'
+ table = '154'
+
+ self.cli_set(path + ['rule', rule, 'set', 'table', table])
+ self.cli_set(path + ['rule', rule, 'fwmark', fwmk])
+
+ self.cli_commit()
+
+ # Check generated configuration
+
+ # Expected values
+ original = """
+ 101: from all fwmark 0x18 lookup 154
+ """
+ tmp = cmd('ip rule show prio 101')
+ original = original.split()
+ tmp = tmp.split()
+
+ self.assertEqual(tmp, original)
+
+ # Test set table for sources with fwmark
+ def test_fwmark_sources_table_id(self):
+ path = base_path + ['local-route']
+
+ sources = ['203.0.113.11', '203.0.113.12']
+ fwmk = '23'
+ rule = '100'
+ table = '150'
+ for src in sources:
+ self.cli_set(path + ['rule', rule, 'set', 'table', table])
+ self.cli_set(path + ['rule', rule, 'source', src])
+ self.cli_set(path + ['rule', rule, 'fwmark', fwmk])
+
+ self.cli_commit()
+
+ # Check generated configuration
+
+ # Expected values
+ original = """
+ 100: from 203.0.113.11 fwmark 0x17 lookup 150
+ 100: from 203.0.113.12 fwmark 0x17 lookup 150
+ """
+ tmp = cmd('ip rule show prio 100')
+ original = original.split()
+ tmp = tmp.split()
+
+ self.assertEqual(tmp, original)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index c3a2ffbf9..df9dc342b 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -78,6 +78,7 @@ neighbor_config = {
'cap_over' : '',
'ttl_security' : '5',
'local_as' : '300',
+ 'solo' : '',
'route_map_in' : route_map_in,
'route_map_out': route_map_out,
'no_send_comm_std' : '',
@@ -173,6 +174,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' neighbor {peer} password {peer_config["password"]}', 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:
@@ -296,6 +299,8 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
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:
@@ -628,6 +633,9 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
# templates and Jinja2 FRR template.
table = '1000'
+ self.cli_set(base_path + ['local-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])
@@ -636,15 +644,26 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
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
- frrconfig = self.getFRRconfig(f'router bgp {ASN} vrf {vrf}')
- self.assertIn(f'router bgp {ASN} vrf {vrf}', frrconfig)
- self.assertIn(f' bgp router-id {router_id}', frrconfig)
+ 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)
- # CCC: Currently this is not working as FRR() class does not support
+ # 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.
#
@@ -694,13 +713,27 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' neighbor {interface} activate', frrconfig)
self.assertIn(f' exit-address-family', frrconfig)
- def test_bgp_13_solo(self):
+
+ 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 + ['local-as', ASN])
- self.cli_set(base_path + ['neighbor', neighbor, 'remote-as', remote_asn])
- self.cli_set(base_path + ['neighbor', neighbor, 'solo'])
+ # 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()
@@ -708,7 +741,19 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
# Verify FRR bgpd configuration
frrconfig = self.getFRRconfig(f'router bgp {ASN}')
self.assertIn(f'router bgp {ASN}', frrconfig)
- self.assertIn(f' neighbor {neighbor} solo', 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)
if __name__ == '__main__':
unittest.main(verbosity=2) \ No newline at end of file
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index 59862ca3d..3f13eec80 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -20,6 +20,7 @@ import unittest
from base_vyostest_shim import VyOSUnitTestSHIM
+from vyos.configsession import ConfigSessionError
from vyos.ifconfig import Section
from vyos.util import process_named_running
from vyos.util import cmd
@@ -220,21 +221,23 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
for protocol in redistribute:
self.cli_set(base_path + ['redistribute', protocol, 'metric', metric])
self.cli_set(base_path + ['redistribute', protocol, 'route-map', route_map])
- if protocol not in ['kernel', 'static']:
- self.cli_set(base_path + ['redistribute', protocol, 'metric-type', metric_type])
+ self.cli_set(base_path + ['redistribute', protocol, 'metric-type', metric_type])
# commit changes
self.cli_commit()
# Verify FRR ospfd configuration
frrconfig = self.getFRRconfig('router ospf')
- self.assertIn(f'router ospf', frrconfig)
- for protocol in redistribute:
- if protocol in ['kernel', 'static']:
- self.assertIn(f' redistribute {protocol} metric {metric} route-map {route_map}', frrconfig)
- else:
+ try:
+ self.assertIn(f'router ospf', frrconfig)
+ for protocol in redistribute:
self.assertIn(f' redistribute {protocol} metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig)
-
+ except:
+ log.debug(frrconfig)
+ log.debug(cmd('sudo dmesg'))
+ log.debug(cmd('sudo cat /var/log/messages'))
+ log.debug(cmd('vtysh -c "show run"'))
+ self.fail('Now we can hopefully see why OSPF fails!')
def test_ospf_09_virtual_link(self):
networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16']
@@ -266,7 +269,7 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' network {network} area {area}', frrconfig)
- def test_ospf_10_interface_configureation(self):
+ def test_ospf_10_interface_configuration(self):
interfaces = Section.interfaces('ethernet')
password = 'vyos1234'
bandwidth = '10000'
@@ -349,6 +352,30 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
frrconfig = self.getFRRconfig(zebra_route_map)
self.assertNotIn(zebra_route_map, frrconfig)
+ def test_ospf_13_interface_area(self):
+ area = '0'
+ interfaces = Section.interfaces('ethernet')
+
+ self.cli_set(base_path + ['area', area, 'network', '10.0.0.0/8'])
+ for interface in interfaces:
+ self.cli_set(base_path + ['interface', interface, 'area', area])
+
+ # we can not have bot area network and interface area set
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+ self.cli_delete(base_path + ['area', area, 'network'])
+
+ self.cli_commit()
+
+ # Verify FRR ospfd configuration
+ frrconfig = self.getFRRconfig('router ospf')
+ self.assertIn(f'router ospf', frrconfig)
+
+ for interface in interfaces:
+ config = self.getFRRconfig(f'interface {interface}')
+ self.assertIn(f'interface {interface}', config)
+ self.assertIn(f' ip ospf area {area}', config)
+
if __name__ == '__main__':
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py
index c76f709b1..ded4d8301 100755
--- a/smoketest/scripts/cli/test_service_ssh.py
+++ b/smoketest/scripts/cli/test_service_ssh.py
@@ -41,10 +41,13 @@ def get_config_value(key):
return tmp
class TestServiceSSH(VyOSUnitTestSHIM.TestCase):
- def setUp(self):
+ @classmethod
+ def setUpClass(cls):
+ super(cls, cls).setUpClass()
+
# ensure we can also run this test on a live system - so lets clean
# out the current configuration :)
- self.cli_delete(base_path)
+ cls.cli_delete(cls, base_path)
def tearDown(self):
# delete testing SSH config
diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py
index 21d626d2f..a2380981b 100755
--- a/smoketest/scripts/cli/test_system_conntrack.py
+++ b/smoketest/scripts/cli/test_system_conntrack.py
@@ -147,8 +147,8 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):
self.assertEqual(get_sysctl(f'{parameter}'), parameter_config['default_value'])
- def test_conntrack_module_disable(self):
- # Some features are disabled by onloading the kernel helper module(s)
+ def test_conntrack_module_enable(self):
+ # conntrack helper modules are disabled by default
modules = {
'ftp' : {
'driver' : ['nf_nat_ftp', 'nf_conntrack_ftp'],
@@ -176,38 +176,39 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):
},
}
+ # load modules
for module in modules:
- self.cli_set(base_path + ['modules', module, 'disable'])
+ self.cli_set(base_path + ['modules', module])
# commit changes
self.cli_commit()
- # verify modules are no longer loaded on the system
+ # verify modules are loaded on the system
for module, module_options in modules.items():
if 'driver' in module_options:
for driver in module_options['driver']:
- self.assertFalse(os.path.isdir(f'/sys/module/{driver}'))
+ self.assertTrue(os.path.isdir(f'/sys/module/{driver}'))
if 'iptables' in module_options:
rules = cmd('sudo iptables-save -t raw')
for ruleset in module_options['iptables']:
- self.assertNotIn(ruleset, rules)
+ self.assertIn(ruleset, rules)
- # reload modules
+ # unload modules
for module in modules:
- self.cli_delete(base_path + ['modules', module, 'disable'])
+ self.cli_delete(base_path + ['modules', module])
# commit changes
self.cli_commit()
- # verify modules are again loaded on the system
+ # verify modules are not loaded on the system
for module, module_options in modules.items():
if 'driver' in module_options:
for driver in module_options['driver']:
- self.assertTrue(os.path.isdir(f'/sys/module/{driver}'))
+ self.assertFalse(os.path.isdir(f'/sys/module/{driver}'))
if 'iptables' in module_options:
rules = cmd('sudo iptables-save -t raw')
for ruleset in module_options['iptables']:
- self.assertIn(ruleset, rules)
+ self.assertNotIn(ruleset, rules)
def test_conntrack_hash_size(self):
hash_size = '65536'
diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py
index a34387dc9..f33268083 100755
--- a/smoketest/scripts/cli/test_vpn_ipsec.py
+++ b/smoketest/scripts/cli/test_vpn_ipsec.py
@@ -182,8 +182,10 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
swanctl_conf_lines = [
f'version = 2',
f'auth = psk',
+ f'rekey_time = 28800s', # default value
f'proposals = aes128-sha1-modp1024',
f'esp_proposals = aes128-sha1-modp1024',
+ f'life_time = 3600s', # default value
f'local_addrs = {local_address} # dhcp:no',
f'remote_addrs = {peer_ip}',
f'mode = tunnel',
@@ -255,6 +257,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
def test_04_dmvpn(self):
tunnel_if = 'tun100'
nhrp_secret = 'secret'
+ ike_lifetime = '3600'
+ esp_lifetime = '1800'
# Tunnel
self.cli_set(tunnel_path + [tunnel_if, 'address', '172.16.253.134/29'])
@@ -272,7 +276,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
# IKE/ESP Groups
self.cli_set(base_path + ['esp-group', esp_group, 'compression', 'disable'])
- self.cli_set(base_path + ['esp-group', esp_group, 'lifetime', '1800'])
+ self.cli_set(base_path + ['esp-group', esp_group, 'lifetime', esp_lifetime])
self.cli_set(base_path + ['esp-group', esp_group, 'mode', 'transport'])
self.cli_set(base_path + ['esp-group', esp_group, 'pfs', 'dh-group2'])
self.cli_set(base_path + ['esp-group', esp_group, 'proposal', '2', 'encryption', 'aes256'])
@@ -282,7 +286,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['ike-group', ike_group, 'ikev2-reauth', 'no'])
self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev1'])
- self.cli_set(base_path + ['ike-group', ike_group, 'lifetime', '3600'])
+ self.cli_set(base_path + ['ike-group', ike_group, 'lifetime', ike_lifetime])
self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'dh-group', '2'])
self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'encryption', 'aes256'])
self.cli_set(base_path + ['ike-group', ike_group, 'proposal', '2', 'hash', 'sha1'])
@@ -300,7 +304,8 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
swanctl_lines = [
f'proposals = aes128-sha1-modp1024,aes256-sha1-modp1024',
f'version = 1',
- f'rekey_time = 3600s',
+ f'life_time = {ike_lifetime}s',
+ f'rekey_time = {esp_lifetime}s',
f'esp_proposals = aes128-sha1-modp1024,aes256-sha1-modp1024,3des-md5-modp1024',
f'local_ts = dynamic[gre]',
f'remote_ts = dynamic[gre]',
diff --git a/src/conf_mode/conntrack.py b/src/conf_mode/conntrack.py
index 4e6e39c0f..68877f794 100755
--- a/src/conf_mode/conntrack.py
+++ b/src/conf_mode/conntrack.py
@@ -97,7 +97,7 @@ def apply(conntrack):
# Depending on the enable/disable state of the ALG (Application Layer Gateway)
# modules we need to either insmod or rmmod the helpers.
for module, module_config in module_map.items():
- if dict_search(f'modules.{module}.disable', conntrack) != None:
+ if dict_search(f'modules.{module}', conntrack) is None:
if 'ko' in module_config:
for mod in module_config['ko']:
# Only remove the module if it's loaded
@@ -105,8 +105,9 @@ def apply(conntrack):
cmd(f'rmmod {mod}')
if 'iptables' in module_config:
for rule in module_config['iptables']:
- print(f'iptables --delete {rule}')
- cmd(f'iptables --delete {rule}')
+ # Only install iptables rule if it does not exist
+ tmp = run(f'iptables --check {rule}')
+ if tmp == 0: cmd(f'iptables --delete {rule}')
else:
if 'ko' in module_config:
for mod in module_config['ko']:
@@ -115,9 +116,7 @@ def apply(conntrack):
for rule in module_config['iptables']:
# Only install iptables rule if it does not exist
tmp = run(f'iptables --check {rule}')
- if tmp > 0:
- cmd(f'iptables --insert {rule}')
-
+ if tmp > 0: cmd(f'iptables --insert {rule}')
if process_named_running('conntrackd'):
# Reload conntrack-sync daemon to fetch new sysctl values
diff --git a/src/conf_mode/containers.py b/src/conf_mode/containers.py
index 21b47f42a..32320a4b2 100755
--- a/src/conf_mode/containers.py
+++ b/src/conf_mode/containers.py
@@ -23,8 +23,11 @@ from ipaddress import ip_network
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configdict import node_changed
+from vyos.util import call
from vyos.util import cmd
-from vyos.util import popen
+from vyos.util import run
+from vyos.util import read_file
+from vyos.util import write_file
from vyos.template import render
from vyos.template import is_ipv4
from vyos.template import is_ipv6
@@ -41,27 +44,7 @@ def _cmd(command):
print(command)
return cmd(command)
-# Container management functions
-def container_exists(name):
- '''
- https://docs.podman.io/en/latest/_static/api.html#operation/ContainerExistsLibpod
- Check if container exists. Response codes.
- 204 - container exists
- 404 - no such container
- '''
- tmp = _cmd(f"curl --unix-socket /run/podman/podman.sock 'http://d/v3.0.0/libpod/containers/{name}/exists'")
- # If container exists it return status code "0" - code can not be displayed
- return (tmp == "")
-
-def container_status(name):
- '''
- https://docs.podman.io/en/latest/_static/api.html#operation/ContainerInspectLibpod
- '''
- tmp = _cmd(f"curl --unix-socket /run/podman/podman.sock 'http://d/v3.0.0/libpod/containers/{name}/json'")
- data = json.loads(tmp)
- return data['State']['Status']
-
-def ctnr_network_exists(name):
+def network_exists(name):
# Check explicit name for network, returns True if network exists
c = _cmd(f'podman network ls --quiet --filter name=^{name}$')
return bool(c)
@@ -79,11 +62,20 @@ def get_config(config=None):
# We have gathered the dict representation of the CLI, but there are default
# options which we need to update into the dictionary retrived.
default_values = defaults(base)
+ # container base default values can not be merged here - remove and add them later
+ if 'name' in default_values:
+ del default_values['name']
container = dict_merge(default_values, container)
+ # Merge per-container default values
+ if 'name' in container:
+ default_values = defaults(base + ['name'])
+ for name in container['name']:
+ container['name'][name] = dict_merge(default_values, container['name'][name])
+
# Delete container network, delete containers
tmp = node_changed(conf, ['container', 'network'])
- if tmp: container.update({'net_remove' : tmp})
+ if tmp: container.update({'network_remove' : tmp})
tmp = node_changed(conf, ['container', 'name'])
if tmp: container.update({'container_remove' : tmp})
@@ -102,7 +94,6 @@ def verify(container):
if len(container_config['network']) > 1:
raise ConfigError(f'Only one network can be specified for container "{name}"!')
-
# Check if the specified container network exists
network_name = list(container_config['network'])[0]
if network_name not in container['network']:
@@ -125,8 +116,25 @@ def verify(container):
# We can not use the first IP address of a network prefix as this is used by podman
if ip_address(address) == ip_network(network)[1]:
- raise ConfigError(f'Address "{address}" reserved for the container engine!')
+ raise ConfigError(f'IP address "{address}" can not be used for a container, '\
+ 'reserved for the container engine!')
+
+ if 'environment' in container_config:
+ for var, cfg in container_config['environment'].items():
+ if 'value' not in cfg:
+ raise ConfigError(f'Environment variable {var} has no value assigned!')
+ if 'volume' in container_config:
+ for volume, volume_config in container_config['volume'].items():
+ if 'source' not in volume_config:
+ raise ConfigError(f'Volume "{volume}" has no source path configured!')
+
+ if 'destination' not in volume_config:
+ raise ConfigError(f'Volume "{volume}" has no destination path configured!')
+
+ source = volume_config['source']
+ if not os.path.exists(source):
+ raise ConfigError(f'Volume "{volume}" source path "{source}" does not exist!')
# Container image is a mandatory option
if 'image' not in container_config:
@@ -142,9 +150,9 @@ def verify(container):
# Add new network
if 'network' in container:
- v4_prefix = 0
- v6_prefix = 0
for network, network_config in container['network'].items():
+ v4_prefix = 0
+ v6_prefix = 0
# If ipv4-prefix not defined for user-defined network
if 'prefix' not in network_config:
raise ConfigError(f'prefix for network "{net}" must be defined!')
@@ -160,8 +168,8 @@ def verify(container):
# A network attached to a container can not be deleted
- if {'net_remove', 'name'} <= set(container):
- for network in container['net_remove']:
+ if {'network_remove', 'name'} <= set(container):
+ for network in container['network_remove']:
for container, container_config in container['name'].items():
if 'network' in container_config and network in container_config['network']:
raise ConfigError(f'Can not remove network "{network}", used by container "{container}"!')
@@ -183,20 +191,19 @@ def apply(container):
# Option "--force" allows to delete containers with any status
if 'container_remove' in container:
for name in container['container_remove']:
- if container_status(name) == 'running':
- _cmd(f'podman stop {name}')
- _cmd(f'podman rm --force {name}')
+ call(f'podman stop {name}')
+ call(f'podman rm --force {name}')
# Delete old networks if needed
- if 'net_remove' in container:
- for network in container['net_remove']:
- _cmd(f'podman network rm {network}')
+ if 'network_remove' in container:
+ for network in container['network_remove']:
+ call(f'podman network rm --force {network}')
# Add network
if 'network' in container:
for network, network_config in container['network'].items():
# Check if the network has already been created
- if not ctnr_network_exists(network) and 'prefix' in network_config:
+ if not network_exists(network) and 'prefix' in network_config:
tmp = f'podman network create {network}'
# we can not use list comprehension here as the --ipv6 option
# must immediately follow the specified subnet!!!
@@ -206,56 +213,82 @@ def apply(container):
tmp += ' --ipv6'
_cmd(tmp)
+ # Disable masquerading and use traditional bridging so VyOS
+ # can control firewalling/NAT by the real VyOS CLI
+ cni_network_config = f'/etc/cni/net.d/{network}.conflist'
+ tmp = read_file(cni_network_config)
+ config = json.loads(tmp)
+ if 'plugins' in config:
+ for count in range(0, len(config['plugins'])):
+ if 'ipMasq' in config['plugins'][count]:
+ config['plugins'][count]['ipMasq'] = False
+ if 'hairpinMode' in config['plugins'][count]:
+ config['plugins'][count]['hairpinMode'] = False
+
+ write_file(cni_network_config, json.dumps(config, indent=4))
+
# Add container
if 'name' in container:
for name, container_config in container['name'].items():
- # Check if the container has already been created
- if not container_exists(name):
- image = container_config['image']
- # Currently the best way to run a command and immediately print stdout
- print(os.system(f'podman pull {image}'))
-
- # Check/set environment options "-e foo=bar"
- env_opt = ''
- if 'environment' in container_config:
- env_opt = '-e '
- env_opt += " -e ".join(f"{k}={v['value']}" for k, v in container_config['environment'].items())
-
- # Publish ports
- port = ''
- if 'port' in container_config:
- protocol = ''
- for portmap in container_config['port']:
- if 'protocol' in container_config['port'][portmap]:
- protocol = container_config['port'][portmap]['protocol']
- protocol = f'/{protocol}'
- else:
- protocol = '/tcp'
- sport = container_config['port'][portmap]['source']
- dport = container_config['port'][portmap]['destination']
- port += f' -p {sport}:{dport}{protocol}'
-
- # Bind volume
- volume = ''
- if 'volume' in container_config:
- for vol in container_config['volume']:
- svol = container_config['volume'][vol]['source']
- dvol = container_config['volume'][vol]['destination']
- volume += f' -v {svol}:{dvol}'
-
- if 'allow_host_networks' in container_config:
- _cmd(f'podman run -dit --name {name} --net host {port} {volume} {env_opt} {image}')
- else:
- for network in container_config['network']:
- ipparam = ''
- if 'address' in container_config['network'][network]:
- ipparam = '--ip ' + container_config['network'][network]['address']
- _cmd(f'podman run --name {name} -dit --net {network} {ipparam} {port} {volume} {env_opt} {image}')
-
- # Else container is already created. Just start it.
- # It's needed after reboot.
- elif container_status(name) != 'running':
- _cmd(f'podman start {name}')
+ image = container_config['image']
+
+ if 'disable' in container_config:
+ # check if there is a container by that name running
+ tmp = _cmd('podman ps -a --format "{{.Names}}"')
+ if name in tmp:
+ _cmd(f'podman stop {name}')
+ _cmd(f'podman rm --force {name}')
+ continue
+
+ memory = container_config['memory']
+ restart = container_config['restart']
+
+ # Check if requested container image exists locally. If it does not, we
+ # pull it. print() is the best way to have a good response from the
+ # polling process to the user to display progress. If the image exists
+ # locally, a user can update it running `update container image <name>`
+ tmp = run(f'podman image exists {image}')
+ if tmp != 0: print(os.system(f'podman pull {image}'))
+
+ # Check/set environment options "-e foo=bar"
+ env_opt = ''
+ if 'environment' in container_config:
+ for k, v in container_config['environment'].items():
+ env_opt += f" -e \"{k}={v['value']}\""
+
+ # Publish ports
+ port = ''
+ if 'port' in container_config:
+ protocol = ''
+ for portmap in container_config['port']:
+ if 'protocol' in container_config['port'][portmap]:
+ protocol = container_config['port'][portmap]['protocol']
+ protocol = f'/{protocol}'
+ else:
+ protocol = '/tcp'
+ sport = container_config['port'][portmap]['source']
+ dport = container_config['port'][portmap]['destination']
+ port += f' -p {sport}:{dport}{protocol}'
+
+ # Bind volume
+ volume = ''
+ if 'volume' in container_config:
+ for vol, vol_config in container_config['volume'].items():
+ svol = vol_config['source']
+ dvol = vol_config['destination']
+ volume += f' -v {svol}:{dvol}'
+
+ container_base_cmd = f'podman run --detach --interactive --tty --replace ' \
+ f'--memory {memory}m --memory-swap 0 --restart {restart} ' \
+ f'--name {name} {port} {volume} {env_opt}'
+ if 'allow_host_networks' in container_config:
+ _cmd(f'{container_base_cmd} --net host {image}')
+ else:
+ for network in container_config['network']:
+ ipparam = ''
+ if 'address' in container_config['network'][network]:
+ ipparam = '--ip ' + container_config['network'][network]['address']
+ _cmd(f'{container_base_cmd} --net {network} {ipparam} {image}')
return None
diff --git a/src/conf_mode/firewall_options.py b/src/conf_mode/firewall_options.py
deleted file mode 100755
index 67bf5d0e2..000000000
--- a/src/conf_mode/firewall_options.py
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 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 sys
-import os
-import copy
-
-from vyos.config import Config
-from vyos import ConfigError
-from vyos.util import call
-
-from vyos import airbag
-airbag.enable()
-
-default_config_data = {
- 'intf_opts': [],
- 'new_chain4': False,
- 'new_chain6': False
-}
-
-def get_config(config=None):
- opts = copy.deepcopy(default_config_data)
- if config:
- conf = config
- else:
- conf = Config()
- if not conf.exists('firewall options'):
- # bail out early
- return opts
- else:
- conf.set_level('firewall options')
-
- # Parse configuration of each individual instance
- if conf.exists('interface'):
- for intf in conf.list_nodes('interface'):
- conf.set_level('firewall options interface {0}'.format(intf))
- config = {
- 'intf': intf,
- 'disabled': False,
- 'mss4': '',
- 'mss6': ''
- }
-
- # Check if individual option is disabled
- if conf.exists('disable'):
- config['disabled'] = True
-
- #
- # Get MSS value IPv4
- #
- if conf.exists('adjust-mss'):
- config['mss4'] = conf.return_value('adjust-mss')
-
- # We need a marker that a new iptables chain needs to be generated
- if not opts['new_chain4']:
- opts['new_chain4'] = True
-
- #
- # Get MSS value IPv6
- #
- if conf.exists('adjust-mss6'):
- config['mss6'] = conf.return_value('adjust-mss6')
-
- # We need a marker that a new ip6tables chain needs to be generated
- if not opts['new_chain6']:
- opts['new_chain6'] = True
-
- # Append interface options to global list
- opts['intf_opts'].append(config)
-
- return opts
-
-def verify(tcp):
- # syntax verification is done via cli
- return None
-
-def apply(tcp):
- target = 'VYOS_FW_OPTIONS'
-
- # always cleanup iptables
- call('iptables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
- call('iptables --table mangle --flush {} >&/dev/null'.format(target))
- call('iptables --table mangle --delete-chain {} >&/dev/null'.format(target))
-
- # always cleanup ip6tables
- call('ip6tables --table mangle --delete FORWARD --jump {} >&/dev/null'.format(target))
- call('ip6tables --table mangle --flush {} >&/dev/null'.format(target))
- call('ip6tables --table mangle --delete-chain {} >&/dev/null'.format(target))
-
- # Setup new iptables rules
- if tcp['new_chain4']:
- call('iptables --table mangle --new-chain {} >&/dev/null'.format(target))
- call('iptables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
-
- for opts in tcp['intf_opts']:
- intf = opts['intf']
- mss = opts['mss4']
-
- # Check if this rule iis disabled
- if opts['disabled']:
- continue
-
- # adjust TCP MSS per interface
- if mss:
- call('iptables --table mangle --append {} --out-interface {} --protocol tcp '
- '--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
-
- # Setup new ip6tables rules
- if tcp['new_chain6']:
- call('ip6tables --table mangle --new-chain {} >&/dev/null'.format(target))
- call('ip6tables --table mangle --append FORWARD --jump {} >&/dev/null'.format(target))
-
- for opts in tcp['intf_opts']:
- intf = opts['intf']
- mss = opts['mss6']
-
- # Check if this rule iis disabled
- if opts['disabled']:
- continue
-
- # adjust TCP MSS per interface
- if mss:
- call('ip6tables --table mangle --append {} --out-interface {} --protocol tcp '
- '--tcp-flags SYN,RST SYN --jump TCPMSS --set-mss {} >&/dev/null'.format(target, intf, mss))
-
- return None
-
-if __name__ == '__main__':
-
- try:
- c = get_config()
- verify(c)
- apply(c)
- except ConfigError as e:
- print(e)
- sys.exit(1)
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 74e29ed82..6be4e918b 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2020 VyOS maintainers and contributors
+# Copyright (C) 2019-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
@@ -273,6 +273,9 @@ def verify(openvpn):
if openvpn['protocol'] == 'tcp-active':
raise ConfigError('Protocol "tcp-active" is not valid in server mode')
+ if dict_search('authentication.username', openvpn) or dict_search('authentication.password', openvpn):
+ raise ConfigError('Cannot specify "authentication" in server mode')
+
if 'remote_port' in openvpn:
raise ConfigError('Cannot specify "remote-port" in server mode')
diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index 6c4c6c95b..584adc75e 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2020 VyOS maintainers and contributors
+# Copyright (C) 2019-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
@@ -22,12 +22,16 @@ from netifaces import interfaces
from vyos.config import Config
from vyos.configdict import get_interface_dict
+from vyos.configdict import leaf_node_changed
from vyos.configverify import verify_authentication
from vyos.configverify import verify_source_interface
+from vyos.configverify import verify_interface_exists
from vyos.configverify import verify_vrf
from vyos.configverify import verify_mtu_ipv6
+from vyos.ifconfig import PPPoEIf
from vyos.template import render
from vyos.util import call
+from vyos.util import is_systemd_service_running
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -44,6 +48,32 @@ def get_config(config=None):
base = ['interfaces', 'pppoe']
pppoe = get_interface_dict(conf, base)
+ # We should only terminate the PPPoE session if critical parameters change.
+ # All parameters that can be changed on-the-fly (like interface description)
+ # should not lead to a reconnect!
+ tmp = leaf_node_changed(conf, ['access-concentrator'])
+ if tmp: pppoe.update({'shutdown_required': {}})
+
+ tmp = leaf_node_changed(conf, ['connect-on-demand'])
+ if tmp: pppoe.update({'shutdown_required': {}})
+
+ tmp = leaf_node_changed(conf, ['service-name'])
+ if tmp: pppoe.update({'shutdown_required': {}})
+
+ tmp = leaf_node_changed(conf, ['source-interface'])
+ if tmp: pppoe.update({'shutdown_required': {}})
+
+ tmp = leaf_node_changed(conf, ['vrf'])
+ # leaf_node_changed() returns a list, as VRF is a non-multi node, there
+ # will be only one list element
+ if tmp: pppoe.update({'vrf_old': tmp[0]})
+
+ tmp = leaf_node_changed(conf, ['authentication', 'user'])
+ if tmp: pppoe.update({'shutdown_required': {}})
+
+ tmp = leaf_node_changed(conf, ['authentication', 'password'])
+ if tmp: pppoe.update({'shutdown_required': {}})
+
return pppoe
def verify(pppoe):
@@ -66,57 +96,42 @@ def generate(pppoe):
# rendered into
ifname = pppoe['ifname']
config_pppoe = f'/etc/ppp/peers/{ifname}'
- script_pppoe_pre_up = f'/etc/ppp/ip-pre-up.d/1000-vyos-pppoe-{ifname}'
- script_pppoe_ip_up = f'/etc/ppp/ip-up.d/1000-vyos-pppoe-{ifname}'
- script_pppoe_ip_down = f'/etc/ppp/ip-down.d/1000-vyos-pppoe-{ifname}'
- script_pppoe_ipv6_up = f'/etc/ppp/ipv6-up.d/1000-vyos-pppoe-{ifname}'
- config_wide_dhcp6c = f'/run/dhcp6c/dhcp6c.{ifname}.conf'
-
- config_files = [config_pppoe, script_pppoe_pre_up, script_pppoe_ip_up,
- script_pppoe_ip_down, script_pppoe_ipv6_up, config_wide_dhcp6c]
if 'deleted' in pppoe or 'disable' in pppoe:
- # stop DHCPv6-PD client
- call(f'systemctl stop dhcp6c@{ifname}.service')
- # Hang-up PPPoE connection
- call(f'systemctl stop ppp@{ifname}.service')
-
- # Delete PPP configuration files
- for file in config_files:
- if os.path.exists(file):
- os.unlink(file)
+ if os.path.exists(config_pppoe):
+ os.unlink(config_pppoe)
return None
# Create PPP configuration files
- render(config_pppoe, 'pppoe/peer.tmpl', pppoe, permission=0o755)
-
- # Create script for ip-pre-up.d
- render(script_pppoe_pre_up, 'pppoe/ip-pre-up.script.tmpl', pppoe,
- permission=0o755)
- # Create script for ip-up.d
- render(script_pppoe_ip_up, 'pppoe/ip-up.script.tmpl', pppoe,
- permission=0o755)
- # Create script for ip-down.d
- render(script_pppoe_ip_down, 'pppoe/ip-down.script.tmpl', pppoe,
- permission=0o755)
- # Create script for ipv6-up.d
- render(script_pppoe_ipv6_up, 'pppoe/ipv6-up.script.tmpl', pppoe,
- permission=0o755)
-
- if 'dhcpv6_options' in pppoe and 'pd' in pppoe['dhcpv6_options']:
- # ipv6.tmpl relies on ifname - this should be made consitent in the
- # future better then double key-ing the same value
- render(config_wide_dhcp6c, 'dhcp-client/ipv6.tmpl', pppoe)
+ render(config_pppoe, 'pppoe/peer.tmpl', pppoe, permission=0o640)
return None
def apply(pppoe):
+ ifname = pppoe['ifname']
if 'deleted' in pppoe or 'disable' in pppoe:
- call('systemctl stop ppp@{ifname}.service'.format(**pppoe))
+ if os.path.isdir(f'/sys/class/net/{ifname}'):
+ p = PPPoEIf(ifname)
+ p.remove()
+ call(f'systemctl stop ppp@{ifname}.service')
return None
- call('systemctl restart ppp@{ifname}.service'.format(**pppoe))
+ # reconnect should only be necessary when certain config options change,
+ # like ACS name, authentication, no-peer-dns, source-interface
+ if ((not is_systemd_service_running(f'ppp@{ifname}.service')) or
+ 'shutdown_required' in pppoe):
+
+ # cleanup system (e.g. FRR routes first)
+ if os.path.isdir(f'/sys/class/net/{ifname}'):
+ p = PPPoEIf(ifname)
+ p.remove()
+
+ call(f'systemctl restart ppp@{ifname}.service')
+ else:
+ if os.path.isdir(f'/sys/class/net/{ifname}'):
+ p = PPPoEIf(ifname)
+ p.update(pppoe)
return None
diff --git a/src/conf_mode/interfaces-wwan.py b/src/conf_mode/interfaces-wwan.py
index 31c599145..faa5eb628 100755
--- a/src/conf_mode/interfaces-wwan.py
+++ b/src/conf_mode/interfaces-wwan.py
@@ -26,7 +26,6 @@ from vyos.configverify import verify_vrf
from vyos.ifconfig import WWANIf
from vyos.util import cmd
from vyos.util import dict_search
-from vyos.template import render
from vyos import ConfigError
from vyos import airbag
airbag.enable()
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index dae958774..59939d0fb 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -139,12 +139,10 @@ def verify(nat):
for rule, config in dict_search('source.rule', nat).items():
err_msg = f'Source NAT configuration error in rule {rule}:'
if 'outbound_interface' not in config:
- raise ConfigError(f'{err_msg}\n' \
- 'outbound-interface not specified')
- else:
- if config['outbound_interface'] not in 'any' and config['outbound_interface'] not in interfaces():
- print(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system')
+ raise ConfigError(f'{err_msg} outbound-interface not specified')
+ if config['outbound_interface'] not in 'any' and config['outbound_interface'] not in interfaces():
+ print(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system')
addr = dict_search('translation.address', config)
if addr != None:
diff --git a/src/conf_mode/nat66.py b/src/conf_mode/nat66.py
index e2bd6417d..f8bc073bb 100755
--- a/src/conf_mode/nat66.py
+++ b/src/conf_mode/nat66.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-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
@@ -55,7 +55,7 @@ def get_config(config=None):
conf = config
else:
conf = Config()
-
+
base = ['nat66']
nat = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
@@ -90,7 +90,7 @@ def get_config(config=None):
# be done only once
if not get_handler(condensed_json, 'PREROUTING', 'NAT_CONNTRACK'):
nat['helper_functions'] = 'add'
-
+
# Retrieve current table handler positions
nat['pre_ct_ignore'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_IGNORE')
nat['pre_ct_conntrack'] = get_handler(condensed_json, 'PREROUTING', 'VYATTA_CT_PREROUTING_HOOK')
@@ -109,21 +109,22 @@ def verify(nat):
if 'helper_functions' in nat and nat['helper_functions'] != 'has':
if not (nat['pre_ct_conntrack'] or nat['out_ct_conntrack']):
raise Exception('could not determine nftable ruleset handlers')
-
+
if dict_search('source.rule', nat):
for rule, config in dict_search('source.rule', nat).items():
err_msg = f'Source NAT66 configuration error in rule {rule}:'
if 'outbound_interface' not in config:
- raise ConfigError(f'{err_msg}\n' \
- 'outbound-interface not specified')
- else:
- if config['outbound_interface'] not in interfaces():
- print(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system')
+ raise ConfigError(f'{err_msg} outbound-interface not specified')
+
+ if config['outbound_interface'] not in interfaces():
+ print(f'WARNING: rule "{rule}" interface "{config["outbound_interface"]}" does not exist on this system')
addr = dict_search('translation.address', config)
if addr != None:
if addr != 'masquerade' and not is_ipv6(addr):
raise ConfigError(f'Warning: IPv6 address {addr} is not a valid address')
+ else:
+ raise ConfigError(f'{err_msg} translation address not specified')
prefix = dict_search('source.prefix', config)
if prefix != None:
@@ -145,7 +146,7 @@ def verify(nat):
def generate(nat):
render(iptables_nat_config, 'firewall/nftables-nat66.tmpl', nat, permission=0o755)
- render(ndppd_config, 'proxy-ndp/ndppd.conf.tmpl', nat, permission=0o755)
+ render(ndppd_config, 'ndppd/ndppd.conf.tmpl', nat, permission=0o755)
return None
def apply(nat):
diff --git a/src/conf_mode/policy-local-route.py b/src/conf_mode/policy-local-route.py
index 013f22665..539189442 100755
--- a/src/conf_mode/policy-local-route.py
+++ b/src/conf_mode/policy-local-route.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-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
@@ -44,17 +44,26 @@ def get_config(config=None):
if tmp:
for rule in (tmp or []):
src = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'source'])
+ fwmk = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'fwmark'])
if src:
dict = dict_merge({'rule_remove' : {rule : {'source' : src}}}, dict)
pbr.update(dict)
+ if fwmk:
+ dict = dict_merge({'rule_remove' : {rule : {'fwmark' : fwmk}}}, dict)
+ pbr.update(dict)
# delete policy local-route rule x source x.x.x.x
+ # delete policy local-route rule x fwmark x
if 'rule' in pbr:
for rule in pbr['rule']:
src = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'source'])
+ fwmk = leaf_node_changed(conf, ['policy', 'local-route', 'rule', rule, 'fwmark'])
if src:
dict = dict_merge({'rule_remove' : {rule : {'source' : src}}}, dict)
pbr.update(dict)
+ if fwmk:
+ dict = dict_merge({'rule_remove' : {rule : {'fwmark' : fwmk}}}, dict)
+ pbr.update(dict)
return pbr
@@ -65,8 +74,8 @@ def verify(pbr):
if 'rule' in pbr:
for rule in pbr['rule']:
- if 'source' not in pbr['rule'][rule]:
- raise ConfigError('Source address required!')
+ if 'source' not in pbr['rule'][rule] and 'fwmark' not in pbr['rule'][rule]:
+ raise ConfigError('Source address or fwmark is required!')
else:
if 'set' not in pbr['rule'][rule] or 'table' not in pbr['rule'][rule]['set']:
raise ConfigError('Table set is required!')
@@ -86,16 +95,34 @@ def apply(pbr):
# Delete old rule if needed
if 'rule_remove' in pbr:
for rule in pbr['rule_remove']:
- for src in pbr['rule_remove'][rule]['source']:
- call(f'ip rule del prio {rule} from {src}')
+ if 'source' in pbr['rule_remove'][rule]:
+ for src in pbr['rule_remove'][rule]['source']:
+ call(f'ip rule del prio {rule} from {src}')
+ if 'fwmark' in pbr['rule_remove'][rule]:
+ for fwmk in pbr['rule_remove'][rule]['fwmark']:
+ call(f'ip rule del prio {rule} from all fwmark {fwmk}')
# Generate new config
if 'rule' in pbr:
for rule in pbr['rule']:
table = pbr['rule'][rule]['set']['table']
- if pbr['rule'][rule]['source']:
+ # Only source in the rule
+ # set policy local-route rule 100 source '203.0.113.1'
+ if 'source' in pbr['rule'][rule] and not 'fwmark' in pbr['rule'][rule]:
for src in pbr['rule'][rule]['source']:
call(f'ip rule add prio {rule} from {src} lookup {table}')
+ # Only fwmark in the rule
+ # set policy local-route rule 101 fwmark '23'
+ if 'fwmark' in pbr['rule'][rule] and not 'source' in pbr['rule'][rule]:
+ fwmk = pbr['rule'][rule]['fwmark']
+ call(f'ip rule add prio {rule} from all fwmark {fwmk} lookup {table}')
+ # Source and fwmark in the rule
+ # set policy local-route rule 100 source '203.0.113.1'
+ # set policy local-route rule 100 fwmark '23'
+ if 'source' in pbr['rule'][rule] and 'fwmark' in pbr['rule'][rule]:
+ fwmk = pbr['rule'][rule]['fwmark']
+ for src in pbr['rule'][rule]['source']:
+ call(f'ip rule add prio {rule} from {src} fwmark {fwmk} lookup {table}')
return None
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 9ecfd07fe..7d05eed9f 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -23,6 +23,7 @@ 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
@@ -221,27 +222,47 @@ def verify(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', bgp) == None:
- pass
- else:
- if dict_search('parameters.distance.global', bgp):
- 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}!')
-
- # Throw an error if the address family specific administrative distance parameters aren't all filled out.
- if dict_search('address_family', bgp) == None:
- pass
- else:
- for address_family_name in dict_search('address_family', bgp):
- if dict_search(f'address_family.{address_family_name}.distance', bgp) == None:
- pass
- else:
+ 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}!')
+
+ # 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 dict_search(f'address_family.{address_family_name}.distance.{key}', bgp) == None:
+ if key not in afi_config['distance']:
raise ConfigError('Missing mandatory configuration option for '\
- f'{address_family_name} administrative distance {key}!')
+ f'{afi} administrative distance {key}!')
+
+ if afi in ['ipv4_unicast', 'ipv6_unicast']:
+ if 'import' in afi_config and 'vrf' in afi_config['import']:
+ # Check if VRF exists
+ verify_vrf(afi_config['import']['vrf'])
+
+ # 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)
+
+ if afi in ['l2vpn_evpn'] and 'vrf' not in bgp:
+ # Some L2VPN EVPN AFI options are only supported under VRF
+ if 'vni' in afi_config:
+ for vni, vni_config in afi_config['vni'].items():
+ if 'rd' in vni_config:
+ raise ConfigError('VNI route-distinguisher is only supported under EVPN VRF')
+ if 'route_target' in vni_config:
+ raise ConfigError('VNI route-target is only supported under EVPN VRF')
return None
diff --git a/src/conf_mode/protocols_isis.py b/src/conf_mode/protocols_isis.py
index d4c82249b..4cf0312e9 100755
--- a/src/conf_mode/protocols_isis.py
+++ b/src/conf_mode/protocols_isis.py
@@ -113,9 +113,13 @@ def verify(isis):
# Interface MTU must be >= configured lsp-mtu
mtu = Interface(interface).get_mtu()
area_mtu = isis['lsp_mtu']
- if mtu < int(area_mtu):
- raise ConfigError(f'Interface {interface} has MTU {mtu}, minimum ' \
- f'area MTU is {area_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
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 78c1c82bd..06a29106d 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -149,14 +149,23 @@ def verify(ospf):
if route_map_name: verify_route_map(route_map_name, ospf)
if 'interface' in ospf:
- for interface in ospf['interface']:
+ 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(ospf['interface'][interface]):
+ 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 'vrf' in ospf:
# If interface specific options are set, we must ensure that the
# interface is bound to our requesting VRF. Due to the VyOS
@@ -177,7 +186,7 @@ def generate(ospf):
ospf['protocol'] = 'ospf' # required for frr/vrf.route-map.frr.tmpl
ospf['frr_zebra_config'] = render_to_string('frr/vrf.route-map.frr.tmpl', ospf)
- ospf['frr_ospfd_config'] = render_to_string('frr/ospf.frr.tmpl', ospf)
+ ospf['frr_ospfd_config'] = render_to_string('frr/ospfd.frr.tmpl', ospf)
return None
def apply(ospf):
diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py
index fef0f509b..536ffa690 100755
--- a/src/conf_mode/protocols_ospfv3.py
+++ b/src/conf_mode/protocols_ospfv3.py
@@ -65,7 +65,7 @@ def verify(ospfv3):
if 'ifmtu' in if_config:
mtu = Interface(ifname).get_mtu()
if int(if_config['ifmtu']) > int(mtu):
- raise ConfigError(f'OSPFv3 ifmtu cannot go beyond physical MTU of "{mtu}"')
+ raise ConfigError(f'OSPFv3 ifmtu can not exceed physical MTU of "{mtu}"')
return None
@@ -74,7 +74,7 @@ def generate(ospfv3):
ospfv3['new_frr_config'] = ''
return None
- ospfv3['new_frr_config'] = render_to_string('frr/ospfv3.frr.tmpl', ospfv3)
+ ospfv3['new_frr_config'] = render_to_string('frr/ospf6d.frr.tmpl', ospfv3)
return None
def apply(ospfv3):
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index d3065fc47..ff6090e22 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -286,20 +286,34 @@ def verify(ipsec):
if 'pre_shared_secret' not in ra_conf['authentication']:
raise ConfigError(f"Missing pre-shared-key on {name} remote-access config")
+ if 'client_mode' not in ra_conf['authentication']:
+ raise ConfigError('Client authentication method is required!')
- if 'client_mode' in ra_conf['authentication']:
- if ra_conf['authentication']['client_mode'] == 'eap-radius':
- if 'radius' not in ipsec['remote_access'] or 'server' not in ipsec['remote_access']['radius'] or len(ipsec['remote_access']['radius']['server']) == 0:
- raise ConfigError('RADIUS authentication requires at least one server')
+ if dict_search('authentication.client_mode', ra_conf) == 'eap-radius':
+ if dict_search('remote_access.radius.server', ipsec) == None:
+ raise ConfigError('RADIUS authentication requires at least one server')
if 'pool' in ra_conf:
+ if {'dhcp', 'radius'} <= set(ra_conf['pool']):
+ raise ConfigError(f'Can not use both DHCP and RADIUS for address allocation '\
+ f'at the same time for "{name}"!')
+
if 'dhcp' in ra_conf['pool'] and len(ra_conf['pool']) > 1:
- raise ConfigError(f'Can not use both DHCP and a predefined address pool for "{name}"!')
+ raise ConfigError(f'Can not use DHCP and a predefined address pool for "{name}"!')
+
+ if 'radius' in ra_conf['pool'] and len(ra_conf['pool']) > 1:
+ raise ConfigError(f'Can not use RADIUS and a predefined address pool for "{name}"!')
for pool in ra_conf['pool']:
if pool == 'dhcp':
if dict_search('remote_access.dhcp.server', ipsec) == None:
raise ConfigError('IPSec DHCP server is not configured!')
+ elif pool == 'radius':
+ if dict_search('remote_access.radius.server', ipsec) == None:
+ raise ConfigError('IPSec RADIUS server is not configured!')
+
+ if dict_search('authentication.client_mode', ra_conf) != 'eap-radius':
+ raise ConfigError('RADIUS IP pool requires eap-radius client authentication!')
elif 'pool' not in ipsec['remote_access'] or pool not in ipsec['remote_access']['pool']:
raise ConfigError(f'Requested pool "{pool}" does not exist!')
diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py
index c1cfc1dcb..919083ac4 100755
--- a/src/conf_mode/vrf.py
+++ b/src/conf_mode/vrf.py
@@ -24,7 +24,6 @@ from vyos.config import Config
from vyos.configdict import node_changed
from vyos.ifconfig import Interface
from vyos.template import render
-from vyos.template import render_to_string
from vyos.util import call
from vyos.util import cmd
from vyos.util import dict_search
@@ -32,12 +31,9 @@ from vyos.util import get_interface_config
from vyos.util import popen
from vyos.util import run
from vyos import ConfigError
-from vyos import frr
from vyos import airbag
airbag.enable()
-frr_daemon = 'zebra'
-
config_file = r'/etc/iproute2/rt_tables.d/vyos-vrf.conf'
def list_rules():
@@ -131,7 +127,6 @@ def verify(vrf):
def generate(vrf):
render(config_file, 'vrf/vrf.conf.tmpl', vrf)
- vrf['new_frr_config'] = render_to_string('frr/vrf.frr.tmpl', vrf)
# Render nftables zones config
vrf['nft_vrf_zones'] = NamedTemporaryFile().name
render(vrf['nft_vrf_zones'], 'firewall/nftables-vrf-zones.tmpl', vrf)
@@ -242,21 +237,6 @@ def apply(vrf):
if tmp == 0:
cmd('nft delete table inet vrf_zones')
- # T3694: Somehow we hit a priority inversion here as we need to remove the
- # VRF assigned VNI before we can remove a BGP bound VRF instance. Maybe
- # move this to an individual helper script that set's up the VNI for the
- # given VRF after any routing protocol.
- #
- # # add configuration to FRR
- # frr_cfg = frr.FRRConfig()
- # frr_cfg.load_configuration(frr_daemon)
- # frr_cfg.modify_section(f'^vrf [a-zA-Z-]*$', '')
- # frr_cfg.add_before(r'(interface .*|line vty)', vrf['new_frr_config'])
- # frr_cfg.commit_configuration(frr_daemon)
- #
- # # Save configuration to /run/frr/config/frr.conf
- # frr.save_configuration()
-
return None
if __name__ == '__main__':
diff --git a/src/conf_mode/vrf_vni.py b/src/conf_mode/vrf_vni.py
new file mode 100755
index 000000000..87ee8f2d1
--- /dev/null
+++ b/src/conf_mode/vrf_vni.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2020-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/>.
+
+from sys import argv
+from sys import exit
+
+from vyos.config import Config
+from vyos.template import render_to_string
+from vyos import ConfigError
+from vyos import frr
+from vyos import airbag
+airbag.enable()
+
+frr_daemon = 'zebra'
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+
+ # This script only works with a passed VRF name
+ if len(argv) < 1:
+ raise NotImplementedError
+ vrf = argv[1]
+
+ # "assemble" dict - easier here then use a full blown get_config_dict()
+ # on a single leafNode
+ vni = { 'vrf' : vrf }
+ tmp = conf.return_value(['vrf', 'name', vrf, 'vni'])
+ if tmp: vni.update({ 'vni' : tmp })
+
+ return vni
+
+def verify(vni):
+ return None
+
+def generate(vni):
+ vni['new_frr_config'] = render_to_string('frr/vrf-vni.frr.tmpl', vni)
+ return None
+
+def apply(vni):
+ # add configuration to FRR
+ frr_cfg = frr.FRRConfig()
+ frr_cfg.load_configuration(frr_daemon)
+ frr_cfg.modify_section(f'^vrf [a-zA-Z-]*$', '')
+ frr_cfg.add_before(r'(interface .*|line vty)', vni['new_frr_config'])
+ frr_cfg.commit_configuration(frr_daemon)
+
+ # Save configuration to /run/frr/config/frr.conf
+ frr.save_configuration()
+
+ 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/etc/ipsec.d/vti-up-down b/src/etc/ipsec.d/vti-up-down
index 281c9bf2b..011013a2e 100755
--- a/src/etc/ipsec.d/vti-up-down
+++ b/src/etc/ipsec.d/vti-up-down
@@ -55,7 +55,7 @@ if __name__ == '__main__':
syslog(f'Interface {interface} not found')
sys.exit(0)
- vti_link_up = (vti_link['operstate'] == 'UP' if 'operstate' in vti_link else False)
+ vti_link_up = (vti_link['operstate'] != 'DOWN' if 'operstate' in vti_link else False)
config = ConfigTreeQuery()
vti_dict = config.get_config_dict(['interfaces', 'vti', interface],
diff --git a/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback b/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback
new file mode 100755
index 000000000..bb918a468
--- /dev/null
+++ b/src/etc/ppp/ip-up.d/99-vyos-pppoe-callback
@@ -0,0 +1,59 @@
+#!/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/>.
+
+# This is a Python hook script which is invoked whenever a PPPoE session goes
+# "ip-up". It will call into our vyos.ifconfig library and will then execute
+# common tasks for the PPPoE interface. The reason we have to "hook" this is
+# that we can not create a pppoeX interface in advance in linux and then connect
+# pppd to this already existing interface.
+
+from sys import argv
+from sys import exit
+
+from syslog import syslog
+from syslog import openlog
+from syslog import LOG_PID
+from syslog import LOG_INFO
+
+from vyos.configquery import ConfigTreeQuery
+from vyos.ifconfig import PPPoEIf
+from vyos.util import read_file
+
+# When the ppp link comes up, this script is called with the following
+# parameters
+# $1 the interface name used by pppd (e.g. ppp3)
+# $2 the tty device name
+# $3 the tty device speed
+# $4 the local IP address for the interface
+# $5 the remote IP address
+# $6 the parameter specified by the 'ipparam' option to pppd
+
+if (len(argv) < 7):
+ exit(1)
+
+interface = argv[6]
+dialer_pid = read_file(f'/var/run/{interface}.pid')
+
+openlog(ident=f'pppd[{dialer_pid}]', facility=LOG_INFO)
+syslog('executing ' + argv[0])
+
+conf = ConfigTreeQuery()
+pppoe = conf.get_config_dict(['interfaces', 'pppoe', argv[6]],
+ get_first_key=True, key_mangling=('-', '_'))
+pppoe['ifname'] = argv[6]
+
+p = PPPoEIf(pppoe['ifname'])
+p.update(pppoe)
diff --git a/src/etc/sysctl.d/32-vyos-podman.conf b/src/etc/sysctl.d/32-vyos-podman.conf
new file mode 100644
index 000000000..7068bf88d
--- /dev/null
+++ b/src/etc/sysctl.d/32-vyos-podman.conf
@@ -0,0 +1,5 @@
+# Increase inotify watchers as per https://bugzilla.redhat.com/show_bug.cgi?id=1829596
+fs.inotify.max_queued_events = 1048576
+fs.inotify.max_user_instances = 1048576
+fs.inotify.max_user_watches = 1048576
+
diff --git a/src/etc/udev/rules.d/90-vyos-serial.rules b/src/etc/udev/rules.d/90-vyos-serial.rules
index 3f10f4924..872fd4fea 100644
--- a/src/etc/udev/rules.d/90-vyos-serial.rules
+++ b/src/etc/udev/rules.d/90-vyos-serial.rules
@@ -8,7 +8,7 @@ SUBSYSTEMS=="pci", IMPORT{builtin}="hwdb --subsystem=pci"
SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
# /dev/serial/by-path/, /dev/serial/by-id/ for USB devices
-KERNEL!="ttyUSB[0-9]*|ttyACM[0-9]*", GOTO="serial_end"
+KERNEL!="ttyUSB[0-9]*", GOTO="serial_end"
SUBSYSTEMS=="usb-serial", ENV{.ID_PORT}="$attr{port_number}"
@@ -18,11 +18,11 @@ IMPORT{builtin}="path_id", IMPORT{builtin}="usb_id"
#
# - $env{ID_PATH} usually is a name like: "pci-0000:00:10.0-usb-0:2.3.3.4:1.0-port0" so we strip the "pci-*"
# portion and only use the usb part
-# - Transform the USB "speach" to the tree like structure so we start with "usb0" as root-complex 0.
+# - Transform the USB "speech" to the tree like structure so we start with "usb0" as root-complex 0.
# (tr -d -) does the replacement
# - Replace the first group after ":" to represent the bus relation (sed -e 0,/:/s//b/) indicated by "b"
# - Replace the next group after ":" to represent the port relation (sed -e 0,/:/s//p/) indicated by "p"
-ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", PROGRAM="/bin/sh -c 'D=$env{ID_PATH}; echo ${D:17} | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"
-ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", PROGRAM="/bin/sh -c 'D=$env{ID_PATH}; echo ${D:17} | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"
+ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="", PROGRAM="/bin/sh -c 'echo $env{ID_PATH:17} | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"
+ENV{ID_PATH}=="?*", ENV{.ID_PORT}=="?*", PROGRAM="/bin/sh -c 'echo $env{ID_PATH:17} | tr -d - | sed -e 0,/:/s//b/ | sed -e 0,/:/s//p/'", SYMLINK+="serial/by-bus/$result"
LABEL="serial_end"
diff --git a/src/etc/update-motd.d/99-reboot b/src/etc/update-motd.d/99-reboot
new file mode 100755
index 000000000..718be1a7a
--- /dev/null
+++ b/src/etc/update-motd.d/99-reboot
@@ -0,0 +1,7 @@
+#!/bin/vbash
+source /opt/vyatta/etc/functions/script-template
+if [ -f /run/systemd/shutdown/scheduled ]; then
+ echo
+ run show reboot
+fi
+exit
diff --git a/src/migration-scripts/conntrack/2-to-3 b/src/migration-scripts/conntrack/2-to-3
new file mode 100755
index 000000000..8a8b43279
--- /dev/null
+++ b/src/migration-scripts/conntrack/2-to-3
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+
+# Conntrack syntax version 3
+# Enables all conntrack modules (previous default behaviour) and omits manually disabled modules.
+
+import sys
+
+from vyos.configtree import ConfigTree
+from vyos.version import get_version
+
+if len(sys.argv) < 1:
+ print('Must specify file name!')
+ sys.exit(1)
+
+filename = sys.argv[1]
+
+with open(filename, 'r') as f:
+ config = ConfigTree(f.read())
+
+module_path = ['system', 'conntrack', 'modules']
+
+# Go over all conntrack modules available as of v1.3.0.
+for module in ['ftp', 'h323', 'nfs', 'pptp', 'sip', 'sqlnet', 'tftp']:
+ # 'disable' is being phased out.
+ if config.exists(module_path + [module, 'disable']):
+ config.delete(module_path + [module])
+ # If it wasn't manually 'disable'd, it was enabled by default.
+ else:
+ config.set(module_path + [module])
+
+try:
+ if config.exists(module_path):
+ with open(filename, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print(f'Failed to save the modified config: {e}')
+ sys.exit(1)
diff --git a/src/migration-scripts/firewall/5-to-6 b/src/migration-scripts/firewall/5-to-6
new file mode 100755
index 000000000..ccb86830a
--- /dev/null
+++ b/src/migration-scripts/firewall/5-to-6
@@ -0,0 +1,63 @@
+#!/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/>.
+
+# T3090: migrate "firewall options interface <name> adjust-mss" to the
+# individual interface.
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+from vyos.ifconfig import Section
+
+if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+ config_file = f.read()
+
+base = ['firewall', 'options', 'interface']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+ # Nothing to do
+ exit(0)
+
+for interface in config.list_nodes(base):
+ if config.exists(base + [interface, 'disable']):
+ continue
+
+ if config.exists(base + [interface, 'adjust-mss']):
+ section = Section.section(interface)
+ tmp = config.return_value(base + [interface, 'adjust-mss'])
+ config.set(['interfaces', section, interface, 'ip', 'adjust-mss'], value=tmp)
+
+ if config.exists(base + [interface, 'adjust-mss6']):
+ section = Section.section(interface)
+ tmp = config.return_value(base + [interface, 'adjust-mss6'])
+ config.set(['interfaces', section, interface, 'ipv6', 'adjust-mss'], value=tmp)
+
+config.delete(['firewall', 'options'])
+
+try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)
diff --git a/src/op_mode/containers_op.py b/src/op_mode/containers_op.py
index 1e3fc3a8f..bc317029c 100755
--- a/src/op_mode/containers_op.py
+++ b/src/op_mode/containers_op.py
@@ -15,10 +15,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import argparse
-from vyos.configquery import query_context, ConfigQueryError
-from vyos.util import cmd
-config, op = query_context()
+from getpass import getuser
+from vyos.configquery import ConfigTreeQuery
+from vyos.util import cmd
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Show all containers")
@@ -26,34 +26,53 @@ parser.add_argument("-i", "--image", action="store_true", help="Show container i
parser.add_argument("-n", "--networks", action="store_true", help="Show container images")
parser.add_argument("-p", "--pull", action="store", help="Pull image for container")
parser.add_argument("-d", "--remove", action="store", help="Delete container image")
+parser.add_argument("-u", "--update", action="store", help="Update given container image")
-if not config.exists(['container']):
+config = ConfigTreeQuery()
+base = ['container']
+if not config.exists(base):
print('Containers not configured')
exit(0)
+if getuser() != 'root':
+ raise OSError('This functions needs to be run as root to return correct results!')
+
if __name__ == '__main__':
args = parser.parse_args()
if args.all:
print(cmd('podman ps --all'))
- exit(0)
- if args.image:
+
+ elif args.image:
print(cmd('podman image ls'))
- exit(0)
- if args.networks:
+
+ elif args.networks:
print(cmd('podman network ls'))
- exit(0)
- if args.pull:
+
+ elif args.pull:
image = args.pull
try:
- print(cmd(f'sudo podman image pull {image}'))
+ print(cmd(f'podman image pull {image}'))
except:
print(f'Can\'t find or download image "{image}"')
- exit(0)
- if args.remove:
+
+ elif args.remove:
image = args.remove
try:
- print(cmd(f'sudo podman image rm {image}'))
+ print(cmd(f'podman image rm {image}'))
except:
print(f'Can\'t delete image "{image}"')
- exit(0)
+
+ elif args.update:
+ tmp = config.get_config_dict(base + ['name', args.update],
+ key_mangling=('-', '_'), get_first_key=True)
+ try:
+ image = tmp['image']
+ print(cmd(f'podman image pull {image}'))
+ except:
+ print(f'Can\'t find or download image "{image}"')
+ else:
+ parser.print_help()
+ exit(1)
+
+ exit(0)
diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py
index 1fb61d263..d79b6c024 100755
--- a/src/op_mode/dns_forwarding_statistics.py
+++ b/src/op_mode/dns_forwarding_statistics.py
@@ -11,7 +11,7 @@ PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns'
OUT_TMPL_SRC = """
DNS forwarding statistics:
-Cache entries: {{ cache_entries -}}
+Cache entries: {{ cache_entries }}
Cache size: {{ cache_size }} kbytes
"""
diff --git a/src/op_mode/ikev2_profile_generator.py b/src/op_mode/ikev2_profile_generator.py
index d45525431..990b06c12 100755
--- a/src/op_mode/ikev2_profile_generator.py
+++ b/src/op_mode/ikev2_profile_generator.py
@@ -21,7 +21,7 @@ from sys import exit
from socket import getfqdn
from cryptography.x509.oid import NameOID
-from vyos.config import Config
+from vyos.configquery import ConfigTreeQuery
from vyos.pki import load_certificate
from vyos.template import render_to_string
from vyos.util import ask_input
@@ -117,7 +117,7 @@ args = parser.parse_args()
ipsec_base = ['vpn', 'ipsec']
config_base = ipsec_base + ['remote-access', 'connection']
pki_base = ['pki']
-conf = Config()
+conf = ConfigTreeQuery()
if not conf.exists(config_base):
exit('IPSec remote-access is not configured!')
@@ -153,7 +153,7 @@ cert = load_certificate(pki['certificate'][cert_name]['certificate'])
data['ca_cn'] = ca_cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
data['cert_cn'] = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value
-data['ca_cert'] = conf.return_value(pki_base + ['ca', ca_name, 'certificate'])
+data['ca_cert'] = conf.value(pki_base + ['ca', ca_name, 'certificate'])
esp_proposals = conf.get_config_dict(ipsec_base + ['esp-group', data['esp_group'], 'proposal'],
key_mangling=('-', '_'), get_first_key=True)
diff --git a/src/op_mode/pki.py b/src/op_mode/pki.py
index 297270cf1..36891d080 100755
--- a/src/op_mode/pki.py
+++ b/src/op_mode/pki.py
@@ -24,7 +24,7 @@ import tabulate
from cryptography import x509
from cryptography.x509.oid import ExtendedKeyUsageOID
-from vyos.config import Config
+from vyos.configquery import ConfigTreeQuery
from vyos.configdict import dict_merge
from vyos.pki import encode_certificate, encode_public_key, encode_private_key, encode_dh_parameters
from vyos.pki import create_certificate, create_certificate_request, create_certificate_revocation_list
@@ -41,10 +41,10 @@ CERT_REQ_END = '-----END CERTIFICATE REQUEST-----'
auth_dir = '/config/auth'
# Helper Functions
-
+conf = ConfigTreeQuery()
def get_default_values():
# Fetch default x509 values
- conf = Config()
+
base = ['pki', 'x509', 'default']
x509_defaults = conf.get_config_dict(base, key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
@@ -53,9 +53,7 @@ def get_default_values():
def get_config_ca_certificate(name=None):
# Fetch ca certificates from config
- conf = Config()
base = ['pki', 'ca']
-
if not conf.exists(base):
return False
@@ -69,9 +67,7 @@ def get_config_ca_certificate(name=None):
def get_config_certificate(name=None):
# Get certificates from config
- conf = Config()
base = ['pki', 'certificate']
-
if not conf.exists(base):
return False
@@ -100,7 +96,6 @@ def get_certificate_ca(cert, ca_certs):
def get_config_revoked_certificates():
# Fetch revoked certificates from config
- conf = Config()
ca_base = ['pki', 'ca']
cert_base = ['pki', 'certificate']
@@ -464,7 +459,7 @@ def generate_certificate_sign(name, ca_name, install=False, file=False):
if not cert_req:
print("Invalid certificate request")
return None
-
+
cert = generate_certificate(cert_req, ca_cert, ca_private_key, is_ca=False)
passphrase = ask_passphrase()
@@ -813,7 +808,7 @@ if __name__ == '__main__':
elif args.self_sign:
generate_certificate_selfsign(args.certificate, install=args.install, file=args.file)
else:
- generate_certificate_request(name=args.certificate, install=args.install)
+ generate_certificate_request(name=args.certificate, install=args.install, file=args.file)
elif args.crl:
generate_certificate_revocation_list(args.crl, install=args.install, file=args.file)
elif args.ssh:
diff --git a/src/op_mode/restart_frr.py b/src/op_mode/restart_frr.py
index d1b66b33f..0b2322478 100755
--- a/src/op_mode/restart_frr.py
+++ b/src/op_mode/restart_frr.py
@@ -155,7 +155,7 @@ def _check_args_daemon(daemons):
# define program arguments
cmd_args_parser = argparse.ArgumentParser(description='restart frr daemons')
cmd_args_parser.add_argument('--action', choices=['restart'], required=True, help='action to frr daemons')
-cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ospfd', 'ospf6d', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons')
+cmd_args_parser.add_argument('--daemon', choices=['bfdd', 'bgpd', 'ospfd', 'ospf6d', 'isisd', 'ripd', 'ripngd', 'staticd', 'zebra'], required=False, nargs='*', help='select single or multiple daemons')
# parse arguments
cmd_args = cmd_args_parser.parse_args()
diff --git a/src/op_mode/show_interfaces.py b/src/op_mode/show_interfaces.py
index 20d5d9e17..241fba4f4 100755
--- a/src/op_mode/show_interfaces.py
+++ b/src/op_mode/show_interfaces.py
@@ -120,10 +120,6 @@ def split_text(text, used=0):
yield line[1:]
-def get_vrrp_intf():
- return [intf for intf in Section.interfaces() if intf.is_vrrp()]
-
-
def get_counter_val(clear, now):
"""
attempt to correct a counter if it wrapped, copied from perl
diff --git a/src/op_mode/show_ipsec_sa.py b/src/op_mode/show_ipsec_sa.py
index e491267fd..c964caaeb 100755
--- a/src/op_mode/show_ipsec_sa.py
+++ b/src/op_mode/show_ipsec_sa.py
@@ -23,6 +23,12 @@ import hurry.filesize
import vyos.util
+def convert(text):
+ return int(text) if text.isdigit() else text.lower()
+
+def alphanum_key(key):
+ return [convert(c) for c in re.split('([0-9]+)', str(key))]
+
def format_output(conns, sas):
sa_data = []
@@ -111,7 +117,7 @@ if __name__ == '__main__':
headers = ["Connection", "State", "Uptime", "Bytes In/Out", "Packets In/Out", "Remote address", "Remote ID", "Proposal"]
sa_data = format_output(conns, sas)
- sa_data = sorted(sa_data, key=lambda peer: peer[0])
+ sa_data = sorted(sa_data, key=alphanum_key)
output = tabulate.tabulate(sa_data, headers)
print(output)
except PermissionError:
diff --git a/src/op_mode/show_nat_rules.py b/src/op_mode/show_nat_rules.py
index 0f40ecabe..4a059c848 100755
--- a/src/op_mode/show_nat_rules.py
+++ b/src/op_mode/show_nat_rules.py
@@ -67,46 +67,54 @@ if args.source or args.destination:
continue
interface = dict_search('match.right', data['expr'][0])
srcdest = ''
- for i in [1, 2]:
- srcdest_json = dict_search('match.right', data['expr'][i])
- if not srcdest_json:
- continue
-
- if isinstance(srcdest_json,str):
- srcdest += srcdest_json + ' '
- elif 'prefix' in srcdest_json:
- addr_tmp = dict_search('match.right.prefix.addr', data['expr'][i])
- len_tmp = dict_search('match.right.prefix.len', data['expr'][i])
- if addr_tmp and len_tmp:
- srcdest = addr_tmp + '/' + str(len_tmp) + ' '
- elif 'set' in srcdest_json:
- if isinstance(srcdest_json['set'][0],str):
- srcdest += 'port ' + str(srcdest_json['set'][0]) + ' '
- else:
- port_range = srcdest_json['set'][0]['range']
- srcdest += 'port ' + str(port_range[0]) + '-' + str(port_range[1]) + ' '
-
+ srcdests = []
tran_addr = ''
- tran_addr_json = dict_search('snat.addr' if args.source else 'dnat.addr', data['expr'][3])
- if tran_addr_json:
- if isinstance(tran_addr_json,str):
- tran_addr = tran_addr_json
- elif 'prefix' in tran_addr_json:
- addr_tmp = dict_search('snat.addr.prefix.addr' if args.source else 'dnat.addr.prefix.addr', data['expr'][3])
- len_tmp = dict_search('snat.addr.prefix.len' if args.source else 'dnat.addr.prefix.len', data['expr'][3])
- if addr_tmp and len_tmp:
- tran_addr = addr_tmp + '/' + str(len_tmp)
- else:
- if 'masquerade' in data['expr'][3]:
- tran_addr = 'masquerade'
- elif 'log' in data['expr'][3]:
- continue
-
- tran_port = dict_search('snat.port' if args.source else 'dnat.port', data['expr'][3])
- if tran_port:
- tran_addr += ' port ' + str(tran_port)
+ for i in range(1,len(data['expr']) + 1):
+ srcdest_json = dict_search('match.right', data['expr'][i])
+ if srcdest_json:
+ if isinstance(srcdest_json,str):
+ if srcdest != '':
+ srcdests.append(srcdest)
+ srcdest = ''
+ srcdest = srcdest_json + ' '
+ elif 'prefix' in srcdest_json:
+ addr_tmp = dict_search('match.right.prefix.addr', data['expr'][i])
+ len_tmp = dict_search('match.right.prefix.len', data['expr'][i])
+ if addr_tmp and len_tmp:
+ srcdest = addr_tmp + '/' + str(len_tmp) + ' '
+ elif 'set' in srcdest_json:
+ if isinstance(srcdest_json['set'][0],int):
+ srcdest += 'port ' + str(srcdest_json['set'][0]) + ' '
+ else:
+ port_range = srcdest_json['set'][0]['range']
+ srcdest += 'port ' + str(port_range[0]) + '-' + str(port_range[1]) + ' '
+
+ tran_addr_json = dict_search('snat' if args.source else 'dnat', data['expr'][i])
+ if tran_addr_json:
+ if isinstance(tran_addr_json['addr'],str):
+ tran_addr += tran_addr_json['addr'] + ' '
+ elif 'prefix' in tran_addr_json['addr']:
+ addr_tmp = dict_search('snat.addr.prefix.addr' if args.source else 'dnat.addr.prefix.addr', data['expr'][3])
+ len_tmp = dict_search('snat.addr.prefix.len' if args.source else 'dnat.addr.prefix.len', data['expr'][3])
+ if addr_tmp and len_tmp:
+ tran_addr += addr_tmp + '/' + str(len_tmp) + ' '
+
+ if isinstance(tran_addr_json['port'],int):
+ tran_addr += 'port ' + tran_addr_json['port']
+
+ else:
+ if 'masquerade' in data['expr'][i]:
+ tran_addr = 'masquerade'
+ elif 'log' in data['expr'][i]:
+ continue
- print(format_nat_rule.format(rule, srcdest, tran_addr, interface))
+ if srcdest != '':
+ srcdests.append(srcdest)
+ srcdest = ''
+ print(format_nat_rule.format(rule, srcdests[0], tran_addr, interface))
+
+ for i in range(1, list(srcdest)):
+ print(format_nat_rule.format(' ', srcdests[i], ' ', ' '))
exit(0)
else:
diff --git a/src/op_mode/show_system_integrity.py b/src/op_mode/show_system_integrity.py
deleted file mode 100755
index c34d41e80..000000000
--- a/src/op_mode/show_system_integrity.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2020 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 sys
-import os
-import re
-import json
-from datetime import datetime, timedelta
-
-version_file = r'/usr/share/vyos/version.json'
-
-
-def _get_sys_build_version():
- if not os.path.exists(version_file):
- return None
- buf = open(version_file, 'r').read()
- j = json.loads(buf)
- if not 'built_on' in j:
- return None
- return datetime.strptime(j['built_on'], '%a %d %b %Y %H:%M %Z')
-
-
-def _check_pkgs(build_stamp):
- pkg_diffs = {
- 'buildtime': str(build_stamp),
- 'pkg': {}
- }
-
- pkg_info = os.listdir('/var/lib/dpkg/info/')
- for file in pkg_info:
- if re.search('\.list$', file):
- fts = os.stat('/var/lib/dpkg/info/' + file).st_mtime
- dt_str = (datetime.utcfromtimestamp(
- fts).strftime('%Y-%m-%d %H:%M:%S'))
- fdt = datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
- if fdt > build_stamp:
- pkg_diffs['pkg'].update(
- {str(re.sub('\.list', '', file)): str(fdt)})
-
- if len(pkg_diffs['pkg']) != 0:
- return pkg_diffs
- else:
- return None
-
-
-if __name__ == '__main__':
- built_date = _get_sys_build_version()
- if not built_date:
- sys.exit(1)
- pkgs = _check_pkgs(built_date)
- if pkgs:
- print (
- "The following packages don\'t fit the image creation time\nbuild time:\t" + pkgs['buildtime'])
- for k, v in pkgs['pkg'].items():
- print ("installed: " + v + '\t' + k)
diff --git a/src/op_mode/wireguard_client.py b/src/op_mode/wireguard_client.py
index 7661254da..76c1ff7d1 100755
--- a/src/op_mode/wireguard_client.py
+++ b/src/op_mode/wireguard_client.py
@@ -39,10 +39,11 @@ To enable this configuration on a VyOS router you can use the following commands
set interfaces wireguard {{ interface }} peer {{ name }} allowed-ips '{{ addr }}'
{% endfor %}
set interfaces wireguard {{ interface }} peer {{ name }} public-key '{{ pubkey }}'
+
+=== RoadWarrior (client) configuration ===
"""
client_config = """
-=== RoadWarrior (client) configuration ===
[Interface]
PrivateKey = {{ privkey }}
diff --git a/src/systemd/opennhrp.service b/src/systemd/opennhrp.service
index 70235f89d..c9a44de29 100644
--- a/src/systemd/opennhrp.service
+++ b/src/systemd/opennhrp.service
@@ -6,8 +6,8 @@ StartLimitIntervalSec=0
[Service]
Type=forking
-ExecStart=/usr/sbin/opennhrp -d -v -a /run/opennhrp.socket -c /run/opennhrp/opennhrp.conf -s /etc/opennhrp/opennhrp-script.py -p /run/opennhrp.pid
+ExecStart=/usr/sbin/opennhrp -d -v -a /run/opennhrp.socket -c /run/opennhrp/opennhrp.conf -s /etc/opennhrp/opennhrp-script.py -p /run/opennhrp/opennhrp.pid
ExecReload=/usr/bin/kill -HUP $MAINPID
-PIDFile=/run/opennhrp.pid
+PIDFile=/run/opennhrp/opennhrp.pid
Restart=on-failure
RestartSec=20
diff --git a/src/validators/bgp-large-community-list b/src/validators/bgp-large-community-list
new file mode 100755
index 000000000..c07268e81
--- /dev/null
+++ b/src/validators/bgp-large-community-list
@@ -0,0 +1,36 @@
+#!/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 re
+import sys
+
+from vyos.template import is_ipv4
+
+pattern = '(.*):(.*):(.*)'
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ sys.exit(1)
+
+ value = sys.argv[1].split(':')
+ if not len(value) == 3:
+ sys.exit(1)
+
+ if not (re.match(pattern, sys.argv[1]) and
+ (is_ipv4(value[0]) or value[0].isdigit()) and value[1].isdigit()):
+ sys.exit(1)
+
+ sys.exit(0)
diff --git a/src/validators/bgp-route-target b/src/validators/bgp-route-target
new file mode 100755
index 000000000..e7e4d403f
--- /dev/null
+++ b/src/validators/bgp-route-target
@@ -0,0 +1,51 @@
+#!/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/>.
+
+from argparse import ArgumentParser
+from vyos.template import is_ipv4
+
+parser = ArgumentParser()
+group = parser.add_mutually_exclusive_group()
+group.add_argument('--single', action='store', help='Validate and allow only one route-target')
+group.add_argument('--multi', action='store', help='Validate multiple, whitespace separated route-targets')
+args = parser.parse_args()
+
+def is_valid_rt(rt):
+ # every route target needs to have a colon and must consists of two parts
+ value = rt.split(':')
+ if len(value) != 2:
+ return False
+ # A route target must either be only numbers, or the first part must be an
+ # IPv4 address
+ if (is_ipv4(value[0]) or value[0].isdigit()) and value[1].isdigit():
+ return True
+ return False
+
+if __name__ == '__main__':
+ if args.single:
+ if not is_valid_rt(args.single):
+ exit(1)
+
+ elif args.multi:
+ for rt in args.multi.split(' '):
+ if not is_valid_rt(rt):
+ exit(1)
+
+ else:
+ parser.print_help()
+ exit(1)
+
+ exit(0)